mirror of
https://github.com/arthur-pbty/shadowbot.git
synced 2026-06-03 23:36:25 +02:00
feat: ajouter la gestion des commandes d'aide avec alias et améliorer l'affichage des informations de commande
This commit is contained in:
@@ -1,17 +1,17 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use serenity::builder::{
|
use serenity::builder::{
|
||||||
CreateActionRow, CreateButton, CreateCommand, CreateEmbed, CreateInteractionResponse,
|
CreateActionRow, CreateButton, CreateCommand, CreateCommandOption, CreateEmbed,
|
||||||
CreateInteractionResponseMessage, CreateMessage, CreateSelectMenu, CreateSelectMenuKind,
|
CreateInteractionResponse, CreateInteractionResponseMessage, CreateMessage, CreateSelectMenu,
|
||||||
CreateSelectMenuOption,
|
CreateSelectMenuKind, CreateSelectMenuOption,
|
||||||
};
|
};
|
||||||
use serenity::model::application::{
|
use serenity::model::application::{
|
||||||
Command, CommandInteraction, ComponentInteractionDataKind, Interaction,
|
Command, CommandInteraction, CommandOptionType, ComponentInteractionDataKind, Interaction,
|
||||||
|
ResolvedValue,
|
||||||
};
|
};
|
||||||
use serenity::model::prelude::*;
|
use serenity::model::prelude::*;
|
||||||
use serenity::prelude::*;
|
use serenity::prelude::*;
|
||||||
|
|
||||||
use crate::commands::alias::resolve_alias;
|
|
||||||
use crate::commands::common::truncate_text;
|
use crate::commands::common::truncate_text;
|
||||||
use crate::db::{
|
use crate::db::{
|
||||||
DbPoolKey, get_help_aliases_enabled, get_help_perms_enabled, get_help_type,
|
DbPoolKey, get_help_aliases_enabled, get_help_perms_enabled, get_help_type,
|
||||||
@@ -448,6 +448,28 @@ fn help_lookup_to_key(input: &str) -> Option<&'static str> {
|
|||||||
matched.or_else(|| help_metadata_lookup_key(input))
|
matched.or_else(|| help_metadata_lookup_key(input))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolve_help_command_key(input: &str, alias_map: &BTreeMap<String, Vec<String>>) -> Option<String> {
|
||||||
|
if let Some(key) = help_lookup_to_key(input) {
|
||||||
|
return Some(key.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(key) = help_metadata_lookup_key(input) {
|
||||||
|
return Some(key.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
let normalized = help_lookup_key(input);
|
||||||
|
if normalized.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
alias_map.iter().find_map(|(command, aliases)| {
|
||||||
|
aliases
|
||||||
|
.iter()
|
||||||
|
.any(|alias| help_lookup_key(alias).eq_ignore_ascii_case(&normalized))
|
||||||
|
.then(|| command.clone())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn help_page_index(key: &str) -> Option<usize> {
|
fn help_page_index(key: &str) -> Option<usize> {
|
||||||
HELP_PAGES
|
HELP_PAGES
|
||||||
.iter()
|
.iter()
|
||||||
@@ -795,10 +817,93 @@ fn parse_help_component_id(custom_id: &str) -> Option<(&str, u64, Option<usize>)
|
|||||||
Some((kind, owner_id, page))
|
Some((kind, owner_id, page))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn build_command_help_embed(
|
||||||
|
ctx: &Context,
|
||||||
|
state: &HelpState,
|
||||||
|
alias_map: &BTreeMap<String, Vec<String>>,
|
||||||
|
key: &str,
|
||||||
|
) -> Option<CreateEmbed> {
|
||||||
|
let doc = command_doc(key)?;
|
||||||
|
|
||||||
|
let aliases = doc
|
||||||
|
.alias_source_key
|
||||||
|
.and_then(|alias_key| alias_map.get(alias_key))
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let alias_text = if aliases.is_empty() {
|
||||||
|
"Aucun alias".to_string()
|
||||||
|
} else {
|
||||||
|
aliases
|
||||||
|
.iter()
|
||||||
|
.map(|alias| format!("`{}`", alias))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ")
|
||||||
|
};
|
||||||
|
|
||||||
|
let examples = doc
|
||||||
|
.examples
|
||||||
|
.iter()
|
||||||
|
.map(|ex| format!("`{}`", ex))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n");
|
||||||
|
|
||||||
|
let mut embed = CreateEmbed::new()
|
||||||
|
.title(format!("Aide commande · +{}", doc.command.replace('_', " ")))
|
||||||
|
.description(doc.description)
|
||||||
|
.field(
|
||||||
|
"Commande",
|
||||||
|
format!("`+{}`", doc.command.replace('_', " ")),
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.field("Clé ACL", format!("`{}`", doc.key), false)
|
||||||
|
.field("Catégorie", help_page_title_for_command_key(doc.key), false)
|
||||||
|
.field("Alias", alias_text, false)
|
||||||
|
.field("Paramètres", doc.params, false)
|
||||||
|
.field(
|
||||||
|
"Disponible en DM",
|
||||||
|
if doc.allow_in_dm { "Oui" } else { "Non" },
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
.field("Exemples", truncate_text(&examples, 1024), false);
|
||||||
|
|
||||||
|
if state.perms_enabled {
|
||||||
|
embed = embed.field(
|
||||||
|
"Permission",
|
||||||
|
permission_level_description(doc.default_permission),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(embed.color(crate::commands::common::theme_color(ctx).await))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn slash_help_input(command: &CommandInteraction) -> Option<String> {
|
||||||
|
command
|
||||||
|
.data
|
||||||
|
.options()
|
||||||
|
.into_iter()
|
||||||
|
.find(|option| option.name == "commande")
|
||||||
|
.and_then(|option| match option.value {
|
||||||
|
ResolvedValue::String(value) => Some(value.trim().to_string()),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.filter(|value| !value.is_empty())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn register_slash_help(ctx: &Context) {
|
pub async fn register_slash_help(ctx: &Context) {
|
||||||
let _ = Command::create_global_command(
|
let _ = Command::create_global_command(
|
||||||
&ctx.http,
|
&ctx.http,
|
||||||
CreateCommand::new("help").description("Affiche l'aide du bot"),
|
CreateCommand::new("help")
|
||||||
|
.description("Affiche l'aide du bot")
|
||||||
|
.add_option(
|
||||||
|
CreateCommandOption::new(
|
||||||
|
CommandOptionType::String,
|
||||||
|
"commande",
|
||||||
|
"Commande, alias ou categorie/page d'aide",
|
||||||
|
)
|
||||||
|
.required(false),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@@ -806,10 +911,41 @@ pub async fn register_slash_help(ctx: &Context) {
|
|||||||
pub async fn handle_help_slash(ctx: &Context, command: &CommandInteraction) {
|
pub async fn handle_help_slash(ctx: &Context, command: &CommandInteraction) {
|
||||||
let state = current_help_state(ctx).await;
|
let state = current_help_state(ctx).await;
|
||||||
let alias_map = aliases_map(ctx).await;
|
let alias_map = aliases_map(ctx).await;
|
||||||
|
let input = slash_help_input(command);
|
||||||
|
|
||||||
|
if let Some(value) = input.as_deref() {
|
||||||
|
let resolved_key = resolve_help_command_key(value, &alias_map).or_else(|| {
|
||||||
|
value
|
||||||
|
.split_whitespace()
|
||||||
|
.next()
|
||||||
|
.and_then(|first| resolve_help_command_key(first, &alias_map))
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(key) = resolved_key {
|
||||||
|
if let Some(embed) = build_command_help_embed(ctx, &state, &alias_map, &key).await {
|
||||||
|
let _ = command
|
||||||
|
.create_response(
|
||||||
|
&ctx.http,
|
||||||
|
CreateInteractionResponse::Message(
|
||||||
|
CreateInteractionResponseMessage::new().embed(embed),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let view_pages = build_help_view_pages(&state, &alias_map);
|
let view_pages = build_help_view_pages(&state, &alias_map);
|
||||||
let avatar_url = bot_avatar_url(ctx);
|
let avatar_url = bot_avatar_url(ctx);
|
||||||
let embed = build_help_embed(0, &state, &view_pages, &avatar_url);
|
let page_index = input
|
||||||
let components = help_components(command.user.id, 0, &state, &view_pages);
|
.as_deref()
|
||||||
|
.and_then(help_page_from_input)
|
||||||
|
.map(|category_index| first_view_page_for_category(&view_pages, category_index))
|
||||||
|
.unwrap_or(0)
|
||||||
|
.min(view_pages.len().saturating_sub(1));
|
||||||
|
let embed = build_help_embed(page_index, &state, &view_pages, &avatar_url);
|
||||||
|
let components = help_components(command.user.id, page_index, &state, &view_pages);
|
||||||
|
|
||||||
let _ = command
|
let _ = command
|
||||||
.create_response(
|
.create_response(
|
||||||
@@ -896,82 +1032,11 @@ pub async fn handle_help(ctx: &Context, msg: &Message, args: &[&str]) {
|
|||||||
if !args.is_empty() {
|
if !args.is_empty() {
|
||||||
let joined = args.join(" ");
|
let joined = args.join(" ");
|
||||||
|
|
||||||
let mut resolved_key = help_lookup_to_key(&joined).map(|s| s.to_string());
|
let resolved_key = resolve_help_command_key(&joined, &alias_map)
|
||||||
if resolved_key.is_none() {
|
.or_else(|| resolve_help_command_key(args[0], &alias_map));
|
||||||
let first = args[0];
|
|
||||||
if let Some(key) = help_lookup_to_key(first) {
|
|
||||||
resolved_key = Some(key.to_string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if resolved_key.is_none() {
|
|
||||||
let alias_input = help_lookup_key(&joined).replace(' ', "_");
|
|
||||||
if let Some(alias_target) = resolve_alias(ctx, &alias_input).await {
|
|
||||||
resolved_key = Some(alias_target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if resolved_key.is_none() {
|
|
||||||
resolved_key = help_metadata_lookup_key(&joined).map(|key| key.to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(key) = resolved_key {
|
if let Some(key) = resolved_key {
|
||||||
if let Some(doc) = command_doc(&key) {
|
if let Some(embed) = build_command_help_embed(ctx, &state, &alias_map, &key).await {
|
||||||
let aliases = doc
|
|
||||||
.alias_source_key
|
|
||||||
.and_then(|alias_key| alias_map.get(alias_key))
|
|
||||||
.cloned()
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
let alias_text = if aliases.is_empty() {
|
|
||||||
"Aucun alias".to_string()
|
|
||||||
} else {
|
|
||||||
aliases
|
|
||||||
.iter()
|
|
||||||
.map(|alias| format!("`{}`", alias))
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(", ")
|
|
||||||
};
|
|
||||||
|
|
||||||
let examples = doc
|
|
||||||
.examples
|
|
||||||
.iter()
|
|
||||||
.map(|ex| format!("`{}`", ex))
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join("\n");
|
|
||||||
|
|
||||||
let mut embed = CreateEmbed::new()
|
|
||||||
.title(format!(
|
|
||||||
"Aide commande · +{}",
|
|
||||||
doc.command.replace('_', " ")
|
|
||||||
))
|
|
||||||
.description(doc.description)
|
|
||||||
.field(
|
|
||||||
"Commande",
|
|
||||||
format!("`+{}`", doc.command.replace('_', " ")),
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
.field("Clé ACL", format!("`{}`", doc.key), false)
|
|
||||||
.field("Catégorie", help_page_title_for_command_key(doc.key), false)
|
|
||||||
.field("Alias", alias_text, false)
|
|
||||||
.field("Paramètres", doc.params, false)
|
|
||||||
.field(
|
|
||||||
"Disponible en DM",
|
|
||||||
if doc.allow_in_dm { "Oui" } else { "Non" },
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
.field("Exemples", truncate_text(&examples, 1024), false);
|
|
||||||
|
|
||||||
if state.perms_enabled {
|
|
||||||
embed = embed.field(
|
|
||||||
"Permission",
|
|
||||||
permission_level_description(doc.default_permission),
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
embed = embed.color(crate::commands::common::theme_color(ctx).await);
|
|
||||||
|
|
||||||
let _ = msg
|
let _ = msg
|
||||||
.channel_id
|
.channel_id
|
||||||
.send_message(&ctx.http, CreateMessage::new().embed(embed))
|
.send_message(&ctx.http, CreateMessage::new().embed(embed))
|
||||||
@@ -1014,7 +1079,7 @@ impl crate::commands::command_contract::CommandSpec for HelpCommand {
|
|||||||
crate::commands::command_contract::CommandMetadata {
|
crate::commands::command_contract::CommandMetadata {
|
||||||
name: "help",
|
name: "help",
|
||||||
category: "permissions",
|
category: "permissions",
|
||||||
params: "[commande|page]",
|
params: "[commande|alias|page]",
|
||||||
description: "Affiche les pages daide du bot ou la fiche detaillee dune commande avec parametres, aliases et exemples.",
|
description: "Affiche les pages daide du bot ou la fiche detaillee dune commande avec parametres, aliases et exemples.",
|
||||||
examples: &["+help", "+hp", "+help help"],
|
examples: &["+help", "+hp", "+help help"],
|
||||||
default_aliases: &["hp"],
|
default_aliases: &["hp"],
|
||||||
|
|||||||
Reference in New Issue
Block a user