Agh ok do a bunch of stuff

This commit is contained in:
Bill Rossi 2025-08-23 14:38:42 -04:00
parent f72eeb3528
commit 661d0f3f9a
13 changed files with 246 additions and 56 deletions

7
ika.rb
View File

@ -1,8 +1,13 @@
require 'discordrb' require 'discordrb'
require_relative './lib/ika' require_relative './lib/ika'
require_relative './lib/discord_handler'
require_relative './lib/console_handler'
token = File.read("./token") token = File.read("./token")
ika = Ika.new Discordrb::Bot.new(token:) bot = Discordrb::Bot.new(token:)
# ika = Ika.for(type: DiscordHandler, bot:)
ika = Ika.for(type: ConsoleHandler)
ika.start! ika.start!

View File

@ -16,7 +16,7 @@ module Commands
def self.for(ika, message) def self.for(ika, message)
Commands.registered_commands.find do |command_class| Commands.registered_commands.find do |command_class|
command_class.matches? message.message.content command_class.matches? message.content
end&.new(ika, message) end&.new(ika, message)
end end

View File

@ -12,6 +12,7 @@ module Commands
return message.respond("There's already a lesson running!") if ika.current_lesson_running? return message.respond("There's already a lesson running!") if ika.current_lesson_running?
message.respond("Starting a lesson now!") message.respond("Starting a lesson now!")
ika.start_lesson! message ika.start_lesson! message
end end
end end

19
lib/console_handler.rb Normal file
View File

@ -0,0 +1,19 @@
require_relative './ika'
class ConsoleHandler < Ika
def start!
@handling_messages = true
while @handling_messages
handle_message Message::Console.new(responder(nil), gets.chomp)
end
end
def stop!
@handling_messages = false
end
def responder(_)
lambda { |response| puts "<Ika> #{response}" }
end
end

28
lib/discord_handler.rb Normal file
View File

@ -0,0 +1,28 @@
require_relative './ika'
class DiscordHandler < Ika
attr_reader :bot
def initialize(bot:)
super()
@bot = bot
end
def start!
bot.remove_handler @message_handler if @message_handler
@message_handler = bot.message do |message_event|
handle_message Message::Discord.new(responder(message_event.channel), message_event.message)
end
bot.run # you can run this in the background, idk
end
def stop!
bot.remove_handler @message_handler if @message_handler
end
def responder(channel)
lambda { |response| channel.send_message(response) }
end
end

View File

@ -1,32 +1,48 @@
class Drill class Drill
COMMANDS = %w[
init
start
end
]
attr_reader :channel attr_reader :channel
def initialize(channel) def initialize(channel)
@channel = channel @channel = channel
@exists = false
@started = false @started = false
end end
def init!
@exists = true
end
def start! def start!
@started = true @started = true
end end
def end!
@started = false
end
def handle_message(message)
message.command_message ? handle_command(message) : handle_normal_message(message)
end
def handle_command(message)
command = message.command
if COMMANDS.includes?(command)
send("handle_#{command}", message)
else
puts "[Drill] Unknown command #{command}"
end
end
def started? def started?
@started @started
end end
def exists? def exists?
true @exists
end
class Empty < Drill
def initialize
super(nil)
end
def start!; end
def exists?
false
end
end end
end end

View File

@ -2,16 +2,14 @@ require_relative "drill"
class DrillPlugin class DrillPlugin
COMMANDS = %w[ COMMANDS = %w[
init help
start
end
] ]
attr_reader :bot, :drills attr_reader :bot, :drills
def initialize(bot) def initialize(bot)
@bot = bot @bot = bot
@drills = Hash.new { Drill::Empty.new } @drills = Hash.new { Drill.new }
end end
def handle_message(message) def handle_message(message)
@ -24,7 +22,8 @@ class DrillPlugin
drill = drills[message.channel.id] drill = drills[message.channel.id]
send("handle_#{command}", message, drill) send("handle_#{command}", message, drill)
else else
message.respond "Unknown command #{command}" drill = drills[message.channel.id]
drill.handle_message(message)
end end
end end

View File

@ -1,42 +1,33 @@
require_relative './session' require_relative './session'
require_relative './lesson' require_relative './lesson'
require_relative './commands' require_relative './commands'
require_relative './message'
require_relative './drill_plugin' require_relative './drill_plugin'
class Ika class Ika
attr_reader :bot attr_reader :handler
attr_reader :lessons, :sessions attr_reader :lessons, :sessions
attr_accessor :current_lesson, :current_session attr_accessor :current_lesson, :current_session
attr_reader :drill_plugin attr_reader :drill_plugin
def initialize(bot) def self.for(type:, **kwargs)
@bot = bot type.new **kwargs
end
def initialize
@lessons = {} @lessons = {}
@sessions = {} @sessions = {}
@current_session = nil @current_session = nil
@current_lesson = Lesson.new @current_lesson = Lesson.new(responder: responder(nil))
@drill_plugin = DrillPlugin.new(self) @drill_plugin = DrillPlugin.new(self)
end end
def start!
bot.remove_handler @message_handler if @message_handler
@message_handler = bot.message do |message|
handle_message message
end
bot.run # you can run this in the background, idk
end
def stop!
bot.remove_handler @message_handler if @message_handler
end
def current_lesson_running? def current_lesson_running?
current_lesson.running? current_lesson.running?
end end
def start_lesson!(message) def start_lesson!(message)
current_lesson.responder = responder(message.channel)
current_lesson.start!(message.channel) current_lesson.start!(message.channel)
end end
@ -49,10 +40,6 @@ class Ika
command.execute command.execute
end end
if message.content.start_with? "!drill" # drill_plugin.handle_message message
drill_plugin.handle_message message
end
return current_session&.respond_to message
end end
end end

