179 lines
5.0 KiB
Ruby
179 lines
5.0 KiB
Ruby
require "yaml"
|
|
|
|
# Refs handles rules as written
|
|
class MetalAdventuresDiscord::RefsPlugin
|
|
include Gem::Text # #levenshtein_distance/2
|
|
|
|
def initialize(bot)
|
|
@bot = bot
|
|
@ref_cache = {}
|
|
hook_ref!
|
|
hook_refs!
|
|
end
|
|
|
|
REF_HOOK_SPECIAL = {
|
|
"short" => "short",
|
|
"court" => "short",
|
|
"long" => "long",
|
|
"ref" => "ref",
|
|
"page" => "ref",
|
|
"full" => "full",
|
|
"tout" => "full",
|
|
}.freeze
|
|
|
|
# !refs will generate a few messages with a component that shows actions (by chunks of 25 rules)
|
|
def hook_refs!
|
|
@bot.message(with_text: /^!refs$/) do |event|
|
|
list_refs.each_slice(25) do |refs_slice|
|
|
event.message.reply!(
|
|
"Recherche de règles (#{refs_slice.first} - #{refs_slice.last})",
|
|
# components: _components_search_refs,
|
|
components: _components_search_list(refs_slice),
|
|
)
|
|
end
|
|
end
|
|
|
|
@bot.interaction_create do |event|
|
|
values = event.interaction.data["values"] # TODO: pattern matching for destructuration
|
|
custom_id = event.interaction.data["custom_id"]
|
|
if custom_id == "class_select_ref" && values.size > 0
|
|
values.each do |ref_name|
|
|
begin
|
|
ref = load_ref(name: ref_name)
|
|
event.channel.send_embed "", ref_to_embed(event, ref, "full")
|
|
rescue StandardError => _e
|
|
event.channel.send_embed "", _err_invalid_ref_embed(ref_name)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
# !ref short blablabla
|
|
# !ref full blablabla
|
|
# !ref blablabla
|
|
# event.message.reply! "Yo frèro", embed: { image: { url: event.user.avatar_url } }
|
|
def hook_ref!
|
|
@bot.message(with_text: /!ref .+/) do |event|
|
|
match = event.message.content.match(/\A!ref (?<total>(?<modifier>\w+ )?(?<nomodifier>.+))/)
|
|
ref_name = match["total"]
|
|
|
|
display_choice = nil
|
|
modifier = match && match["modifier"].to_s.rstrip
|
|
if REF_HOOK_SPECIAL[modifier]
|
|
display_choice = modifier
|
|
ref_name = match["nomodifier"]
|
|
end
|
|
|
|
begin
|
|
ref = load_ref(name: ref_name)
|
|
event.message.reply! "", embed: ref_to_embed(event, ref, display_choice)
|
|
rescue StandardError => _e
|
|
event.message.reply! "", embed: _err_invalid_ref_embed(ref_name)
|
|
end
|
|
end
|
|
end
|
|
|
|
def list_refs
|
|
Dir.glob("scenes/actions/*.yaml").map { _1.tr('_', ' ').split('/').last.split('.').first }
|
|
end
|
|
|
|
# TODO: not working yet
|
|
# generate a text input
|
|
def _components_search_refs
|
|
[
|
|
{
|
|
"type" => 1,
|
|
"components" => [
|
|
{
|
|
"type" => 4,
|
|
"custom_id" => "search_refs_field",
|
|
"label" => "Text to search",
|
|
"style" => 1,
|
|
# "min_length" => 0,
|
|
# "max_length" => 80,
|
|
# "placeholder" => "Courir",
|
|
# "required" => true,
|
|
},
|
|
],
|
|
},
|
|
]
|
|
end
|
|
|
|
# Generate a menu to show all refs
|
|
def _components_search_list(refs)
|
|
[
|
|
{
|
|
"type" => 1,
|
|
"components" => [
|
|
{
|
|
"type" => 3,
|
|
"custom_id" => "class_select_ref",
|
|
"options" => refs.map { { "label" => _1, "value" => _1, "description" => _1, } },
|
|
"placeholder" => "Reference à afficher",
|
|
"min_values" => 1,
|
|
"max_values" => 1,
|
|
},
|
|
],
|
|
},
|
|
]
|
|
end
|
|
|
|
def _err_invalid_ref_embed(ref)
|
|
{
|
|
color: 0xFF0000,
|
|
title: "Error: invalid ref \"#{ref}\"",
|
|
description: "!roll [full/short/ref/long] name of the page",
|
|
}
|
|
end
|
|
|
|
# Load an existing ref by filename or name.
|
|
# It will cache without TTL the result to fasten the operation by default.
|
|
def load_ref(filename: nil, name: nil, cache: true)
|
|
filename = "#{name.downcase.tr(' ', '_')}.yaml" if name && !filename
|
|
if cache
|
|
@ref_cache[filename] ||= YAML.load_file("scenes/actions/#{filename}")
|
|
else
|
|
YAML.load_file("scenes/actions/#{filename}")
|
|
end
|
|
end
|
|
|
|
DURATIONS = { "S" => "Simple", "C" => "Complexe", "G" => "Gratuite", nil => "Spéciale" }.freeze
|
|
REFS = {
|
|
"MJ1" => "Manuel du Joueur 1.0",
|
|
"MJ" => "Manuel du Joueur 1.5",
|
|
"MM" => "Manuel du Meneur",
|
|
"PP" => "Prise et Profits",
|
|
"FS" => "Fer et Sang",
|
|
"PE" => "Pirates de l'Espace",
|
|
"MA" => "Mutant Apocalypse",
|
|
}.freeze
|
|
|
|
# Generate a discord embed for the ref.
|
|
# Several formats of ref are available (see the constant {REFS})
|
|
def ref_to_embed(_event, ref, display_choice)
|
|
description =
|
|
case display_choice
|
|
when "full"
|
|
[ref['long'], "_#{ref['description']}_"].join("\n\n")
|
|
when "short"
|
|
ref['short']
|
|
when "long"
|
|
ref['long']
|
|
when "ref"
|
|
ref_manual, ref_page = ref['ref'].split(" ")
|
|
"#{REFS[ref_manual]}, page #{ref_page}"
|
|
else
|
|
ref['short'] || ref['long'] || "Pas de données"
|
|
end
|
|
|
|
duration = DURATIONS[ref['duration']]
|
|
with_infos = ["**Compétence**: #{ref['skill']}", "**Durée**: #{duration}", description].join("\n\n")
|
|
|
|
{
|
|
title: "#{ref['name']} (#{ref['ref']})",
|
|
description: with_infos,
|
|
}
|
|
end
|
|
end
|