From 1a0a2ddb8aee7d1dee5edf704d5327e3e90f6b85 Mon Sep 17 00:00:00 2001 From: Mylloon Date: Sat, 2 Nov 2024 01:32:09 +0100 Subject: [PATCH] multi lang + subcommand support in help --- src/commands/misc/help.ts | 56 ++++++++++++++++++++++--------- src/utils/commands/help.ts | 68 +++++++++++++++++++++++++++++++++----- 2 files changed, 100 insertions(+), 24 deletions(-) diff --git a/src/commands/misc/help.ts b/src/commands/misc/help.ts index 6806d6f..a3811c3 100644 --- a/src/commands/misc/help.ts +++ b/src/commands/misc/help.ts @@ -9,7 +9,12 @@ import { import "../../modules/string"; import { getLocale, getLocalizations } from "../../utils/locales"; import { getFilename } from "../../utils/misc"; -import { goodDescription, goodName } from "../../utils/commands/help"; +import { + goodDescription, + goodName, + NameNotLocalized, + SubnameNotLocalized, +} from "../../utils/commands/help"; export default { scope: () => [], @@ -99,28 +104,49 @@ export default { }); } - // If a command is specified - // TODO: Check if the command exist in the context (guild) - // https://git.mylloon.fr/ConfrerieDuKassoulait/Botanique/issues/187 - const command = client.commands.list.get(desired_command); + const error = `${loc.get("c_help3")} \`${desired_command}\``; + + const [possible_command, possible_subcommand] = desired_command.split(" "); + + const command = NameNotLocalized(client, possible_command); if (!command) { - // Command don't exist - return interaction.reply({ - content: `${loc.get("c_help3")} \`${desired_command}\``, - ephemeral: true, - }); + return interaction.reply({ content: error, ephemeral: true }); } + const scope = client.commands.list.get(command.name)?.scope(); + if (scope!.length > 0 && scope?.find((id) => id === interaction.guildId) === undefined) { + // Command not available for the current guild + return interaction.reply({ content: error, ephemeral: true }); + } + + let subcommand = undefined; + if (possible_subcommand) { + subcommand = SubnameNotLocalized(command, possible_subcommand); + } else { + subcommand = null; + } + + if (!command || subcommand === undefined) { + // Sub/Command don't exist + return interaction.reply({ content: error, ephemeral: true }); + } + + // Loads the data according to the user's locals + const requestedName = + goodName(command, interaction.locale) + + (subcommand !== null ? " " + goodName(subcommand, interaction.locale) : ""); + const requestedDesc = goodDescription( + subcommand !== null ? subcommand : command, + interaction.locale, + ); + // Send information about the command return interaction.reply({ embeds: [ new EmbedBuilder() .setColor(Colors.Blurple) - .setTitle("`/" + goodName(command.data, interaction.locale) + "`") - .setDescription( - // Loads the description according to the user's locals - goodDescription(command.data, interaction.locale), - ), + .setTitle("`/" + requestedName + "`") + .setDescription(requestedDesc), ], }); }, diff --git a/src/utils/commands/help.ts b/src/utils/commands/help.ts index 2ff72c9..84ee417 100644 --- a/src/utils/commands/help.ts +++ b/src/utils/commands/help.ts @@ -1,4 +1,12 @@ -import { APIApplicationCommandSubcommandOption, Locale, SlashCommandBuilder } from "discord.js"; +import { + APIApplicationCommandSubcommandOption, + ApplicationCommandOptionType, + Client, + Locale, + SlashCommandBuilder, +} from "discord.js"; + +type Data = SlashCommandBuilder | APIApplicationCommandSubcommandOption; /** * Find the name of the command, trying to get the correct locale @@ -6,10 +14,8 @@ import { APIApplicationCommandSubcommandOption, Locale, SlashCommandBuilder } fr * @param locale Locale wanted * @returns Command's name */ -export const goodName = ( - data: SlashCommandBuilder | APIApplicationCommandSubcommandOption, - locale: Locale, -) => data.name_localizations?.[locale] ?? data.name; +export const goodName = (data: Data, locale: Locale) => + data.name_localizations?.[locale] ?? data.name; /** * Find the description of the command, trying to get the correct locale @@ -17,7 +23,51 @@ export const goodName = ( * @param locale Locale wanted * @returns Command's description */ -export const goodDescription = ( - data: SlashCommandBuilder | APIApplicationCommandSubcommandOption, - locale: Locale, -) => data.description_localizations?.[locale] ?? data.description; +export const goodDescription = (data: Data, locale: Locale) => + data.description_localizations?.[locale] ?? data.description; + +/** + * Aux function for Sub/NameNotLocalized + * @param cmd data + * @param command command researched + * @returns if we found or not the researched command + */ +const filterLocalizations = (cmd: Data, command: string) => { + let res = false; + for (const key in cmd?.name_localizations) { + res = res || cmd.name_localizations?.[key as Locale] === command; + } + + return res; +}; + +/** + * Find a command based on any string, localized or not + * @param command string + * @returns the not localized corresponding string's command name + */ +export const NameNotLocalized = (client: Client, command: string): SlashCommandBuilder | null => { + const list = client.commands.list.map((cmd) => cmd.data); + + return ( + list.find((cmd) => cmd.name === command) || + list.filter((cmd) => filterLocalizations(cmd, command))[0] + ); +}; + +/** + * Find a subcommand of a command based on any string, localized or not + * @param parent command of the subcommand + * @param command string + * @returns the not localized corresponding string's subcommand name + */ +export const SubnameNotLocalized = (parent: SlashCommandBuilder, command: string) => { + const list = parent + ?.toJSON() + .options?.filter((option) => option.type === ApplicationCommandOptionType.Subcommand); + + return ( + list?.find((cmd) => cmd?.name === command) || + list?.filter((cmd) => filterLocalizations(cmd, command))[0] + ); +};