View File

@ -8,12 +8,14 @@ DEFAULT_LESSON_PLAN = [
] ]
class Lesson class Lesson
attr_reader :lesson_plan, :channel, :thread, :running, :scheduler attr_reader :lesson_plan, :channel, :running, :scheduler
attr_accessor :responder
def initialize(lesson_plan=DEFAULT_LESSON_PLAN, scheduler: Rufus::Scheduler.new) def initialize(lesson_plan=DEFAULT_LESSON_PLAN, scheduler: Rufus::Scheduler.new, responder: nil)
@lesson_plan = lesson_plan @lesson_plan = lesson_plan
@running = false @running = false
@scheduler = scheduler @scheduler = scheduler
@responder = responder
end end
def stop! def stop!
@ -25,13 +27,13 @@ class Lesson
offset = lesson_plan.map(&:first)[0..index - 1].sum(0) offset = lesson_plan.map(&:first)[0..index - 1].sum(0)
offset = 0 if index == 0 offset = 0 if index == 0
scheduler.in "#{offset}m" do scheduler.in "#{offset}m" do
channel.send_message "#{time} minutes to #{message}" responder.call "#{time} minutes to #{message}"
end end
end end
end_offset = lesson_plan.map(&:first).sum(0) end_offset = lesson_plan.map(&:first).sum(0)
scheduler.in "#{end_offset}m" do scheduler.in "#{end_offset}m" do
channel.send_message "Lesson over!" responder.call "Lesson over!"
@running = false @running = false
end end

109
lib/message.rb Normal file
View File

@ -0,0 +1,109 @@
class Message
attr_reader :responder
def initialize(responder)
@responder = responder
end
def content
# TODO: figure out how to delegate
discord_message.content
end
def author
# TODO: figure out how to delegate
discord_message.author
end
def channel
# TODO: figure out how to delegate
discord_message.channel
end
def respond(response)
# TODO: figure out how to delegate
discord_message.respond response
end
def message
discord_message
end
def words
content.split(" ")
end
def first_word
words.first
end
def command_message?
first_word.start_with? "!"
end
def command
command_message? ? first_word[1..] : nil
end
def subcommand
command_message? ? words[1] : nil
end
def params
command_message? ? words[2..] : []
end
class Console < Message
attr_reader :content
def initialize(responder, content)
super(responder)
@content = content
end
def author
OpenStruct.new(display_name: "CHANGE ME")
end
def channel
OpenStruct.new(id: nil)
end
def respond(response)
responder.call response
end
end
class Discord < Message
attr_reader :discord_message
def initialize(responder, discord_message)
super(responder)
@discord_message = discord_message
end
def content
# TODO: figure out how to delegate
discord_message.content
end
def author
# TODO: figure out how to delegate
discord_message.author
end
def channel
# TODO: figure out how to delegate
discord_message.channel
end
def respond(response)
# TODO: figure out how to delegate
discord_message.respond response
end
def message
discord_message
end
end
end

View File

@ -0,0 +1,15 @@
require_relative "../lib/discord_handler"
require "minitest/autorun"
class TestDiscordHandler < Minitest::Test
def setup
@bot = Minitest::Mock.new
@ika = DiscordHandler.new bot: @bot
end
def test_start!
@bot.expect(:message, nil)
@bot.expect(:run, nil)
@ika.start!
end
end

View File

@ -1,16 +1,21 @@
require_relative "../lib/ika" require_relative "../lib/ika"
require "minitest/autorun" require "minitest/autorun"
class TestIka < Minitest::Test class TestHandler < Ika
def setup attr_reader :responses
@bot = Minitest::Mock.new
@ika = Ika.new @bot def initialize
@responses = []
end end
def test_start def responder
@bot.expect(:message, nil) lambda { |response| @responses << response }
@bot.expect(:run, nil) end
@ika.start! end
class TestIka < Minitest::Test
def setup
@ika = TestHandler.new
end end
def test_handle_command_message def test_handle_command_message
@ -19,6 +24,7 @@ class TestIka < Minitest::Test
Commands::Command.stub(:for, @command) do |x| Commands::Command.stub(:for, @command) do |x|
@ika.handle_message("msg") @ika.handle_message("msg")
end end
assert_equal [], @ika.responses
end end
def test_handle_normal_message def test_handle_normal_message
@ -30,5 +36,6 @@ class TestIka < Minitest::Test
@ika.handle_message("msg") @ika.handle_message("msg")
end end
end end
assert_equal [], @ika.responses
end end
end end

View File

@ -4,10 +4,12 @@ require "minitest/autorun"
class TestLesson < Minitest::Test class TestLesson < Minitest::Test
def setup def setup
@scheduler = Minitest::Mock.new @scheduler = Minitest::Mock.new
@responses = []
@responder = lambda { |rsp| @responses << rsp }
end end
def test_start def test_start
@lesson = Lesson.new [[1, "test the thing"], [3, "finish testing"]], scheduler: @scheduler @lesson = Lesson.new [[1, "test the thing"], [3, "finish testing"]], scheduler: @scheduler, responder: @responder
@scheduler.expect(:in, nil) { |time| time == "0m" } @scheduler.expect(:in, nil) { |time| time == "0m" }
@scheduler.expect(:in, nil) { |time| time == "1m" } @scheduler.expect(:in, nil) { |time| time == "1m" }
@scheduler.expect(:in, nil) { |time| time == "4m" } @scheduler.expect(:in, nil) { |time| time == "4m" }