From 661d0f3f9a2cff6bda1c8a37f1c7cb65d7a4627a Mon Sep 17 00:00:00 2001 From: Bill Rossi Date: Sat, 23 Aug 2025 14:38:42 -0400 Subject: [PATCH] Agh ok do a bunch of stuff --- ika.rb | 7 ++- lib/commands/command.rb | 2 +- lib/commands/lesson_command.rb | 1 + lib/console_handler.rb | 19 ++++++ lib/discord_handler.rb | 28 +++++++++ lib/drill.rb | 42 +++++++++---- lib/drill_plugin.rb | 9 ++- lib/ika.rb | 33 +++------- lib/lesson.rb | 10 +-- lib/message.rb | 109 +++++++++++++++++++++++++++++++++ test/test_discord_handler.rb | 15 +++++ test/test_ika.rb | 23 ++++--- test/test_lesson.rb | 4 +- 13 files changed, 246 insertions(+), 56 deletions(-) create mode 100644 lib/console_handler.rb create mode 100644 lib/discord_handler.rb create mode 100644 lib/message.rb create mode 100644 test/test_discord_handler.rb diff --git a/ika.rb b/ika.rb index 996f820..ea96e51 100644 --- a/ika.rb +++ b/ika.rb @@ -1,8 +1,13 @@ require 'discordrb' require_relative './lib/ika' +require_relative './lib/discord_handler' +require_relative './lib/console_handler' 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! diff --git a/lib/commands/command.rb b/lib/commands/command.rb index f6f47c0..18cec65 100644 --- a/lib/commands/command.rb +++ b/lib/commands/command.rb @@ -16,7 +16,7 @@ module Commands def self.for(ika, message) Commands.registered_commands.find do |command_class| - command_class.matches? message.message.content + command_class.matches? message.content end&.new(ika, message) end diff --git a/lib/commands/lesson_command.rb b/lib/commands/lesson_command.rb index 2b849a6..71174c5 100644 --- a/lib/commands/lesson_command.rb +++ b/lib/commands/lesson_command.rb @@ -12,6 +12,7 @@ module Commands return message.respond("There's already a lesson running!") if ika.current_lesson_running? message.respond("Starting a lesson now!") + ika.start_lesson! message end end diff --git a/lib/console_handler.rb b/lib/console_handler.rb new file mode 100644 index 0000000..286f5c8 --- /dev/null +++ b/lib/console_handler.rb @@ -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 " #{response}" } + end +end diff --git a/lib/discord_handler.rb b/lib/discord_handler.rb new file mode 100644 index 0000000..3ebceb1 --- /dev/null +++ b/lib/discord_handler.rb @@ -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 diff --git a/lib/drill.rb b/lib/drill.rb index b4b0794..70a0668 100644 --- a/lib/drill.rb +++ b/lib/drill.rb @@ -1,32 +1,48 @@ class Drill + COMMANDS = %w[ + init + start + end + ] + attr_reader :channel def initialize(channel) @channel = channel + @exists = false @started = false end + def init! + @exists = true + end + def start! @started = true 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? @started end def exists? - true - end - - class Empty < Drill - def initialize - super(nil) - end - - def start!; end - - def exists? - false - end + @exists end end diff --git a/lib/drill_plugin.rb b/lib/drill_plugin.rb index fb78472..2189219 100644 --- a/lib/drill_plugin.rb +++ b/lib/drill_plugin.rb @@ -2,16 +2,14 @@ require_relative "drill" class DrillPlugin COMMANDS = %w[ - init - start - end + help ] attr_reader :bot, :drills def initialize(bot) @bot = bot - @drills = Hash.new { Drill::Empty.new } + @drills = Hash.new { Drill.new } end def handle_message(message) @@ -24,7 +22,8 @@ class DrillPlugin drill = drills[message.channel.id] send("handle_#{command}", message, drill) else - message.respond "Unknown command #{command}" + drill = drills[message.channel.id] + drill.handle_message(message) end end diff --git a/lib/ika.rb b/lib/ika.rb index d548f88..1d7a901 100644 --- a/lib/ika.rb +++ b/lib/ika.rb @@ -1,42 +1,33 @@ require_relative './session' require_relative './lesson' require_relative './commands' +require_relative './message' require_relative './drill_plugin' class Ika - attr_reader :bot + attr_reader :handler attr_reader :lessons, :sessions attr_accessor :current_lesson, :current_session attr_reader :drill_plugin - def initialize(bot) - @bot = bot + def self.for(type:, **kwargs) + type.new **kwargs + end + + def initialize @lessons = {} @sessions = {} @current_session = nil - @current_lesson = Lesson.new + @current_lesson = Lesson.new(responder: responder(nil)) @drill_plugin = DrillPlugin.new(self) 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? current_lesson.running? end def start_lesson!(message) + current_lesson.responder = responder(message.channel) current_lesson.start!(message.channel) end @@ -49,10 +40,6 @@ class Ika command.execute end - if message.content.start_with? "!drill" - drill_plugin.handle_message message - end - - return current_session&.respond_to message + # drill_plugin.handle_message message end end diff --git a/lib/lesson.rb b/lib/lesson.rb index 2c21ddd..bf896e7 100644 --- a/lib/lesson.rb +++ b/lib/lesson.rb @@ -8,12 +8,14 @@ DEFAULT_LESSON_PLAN = [ ] 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 @running = false @scheduler = scheduler + @responder = responder end def stop! @@ -25,13 +27,13 @@ class Lesson offset = lesson_plan.map(&:first)[0..index - 1].sum(0) offset = 0 if index == 0 scheduler.in "#{offset}m" do - channel.send_message "#{time} minutes to #{message}" + responder.call "#{time} minutes to #{message}" end end end_offset = lesson_plan.map(&:first).sum(0) scheduler.in "#{end_offset}m" do - channel.send_message "Lesson over!" + responder.call "Lesson over!" @running = false end diff --git a/lib/message.rb b/lib/message.rb new file mode 100644 index 0000000..34acd48 --- /dev/null +++ b/lib/message.rb @@ -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 diff --git a/test/test_discord_handler.rb b/test/test_discord_handler.rb new file mode 100644 index 0000000..997fbce --- /dev/null +++ b/test/test_discord_handler.rb @@ -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 diff --git a/test/test_ika.rb b/test/test_ika.rb index 587b93e..c687d9c 100644 --- a/test/test_ika.rb +++ b/test/test_ika.rb @@ -1,16 +1,21 @@ require_relative "../lib/ika" require "minitest/autorun" -class TestIka < Minitest::Test - def setup - @bot = Minitest::Mock.new - @ika = Ika.new @bot +class TestHandler < Ika + attr_reader :responses + + def initialize + @responses = [] end - def test_start - @bot.expect(:message, nil) - @bot.expect(:run, nil) - @ika.start! + def responder + lambda { |response| @responses << response } + end +end + +class TestIka < Minitest::Test + def setup + @ika = TestHandler.new end def test_handle_command_message @@ -19,6 +24,7 @@ class TestIka < Minitest::Test Commands::Command.stub(:for, @command) do |x| @ika.handle_message("msg") end + assert_equal [], @ika.responses end def test_handle_normal_message @@ -30,5 +36,6 @@ class TestIka < Minitest::Test @ika.handle_message("msg") end end + assert_equal [], @ika.responses end end diff --git a/test/test_lesson.rb b/test/test_lesson.rb index 7738510..fe66e51 100644 --- a/test/test_lesson.rb +++ b/test/test_lesson.rb @@ -4,10 +4,12 @@ require "minitest/autorun" class TestLesson < Minitest::Test def setup @scheduler = Minitest::Mock.new + @responses = [] + @responder = lambda { |rsp| @responses << rsp } end 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 == "1m" } @scheduler.expect(:in, nil) { |time| time == "4m" }