From 63cb52e7f47e9c6da3e1342369d7c5101f7ed633 Mon Sep 17 00:00:00 2001 From: Wroclaw Date: Tue, 23 Apr 2024 20:56:55 +0200 Subject: [PATCH] Command: Add integration and context types While discord api supports that, discord api types, which discord.js depends on does not. --- scripts/pushCommands.ts | 18 ++++++++++++++++- src/command.ts | 44 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/scripts/pushCommands.ts b/scripts/pushCommands.ts index 25ee04e..3c5f093 100644 --- a/scripts/pushCommands.ts +++ b/scripts/pushCommands.ts @@ -4,13 +4,25 @@ import { REST, RESTGetAPIOAuth2CurrentApplicationResult, RESTPostAPIApplicationC import { config } from "../src/index"; import requireDirectory from "require-directory"; -import Command from "../src/command"; +import + Command +, { + ApplicationIntegrationType +, InteractionContextTypes +, InteractionTypeMap +} from "../src/command"; const post: RESTPostAPIApplicationCommandsJSONBody[] = []; const guildId = process.argv.slice(2)[0]; const importedCommands = requireDirectory(module, "../src/commands"); +function isGuildCommand(command: Command): boolean { + // guild Commmand is when it's a guild install and context is guild (and these are defaults if not provided) + return (command.integration_types?.includes(ApplicationIntegrationType.Guild_Install) ?? true) + && (command.contexts?.includes(InteractionContextTypes.Guild) ?? true); +} + for (const obj in importedCommands) { try { const allExports = importedCommands[obj] as {default: unknown}; @@ -19,6 +31,10 @@ for (const obj in importedCommands) { // @ts-expect-error const constructedExport = new defaultExport() as unknown; if (!(constructedExport instanceof Command)) throw new Error(`${obj}'s default does not extends Command`); + if (guildId && guildId !== "" && isGuildCommand(constructedExport as Command)) { + console.log(`Skipping ${obj} because it's not a guild command`); + continue; + } post.push(constructedExport.toRESTPostApplicationCommands()); } catch (e) { console.error(e); diff --git a/src/command.ts b/src/command.ts index d053e72..35be22a 100644 --- a/src/command.ts +++ b/src/command.ts @@ -2,12 +2,47 @@ import { AutocompleteInteraction, PermissionsBitField } from "discord.js"; import { RESTPostAPIApplicationCommandsJSONBody } from "discord.js"; import { APIApplicationCommandOption, ApplicationCommandType, ChatInputCommandInteraction, LocalizationMap, MessageInteraction, PermissionResolvable, UserSelectMenuInteraction } from "discord.js"; -type InteractionTypeMap = { +export type InteractionTypeMap = { + // [CommandType]: [Interaction, Description] [ApplicationCommandType.ChatInput]: [ChatInputCommandInteraction, string]; [ApplicationCommandType.Message]: [MessageInteraction, never]; [ApplicationCommandType.User]: [UserSelectMenuInteraction, never]; }; +// TODO: At time of coding, Discord api types doesn't support user installations of bot/application yet +// replace this with the types from the discord api types when it's available +/** + * https://discord.com/developers/docs/resources/application#application-object-application-integration-types + */ +export enum ApplicationIntegrationType { + Guild_Install = 0, + User_Install = 1, +} + +/** + * https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-interaction-context-types + */ +export enum InteractionContextTypes { + Guild = 0, + BotDM = 1, + PrivateChannel = 2, +} + +/** + * https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-structure + */ +export type FutureRESTPostAPIApplicationCommandsJSONBody = + RESTPostAPIApplicationCommandsJSONBody +& { + /** + * @deprecated use contexts instead + */ + dm_permission?: boolean; + integration_types?: ApplicationIntegrationType[]; + contexts?: InteractionContextTypes[]; +}; + + interface Command { readonly name: string; readonly name_localizations?: LocalizationMap; @@ -17,7 +52,10 @@ interface Command { @@ -25,7 +63,7 @@ abstract class Command; - toRESTPostApplicationCommands(): RESTPostAPIApplicationCommandsJSONBody { + toRESTPostApplicationCommands(): FutureRESTPostAPIApplicationCommandsJSONBody { return { name: this.name, name_localizations: this.name_localizations, @@ -36,6 +74,8 @@ abstract class Command