diff --git a/src/renderer/apis/commands.ts b/src/renderer/apis/commands.ts index 509ee507c..e46104a57 100644 --- a/src/renderer/apis/commands.ts +++ b/src/renderer/apis/commands.ts @@ -117,6 +117,11 @@ async function executeCommand( }, // eslint-disable-next-line @typescript-eslint/naming-convention interaction_data: { + // eslint-disable-next-line @typescript-eslint/naming-convention + application_command: command, + options: args, + type: command.type, + id: command.id, name: command.displayName, }, type: 20, @@ -155,6 +160,11 @@ async function executeCommand( }, // eslint-disable-next-line @typescript-eslint/naming-convention interaction_data: { + // eslint-disable-next-line @typescript-eslint/naming-convention + application_command: command, + options: args, + type: command.type, + id: command.id, name: command.displayName, }, type: 20, @@ -183,6 +193,11 @@ async function executeCommand( }, // eslint-disable-next-line @typescript-eslint/naming-convention interaction_data: { + // eslint-disable-next-line @typescript-eslint/naming-convention + application_command: command, + options: args, + type: command.type, + id: command.id, name: command.displayName, }, type: 20, @@ -215,10 +230,11 @@ export class CommandManager { }); } const currentSection = commandAndSections.get(this.#section.id); + const subcommandUnregister: Array<() => void> = []; command.applicationId = currentSection?.section.id; command.displayName ??= command.name; command.displayDescription ??= command.description; - command.type = 2; + command.type = 1; command.id ??= command.name; command.execute ??= (args, currentInfo) => { @@ -226,15 +242,43 @@ export class CommandManager { }; command.options?.map((option) => { + if (option.type === ApplicationCommandOptionType.Subcommand) { + option.applicationId = currentSection?.section.id; + option.name = `${command.name} ${option.name}`; + option.displayName ??= option.name; + option.displayDescription ??= option.description; + option.id = `${command.id}\u0000${option.name}`; + option.execute ??= (args, currentInfo) => { + void executeCommand(option.executor, args, currentInfo, option); + }; + subcommandUnregister.push(this.registerCommand(option)); + return null; + } + if (option.type === ApplicationCommandOptionType.SubcommandGroup) { + for (const subcommand of option.options ?? []) { + subcommand.type = 1; + subcommand.applicationId = currentSection?.section.id; + subcommand.name = `${command.name} ${option.name} ${subcommand.name}`; + subcommand.displayName ??= subcommand.name; + subcommand.displayDescription ??= subcommand.description; + subcommand.id = `${command.id}\u0000${option.name}\u0000${subcommand.name}`; + subcommand.execute ??= (args, currentInfo) => { + void executeCommand(subcommand.executor, args, currentInfo, subcommand); + }; + subcommandUnregister.push(this.registerCommand(subcommand)); + } + return null; + } option.serverLocalizedName ??= option.displayName; option.displayName ??= option.name; option.displayDescription ??= option.description; return option; }); - + command.options = command.options?.filter(Boolean); currentSection?.commands.set(command.id, command as AnyRepluggedCommand); const uninject = (): void => { + subcommandUnregister.forEach((un) => un()); void currentSection?.commands.delete(command.id!); this.#unregister = this.#unregister.filter((u) => u !== uninject); }; diff --git a/src/renderer/coremods/commands/index.ts b/src/renderer/coremods/commands/index.ts index 255e9ba23..ec2fb74bc 100644 --- a/src/renderer/coremods/commands/index.ts +++ b/src/renderer/coremods/commands/index.ts @@ -264,7 +264,31 @@ async function injectApplicationCommandIndexStore(): Promise { }, ); } - +async function injectCommandCache(): Promise { + const mod = await waitForProps<{ + getCachedCommand: (channel: Channel, id: string) => Promise; + }>("getCachedCommand"); + injector.after( + mod, + "getCachedCommand", + ([, id], res: { application?: RepluggedCommandSection; command?: AnyRepluggedCommand }) => { + const commandAndSectionsArray = Array.from(commandAndSections.values()).filter( + (commandAndSection) => commandAndSection.commands.size, + ); + const rpCached = commandAndSectionsArray + .map((commandAndSection) => ({ + application: commandAndSection.section, + command: Array.from(commandAndSection.commands.values()).find( + (command) => command.id === id, + ), + })) + .find((applicationAndCommand) => applicationAndCommand.command); + res.application ??= rpCached?.application; + res.command ??= rpCached?.command; + return res; + }, + ); +} async function injectProfileFetch(): Promise { const mod = await waitForProps<{ fetchProfile: (id: string) => Promise; @@ -280,6 +304,7 @@ export async function start(): Promise { await injectRepluggedBotIcon(); await injectRepluggedSectionIcon(); await injectApplicationCommandIndexStore(); + await injectCommandCache(); await injectProfileFetch(); loadCommands(); } diff --git a/src/types/discord.ts b/src/types/discord.ts index 4eedc3783..31cf18587 100644 --- a/src/types/discord.ts +++ b/src/types/discord.ts @@ -1,8 +1,8 @@ import { Message } from "@common/i18n"; export enum ApplicationCommandOptionType { - //Subcommand = 1, - //SubcommandGroup = 2, + Subcommand = 1, + SubcommandGroup = 2, String = 3, Integer = 4, Boolean = 5,