diff --git a/helpers/interactions/commands/createApplicationCommand.ts b/helpers/interactions/commands/createApplicationCommand.ts index 8bde7fe92..65664bc6c 100644 --- a/helpers/interactions/commands/createApplicationCommand.ts +++ b/helpers/interactions/commands/createApplicationCommand.ts @@ -1,6 +1,6 @@ import type { Bot } from "../../../bot.ts"; import { ApplicationCommandOption, ApplicationCommandTypes } from "../../../mod.ts"; -import { DiscordApplicationCommand } from "../../../types/discord.ts"; +import { DiscordApplicationCommand, DiscordApplicationCommandOption } from "../../../types/discord.ts"; /** * There are two kinds of Application Commands: global commands and guild commands. Global commands are available for every guild that adds your app; guild commands are specific to the guild you specify when making them. Command names are unique per application within each scope (global and guild). That means: @@ -13,14 +13,18 @@ import { DiscordApplicationCommand } from "../../../types/discord.ts"; * Global commands are cached for **1 hour**. That means that new global commands will fan out slowly across all guilds, and will be guaranteed to be updated in an hour. * Guild commands update **instantly**. We recommend you use guild commands for quick testing, and global commands when they're ready for public use. */ -export async function createApplicationCommand(bot: Bot, options: CreateApplicationCommand, guildId?: bigint) { +export async function createApplicationCommand( + bot: Bot, + options: CreateApplicationCommand | CreateContextApplicationCommand, + guildId?: bigint, +) { const result = await bot.rest.runMethod( bot.rest, "post", guildId ? bot.constants.endpoints.COMMANDS_GUILD(bot.applicationId, guildId) : bot.constants.endpoints.COMMANDS(bot.applicationId), - { + isContextApplicationCommand(options) ? { name: options.name, type: options.type } : { name: options.name, description: options.description, type: options.type, @@ -31,8 +35,7 @@ export async function createApplicationCommand(bot: Bot, options: CreateApplicat return bot.transformers.applicationCommand(bot, result); } -// @ts-ignore TODO: see if we can make this not circular -export function makeOptionsForCommand(options: ApplicationCommandOption[]) { +export function makeOptionsForCommand(options: ApplicationCommandOption[]): DiscordApplicationCommandOption[] { return options.map((option) => ({ type: option.type, name: option.name, @@ -57,4 +60,20 @@ export interface CreateApplicationCommand { type?: ApplicationCommandTypes; /** The parameters for the command */ options?: ApplicationCommandOption[]; + /** Whether the command is enabled by default when the app is added to a guild. Default: true */ + defaultPermission?: boolean; +} + +/** https://discord.com/developers/docs/interactions/slash-commands#create-global-application-command-json-params */ +export interface CreateContextApplicationCommand { + /** 1-31 character name matching lowercase `^[\w-]{1,32}$` */ + name: string; + /** The type of the command */ + type: ApplicationCommandTypes.Message | ApplicationCommandTypes.User; +} + +export function isContextApplicationCommand( + cmd: CreateContextApplicationCommand | CreateApplicationCommand, +): cmd is CreateContextApplicationCommand { + return cmd.type === ApplicationCommandTypes.Message || cmd.type === ApplicationCommandTypes.User; } diff --git a/helpers/interactions/commands/upsertApplicationCommand.ts b/helpers/interactions/commands/upsertApplicationCommand.ts index f25b2d720..556f89056 100644 --- a/helpers/interactions/commands/upsertApplicationCommand.ts +++ b/helpers/interactions/commands/upsertApplicationCommand.ts @@ -1,5 +1,10 @@ import type { Bot } from "../../../bot.ts"; -import { makeOptionsForCommand } from "./createApplicationCommand.ts"; +import { + CreateApplicationCommand, + CreateContextApplicationCommand, + isContextApplicationCommand, + makeOptionsForCommand, +} from "./createApplicationCommand.ts"; import { DiscordApplicationCommand } from "../../../types/discord.ts"; import { ApplicationCommandOption } from "../../../transformers/applicationCommandOption.ts"; import { ApplicationCommandTypes } from "../../../types/shared.ts"; @@ -10,7 +15,7 @@ import { ApplicationCommandTypes } from "../../../types/shared.ts"; export async function upsertApplicationCommand( bot: Bot, commandId: bigint, - options: EditGlobalApplicationCommand, + options: CreateApplicationCommand | CreateContextApplicationCommand, guildId?: bigint, ) { const result = await bot.rest.runMethod( @@ -19,27 +24,18 @@ export async function upsertApplicationCommand( guildId ? bot.constants.endpoints.COMMANDS_GUILD_ID(bot.applicationId, guildId, commandId) : bot.constants.endpoints.COMMANDS_ID(bot.applicationId, commandId), - { - name: options.name, - description: options.description, - type: options.type, - options: options.options ? makeOptionsForCommand(options.options) : undefined, - }, + isContextApplicationCommand(options) + ? { + name: options.name, + type: options.type, + } + : { + name: options.name, + description: options.description, + type: options.type, + options: options.options ? makeOptionsForCommand(options.options) : undefined, + }, ); return bot.transformers.applicationCommand(bot, result); } - -/** https://discord.com/developers/docs/interactions/slash-commands#edit-global-application-command-json-params */ -export interface EditGlobalApplicationCommand { - /** 1-32 character name matching lowercase `^[\w-]{1,32}$` */ - name?: string; - /** 1-100 character description */ - description?: string; - /** The type of the command */ - type?: ApplicationCommandTypes; - /** The parameters for the command */ - options?: ApplicationCommandOption[] | null; - /** Whether the command is enabled by default when the app is added to a guild. Default: true */ - defaultPermission?: boolean; -} diff --git a/helpers/interactions/commands/upsertApplicationCommands.ts b/helpers/interactions/commands/upsertApplicationCommands.ts index 533c8cc34..d85ce1a12 100644 --- a/helpers/interactions/commands/upsertApplicationCommands.ts +++ b/helpers/interactions/commands/upsertApplicationCommands.ts @@ -1,8 +1,12 @@ import type { Bot } from "../../../bot.ts"; import { Collection } from "../../../util/collection.ts"; -import { makeOptionsForCommand } from "./createApplicationCommand.ts"; +import { + CreateApplicationCommand, + CreateContextApplicationCommand, + isContextApplicationCommand, + makeOptionsForCommand, +} from "./createApplicationCommand.ts"; import { DiscordApplicationCommand } from "../../../types/discord.ts"; -import { EditGlobalApplicationCommand } from "./upsertApplicationCommand.ts"; import { MakeRequired } from "../../../types/shared.ts"; /** @@ -12,7 +16,7 @@ import { MakeRequired } from "../../../types/shared.ts"; */ export async function upsertApplicationCommands( bot: Bot, - options: MakeRequired[], + options: (CreateApplicationCommand | CreateContextApplicationCommand)[], guildId?: bigint, ) { const result = await bot.rest.runMethod( @@ -21,13 +25,19 @@ export async function upsertApplicationCommands( guildId ? bot.constants.endpoints.COMMANDS_GUILD(bot.applicationId, guildId) : bot.constants.endpoints.COMMANDS(bot.applicationId), - options.map((option) => ({ - name: option.name, - description: option.description, - type: option.type, - options: option.options ? makeOptionsForCommand(option.options) : undefined, - default_permission: option.defaultPermission, - })), + options.map((option) => (isContextApplicationCommand(option) + ? { + name: option.name, + type: option.type, + } + : { + name: option.name, + description: option.description, + type: option.type, + options: option.options ? makeOptionsForCommand(option.options) : undefined, + default_permission: option.defaultPermission, + }) + ), ); return new Collection(