MetalAdventures/src/discord/scenes_plugin.rb

105 lines
2.7 KiB
Ruby

require "rubygems/text"
class MetalAdventuresDiscord::ScenesPlugin
include Gem::Text # #levenshtein_distance/2
def initialize(bot)
@bot = bot
@playing = {}
hook_scene!
end
def hook_scene!
@bot.message(with_text: /^!scene.+/) do |event|
handle_scene(event)
end
@bot.message(with_message: /^[^!]/) do |event|
handle_not_command(event)
end
end
def _error_invalid_scene_syntax
<<EOF
Invalid syntax (!scene <action> [params]).
Action can be:
- **start**: start a new session. impossible if another scene is already started on the current channel
- **stop**: close the current scene, stop the bot from asking things
EOF
end
def _error_not_implemented(method)
"Not implemented: #{self.class}##{method}"
end
def handle_scene(event)
match = event.content.match(/^!scene (?<event_name>start|stop) (?<params>.+)/)
if match.nil?
event.message.respond _error_invalid_scene_syntax
return nil
end
event_handler = "handle_event_#{match['event_name']}"
if !respond_to?(event_handler)
event.message.respond _error_not_implemented(event_handler)
logger.error _error_not_implemented(event_handler)
return nil
end
send(event_handler, event, match["params"])
end
def handle_event_start(event, params)
if @playing[event.message.channel.id]
event.message.respond "Scene #{@playing[event.message.channel.id].name} already running"
return nil
end
new_scene = MetalAdventures::Scene.load!(params)
@playing[event.message.channel.id] = new_scene
run_current_action(event)
end
def handle_event_stop(_event, _match)
@playing.delete event.message.channel.id
end
# handle all message that are not a !command
# while we are playing on the channel
def handle_not_command(event)
return if !@playing[event.message.channel.id]
scene = current_scene(event)
if event.message.content == "next" || event.message.content.downcase.end_with?(scene.current_action.name.downcase)
scene.next!
run_current_action(event)
end
end
def _options_strings(scene)
scene.current_action.options.map { _option_string(_1) }
end
def _option_string(option)
"- **#{option.name}** (#{option.duration}): compétence #{option.skill}"
end
def _scene_current_action(scene)
<<EOF
Action en cours à jouer: **#{scene.current_action.name}**.
Executez une option avec un jet de dès du même nom:
#{_options_strings(scene).join("\n")}
EOF
end
# do the bot job for the curren action
def run_current_action(event)
scene = current_scene(event)
event.message.respond _scene_current_action(scene)
end
private def current_scene(event)
@playing[event.message.channel.id]
end
end