From 7dd0dee20d6b04bce551d6615e71c9a3d8801f96 Mon Sep 17 00:00:00 2001 From: Naiyar <137700126+imnaiyar@users.noreply.github.com> Date: Tue, 28 Jan 2025 17:43:43 +0530 Subject: [PATCH 1/9] feat: entry point command --- .../src/client/actions/InteractionCreate.js | 4 + packages/discord.js/src/index.js | 2 + .../src/managers/ApplicationCommandManager.js | 1 + .../src/structures/ApplicationCommand.js | 29 ++++- .../src/structures/BaseInteraction.js | 10 ++ .../src/structures/CommandInteraction.js | 1 + .../structures/MessageComponentInteraction.js | 1 + .../src/structures/ModalSubmitInteraction.js | 1 + .../PrimaryEntryPointCommandInteraction.js | 10 ++ .../interfaces/InteractionResponses.js | 26 ++++ packages/discord.js/typings/index.d.ts | 82 ++++++++++--- packages/discord.js/typings/index.test-d.ts | 112 ++++++++++++++++++ 12 files changed, 258 insertions(+), 21 deletions(-) create mode 100644 packages/discord.js/src/structures/PrimaryEntryPointCommandInteraction.js diff --git a/packages/discord.js/src/client/actions/InteractionCreate.js b/packages/discord.js/src/client/actions/InteractionCreate.js index 60d1b04a54ec..59b97742a89c 100644 --- a/packages/discord.js/src/client/actions/InteractionCreate.js +++ b/packages/discord.js/src/client/actions/InteractionCreate.js @@ -9,6 +9,7 @@ const { ChatInputCommandInteraction } = require('../../structures/ChatInputComma const { MentionableSelectMenuInteraction } = require('../../structures/MentionableSelectMenuInteraction.js'); const { MessageContextMenuCommandInteraction } = require('../../structures/MessageContextMenuCommandInteraction.js'); const { ModalSubmitInteraction } = require('../../structures/ModalSubmitInteraction.js'); +const { PrimaryEntryPointCommandInteraction } = require('../../structures/PrimaryEntryPointCommandInteraction.js'); const { RoleSelectMenuInteraction } = require('../../structures/RoleSelectMenuInteraction.js'); const { StringSelectMenuInteraction } = require('../../structures/StringSelectMenuInteraction.js'); const { UserContextMenuCommandInteraction } = require('../../structures/UserContextMenuCommandInteraction.js'); @@ -38,6 +39,9 @@ class InteractionCreateAction extends Action { if (channel && !channel.isTextBased()) return; InteractionClass = MessageContextMenuCommandInteraction; break; + case ApplicationCommandType.PrimaryEntryPoint: + InteractionClass = PrimaryEntryPointCommandInteraction; + break; default: client.emit( Events.Debug, diff --git a/packages/discord.js/src/index.js b/packages/discord.js/src/index.js index a93413cd241a..668b6f080dff 100644 --- a/packages/discord.js/src/index.js +++ b/packages/discord.js/src/index.js @@ -186,6 +186,8 @@ exports.PartialGroupDMChannel = require('./structures/PartialGroupDMChannel.js') exports.PermissionOverwrites = require('./structures/PermissionOverwrites.js').PermissionOverwrites; exports.Poll = require('./structures/Poll.js').Poll; exports.PollAnswer = require('./structures/PollAnswer.js').PollAnswer; +exports.PrimaryEntryPointCommandInteraction = + require('./structures/PrimaryEntryPointCommandInteraction.js').PrimaryEntryPointCommandInteraction; exports.Presence = require('./structures/Presence.js').Presence; exports.ReactionCollector = require('./structures/ReactionCollector.js').ReactionCollector; exports.ReactionEmoji = require('./structures/ReactionEmoji.js').ReactionEmoji; diff --git a/packages/discord.js/src/managers/ApplicationCommandManager.js b/packages/discord.js/src/managers/ApplicationCommandManager.js index 2498eca7219a..5cec2bbf0378 100644 --- a/packages/discord.js/src/managers/ApplicationCommandManager.js +++ b/packages/discord.js/src/managers/ApplicationCommandManager.js @@ -282,6 +282,7 @@ class ApplicationCommandManager extends CachedManager { default_member_permissions, integration_types: command.integrationTypes ?? command.integration_types, contexts: command.contexts, + handler: command.handler, }; } } diff --git a/packages/discord.js/src/structures/ApplicationCommand.js b/packages/discord.js/src/structures/ApplicationCommand.js index ff18bd67b262..ac1a758a0e7d 100644 --- a/packages/discord.js/src/structures/ApplicationCommand.js +++ b/packages/discord.js/src/structures/ApplicationCommand.js @@ -162,6 +162,19 @@ class ApplicationCommand extends Base { this.contexts ??= null; } + if ('handler' in data) { + /** + * Determines whether the interaction is handled by the app's interactions handler or by Discord. + * Only available for {@link ApplicationCommandType.PrimaryEntryPoint} command + * and for apps with {@link ApplicationFlags.Embedded} flag (i.e, applications that have an Activity) + * + * @type {?EntryPointCommandHandlerType} + */ + this.handler = data.handler; + } else { + this.handler ??= null; + } + if ('version' in data) { /** * Autoincrementing version identifier updated during substantial record changes @@ -204,14 +217,18 @@ class ApplicationCommand extends Base { * @property {string} name The name of the command, must be in all lowercase if type is * {@link ApplicationCommandType.ChatInput} * @property {Object} [nameLocalizations] The localizations for the command name - * @property {string} description The description of the command, if type is {@link ApplicationCommandType.ChatInput} + * @property {string} description The description of the command, + * if type is {@link ApplicationCommandType.ChatInput} or {@link ApplicationCommandType.PrimaryEntryPoint} * @property {boolean} [nsfw] Whether the command is age-restricted * @property {Object} [descriptionLocalizations] The localizations for the command description, - * if type is {@link ApplicationCommandType.ChatInput} + * if type is {@link ApplicationCommandType.ChatInput} or {@link ApplicationCommandType.PrimaryEntryPoint} * @property {ApplicationCommandType} [type=ApplicationCommandType.ChatInput] The type of the command * @property {ApplicationCommandOptionData[]} [options] Options for the command * @property {?PermissionResolvable} [defaultMemberPermissions] The bitfield used to determine the default permissions * a member needs in order to run the command + * @property {ApplicationIntegrationType[]} [integrationTypes] Installation context(s) where the command is available + * @property {InteractionContextType[]} [contexts] Interaction context(s) where the command can be used + * @property {EntryPointCommandHandlerType} [handler] Determines whether the interaction is handled by the app's */ /** @@ -395,7 +412,8 @@ class ApplicationCommand extends Base { this.descriptionLocalizations ?? {}, ) || !isEqual(command.integrationTypes ?? command.integration_types ?? [], this.integrationTypes ?? []) || - !isEqual(command.contexts ?? [], this.contexts ?? []) + !isEqual(command.contexts ?? [], this.contexts ?? []) || + ('handler' in command && command.handler !== this.handler) ) { return false; } @@ -595,3 +613,8 @@ exports.ApplicationCommand = ApplicationCommand; * @external ApplicationCommandOptionAllowedChannelTypes * @see {@link https://discord.js.org/docs/packages/builders/stable/ApplicationCommandOptionAllowedChannelTypes:TypeAlias} */ + +/** + * @external EntryPointCommandHandlerType + * @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/EntryPointCommandHandlerType} + */ diff --git a/packages/discord.js/src/structures/BaseInteraction.js b/packages/discord.js/src/structures/BaseInteraction.js index 0dcfb80d950a..e97e49f0fbbb 100644 --- a/packages/discord.js/src/structures/BaseInteraction.js +++ b/packages/discord.js/src/structures/BaseInteraction.js @@ -218,6 +218,16 @@ class BaseInteraction extends Base { ); } + /** + * Indicates whether this interaction is a {@link PrimaryEntryPointCommandInteraction} + * @returns {boolean} + */ + isPrimaryEntryPointCommand() { + return ( + this.type === InteractionType.ApplicationCommand && this.commandType === ApplicationCommandType.PrimaryEntryPoint + ); + } + /** * Indicates whether this interaction is a {@link MessageComponentInteraction} * @returns {boolean} diff --git a/packages/discord.js/src/structures/CommandInteraction.js b/packages/discord.js/src/structures/CommandInteraction.js index 32b5fb3f77a1..05a90422f692 100644 --- a/packages/discord.js/src/structures/CommandInteraction.js +++ b/packages/discord.js/src/structures/CommandInteraction.js @@ -152,6 +152,7 @@ class CommandInteraction extends BaseInteraction { editReply() {} deleteReply() {} followUp() {} + launchActivity() {} showModal() {} awaitModalSubmit() {} } diff --git a/packages/discord.js/src/structures/MessageComponentInteraction.js b/packages/discord.js/src/structures/MessageComponentInteraction.js index 7b0d6b6b6acc..296451d84259 100644 --- a/packages/discord.js/src/structures/MessageComponentInteraction.js +++ b/packages/discord.js/src/structures/MessageComponentInteraction.js @@ -98,6 +98,7 @@ class MessageComponentInteraction extends BaseInteraction { followUp() {} deferUpdate() {} update() {} + launchActivity() {} showModal() {} awaitModalSubmit() {} } diff --git a/packages/discord.js/src/structures/ModalSubmitInteraction.js b/packages/discord.js/src/structures/ModalSubmitInteraction.js index 5362bb2e6bf3..85ae1df1ce9b 100644 --- a/packages/discord.js/src/structures/ModalSubmitInteraction.js +++ b/packages/discord.js/src/structures/ModalSubmitInteraction.js @@ -118,6 +118,7 @@ class ModalSubmitInteraction extends BaseInteraction { followUp() {} deferUpdate() {} update() {} + launchActivity() {} } InteractionResponses.applyToClass(ModalSubmitInteraction, 'showModal'); diff --git a/packages/discord.js/src/structures/PrimaryEntryPointCommandInteraction.js b/packages/discord.js/src/structures/PrimaryEntryPointCommandInteraction.js new file mode 100644 index 000000000000..e6eaf1b48ea2 --- /dev/null +++ b/packages/discord.js/src/structures/PrimaryEntryPointCommandInteraction.js @@ -0,0 +1,10 @@ +'use strict'; + +const { CommandInteraction } = require('./CommandInteraction.js'); +/** + * Represents a primary entry point command interaction. + * @extends {CommandInteraction} + */ +class PrimaryEntryPointCommandInteraction extends CommandInteraction {} + +exports.PrimaryEntryPointCommandInteraction = PrimaryEntryPointCommandInteraction; diff --git a/packages/discord.js/src/structures/interfaces/InteractionResponses.js b/packages/discord.js/src/structures/interfaces/InteractionResponses.js index 834e3e65f698..9ac40b057801 100644 --- a/packages/discord.js/src/structures/interfaces/InteractionResponses.js +++ b/packages/discord.js/src/structures/interfaces/InteractionResponses.js @@ -51,6 +51,12 @@ class InteractionResponses { * @property {boolean} [withResponse] Whether to return an {@link InteractionCallbackResponse} as the response */ + /** + * Options for launching activity in response to a {@link BaseInteraction} + * @typedef {Object} LaunchActivityOptions + * @property {boolean} [withResponse] Whether to return an {@link InteractionCallbackResponse} as the response + */ + /** * Options for showing a modal in response to a {@link BaseInteraction} * @typedef {Object} ShowModalOptions @@ -265,6 +271,25 @@ class InteractionResponses { return options.withResponse ? new InteractionCallbackResponse(this.client, response) : undefined; } + /** + * Launches activity, if enabled + * @param {LaunchActivityOptions} [options={}] Options for launching the activity + * @returns {Promise} + */ + async launchActivity({ withResponse } = {}) { + if (this.deferred || this.replied) throw new DiscordjsError(ErrorCodes.InteractionAlreadyReplied); + const response = await this.client.rest.post(Routes.interactionCallback(this.id, this.token), { + query: makeURLSearchParams({ with_response: withResponse ?? false }), + body: { + type: InteractionResponseType.LaunchActivity, + }, + auth: false, + }); + this.replied = true; + + return withResponse ? new InteractionCallbackResponse(this.client, response) : undefined; + } + /** * Shows a modal component * @param {ModalBuilder|ModalComponentData|APIModalInteractionResponseCallbackData} modal The modal to show @@ -328,6 +353,7 @@ class InteractionResponses { 'followUp', 'deferUpdate', 'update', + 'launchActivity', 'showModal', 'awaitModalSubmit', ]; diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 4cf6b1b415ed..0d101645f6a7 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -159,6 +159,7 @@ import { VoiceChannelEffectSendAnimationType, GatewayVoiceChannelEffectSendDispatchData, RESTAPIPoll, + EntryPointCommandHandlerType, } from 'discord-api-types/v10'; import { ChildProcess } from 'node:child_process'; import { Stream } from 'node:stream'; @@ -406,6 +407,7 @@ export class ApplicationCommand extends Base { public get manager(): ApplicationCommandManager; public id: Snowflake; public integrationTypes: ApplicationIntegrationType[] | null; + public handler: EntryPointCommandHandlerType | null; public name: string; public nameLocalizations: LocalizationMap | null; public nameLocalized: string | null; @@ -508,23 +510,6 @@ export type BooleanCache = Cached extends 'cached' ? t export abstract class CommandInteraction extends BaseInteraction { public type: InteractionType.ApplicationCommand; public get command(): ApplicationCommand | ApplicationCommand<{ guild: GuildResolvable }> | null; - public options: Omit< - CommandInteractionOptionResolver, - | 'getMessage' - | 'getFocused' - | 'getMentionable' - | 'getRole' - | 'getUser' - | 'getMember' - | 'getAttachment' - | 'getNumber' - | 'getInteger' - | 'getString' - | 'getChannel' - | 'getBoolean' - | 'getSubcommandGroup' - | 'getSubcommand' - >; public channelId: Snowflake; public commandId: Snowflake; public commandName: string; @@ -557,6 +542,13 @@ export abstract class CommandInteraction e public reply( options: string | MessagePayload | InteractionReplyOptions, ): Promise> | undefined>; + public launchActivity( + options: LaunchActivityOptions & { withResponse: true }, + ): Promise>>; + public launchActivity(options?: LaunchActivityOptions & { withResponse?: false }): Promise; + public launchActivity( + options?: LaunchActivityOptions, + ): Promise> | undefined>; public showModal( modal: | JSONEncodable @@ -1156,6 +1148,23 @@ export class CommandInteractionOptionResolver extends CommandInteraction { + public options: Omit< + CommandInteractionOptionResolver, + | 'getMessage' + | 'getFocused' + | 'getMentionable' + | 'getRole' + | 'getUser' + | 'getMember' + | 'getAttachment' + | 'getNumber' + | 'getInteger' + | 'getString' + | 'getChannel' + | 'getBoolean' + | 'getSubcommandGroup' + | 'getSubcommand' + >; public commandType: ApplicationCommandType.Message | ApplicationCommandType.User; public targetId: Snowflake; public inGuild(): this is ContextMenuCommandInteraction<'raw' | 'cached'>; @@ -1164,6 +1173,15 @@ export class ContextMenuCommandInteraction private resolveContextMenuOptions(data: APIApplicationCommandInteractionData): CommandInteractionOption[]; } +export class PrimaryEntryPointCommandInteraction< + Cached extends CacheType = CacheType, +> extends CommandInteraction { + public commandType: ApplicationCommandType.PrimaryEntryPoint; + public inGuild(): this is PrimaryEntryPointCommandInteraction<'raw' | 'cached'>; + public inCachedGuild(): this is PrimaryEntryPointCommandInteraction<'cached'>; + public inRawGuild(): this is PrimaryEntryPointCommandInteraction<'raw'>; +} + // tslint:disable-next-line no-empty-interface export interface DMChannel extends Omit< @@ -1779,6 +1797,7 @@ export type Interaction = | ChatInputCommandInteraction | MessageContextMenuCommandInteraction | UserContextMenuCommandInteraction + | PrimaryEntryPointCommandInteraction | SelectMenuInteraction | ButtonInteraction | AutocompleteInteraction @@ -1827,6 +1846,7 @@ export class BaseInteraction extends Base public isChatInputCommand(): this is ChatInputCommandInteraction; public isCommand(): this is CommandInteraction; public isContextMenuCommand(): this is ContextMenuCommandInteraction; + public isPrimaryEntryPointCommand(): this is PrimaryEntryPointCommandInteraction; public isMessageComponent(): this is MessageComponentInteraction; public isMessageContextMenuCommand(): this is MessageContextMenuCommandInteraction; public isModalSubmit(): this is ModalSubmitInteraction; @@ -2198,6 +2218,13 @@ export class MessageComponentInteraction e public update( options: string | MessagePayload | InteractionUpdateOptions, ): Promise> | undefined>; + public launchActivity( + options: LaunchActivityOptions & { withResponse: true }, + ): Promise>>; + public launchActivity(options?: LaunchActivityOptions & { withResponse?: false }): Promise; + public launchActivity( + options?: LaunchActivityOptions, + ): Promise> | undefined>; public showModal( modal: | JSONEncodable @@ -2436,6 +2463,13 @@ export class ModalSubmitInteraction extend public deferUpdate( options?: InteractionDeferUpdateOptions, ): Promise> | undefined>; + public launchActivity( + options: LaunchActivityOptions & { withResponse: true }, + ): Promise>>; + public launchActivity(options?: LaunchActivityOptions & { withResponse?: false }): Promise; + public launchActivity( + options?: LaunchActivityOptions, + ): Promise> | undefined>; public inGuild(): this is ModalSubmitInteraction<'raw' | 'cached'>; public inCachedGuild(): this is ModalSubmitInteraction<'cached'>; public inRawGuild(): this is ModalSubmitInteraction<'raw'>; @@ -4575,10 +4609,18 @@ export interface ChatInputApplicationCommandData extends BaseApplicationCommandD options?: readonly ApplicationCommandOptionData[]; } +export interface PrimaryEntryPointCommandData extends BaseApplicationCommandData { + description?: string; + descriptionLocalizations?: LocalizationMap; + type: ApplicationCommandType.PrimaryEntryPoint; + handler?: EntryPointCommandHandlerType; +} + export type ApplicationCommandData = | UserApplicationCommandData | MessageApplicationCommandData - | ChatInputApplicationCommandData; + | ChatInputApplicationCommandData + | PrimaryEntryPointCommandData; export interface ApplicationCommandChannelOptionData extends BaseApplicationCommandOptionsData { type: CommandOptionChannelResolvableType; @@ -6601,6 +6643,10 @@ export interface ShowModalOptions { withResponse?: boolean; } +export interface LaunchActivityOptions { + withResponse?: boolean; +} + export { Snowflake }; export type StageInstanceResolvable = StageInstance | Snowflake; diff --git a/packages/discord.js/typings/index.test-d.ts b/packages/discord.js/typings/index.test-d.ts index c327afdc02af..011c1d523e18 100644 --- a/packages/discord.js/typings/index.test-d.ts +++ b/packages/discord.js/typings/index.test-d.ts @@ -204,6 +204,7 @@ import { SendableChannels, PollData, InteractionCallbackResponse, + PrimaryEntryPointCommandInteraction, GuildScheduledEventRecurrenceRuleOptions, ThreadOnlyChannel, PartialPoll, @@ -1884,6 +1885,11 @@ client.on('interactionCreate', async interaction => { expectType>>(interaction.deferUpdate({ withResponse: true })); expectType>(interaction.deferUpdate()); expectType>>(interaction.followUp({ content: 'a' })); + expectType>(interaction.launchActivity({ withResponse: true })); + expectType>(interaction.launchActivity({ withResponse: false })); + expectType>( + interaction.launchActivity({ withResponse: booleanValue }), + ); } else if (interaction.inRawGuild()) { expectAssignable(interaction); expectType(interaction.component); @@ -1910,6 +1916,11 @@ client.on('interactionCreate', async interaction => { expectType>>(interaction.deferUpdate({ withResponse: true })); expectType>(interaction.deferUpdate()); expectType>>(interaction.followUp({ content: 'a' })); + expectType>(interaction.launchActivity({ withResponse: true })); + expectType>(interaction.launchActivity({ withResponse: false })); + expectType>( + interaction.launchActivity({ withResponse: booleanValue }), + ); } else if (interaction.inGuild()) { expectAssignable(interaction); expectType(interaction.component); @@ -1936,6 +1947,11 @@ client.on('interactionCreate', async interaction => { expectType>(interaction.deferUpdate({ withResponse: true })); expectType>(interaction.deferUpdate()); expectType>(interaction.followUp({ content: 'a' })); + expectType>(interaction.launchActivity({ withResponse: true })); + expectType>(interaction.launchActivity({ withResponse: false })); + expectType>( + interaction.launchActivity({ withResponse: booleanValue }), + ); } } @@ -1982,6 +1998,11 @@ client.on('interactionCreate', async interaction => { expectType>>(interaction.editReply({ content: 'a' })); expectType>>(interaction.fetchReply()); expectType>>(interaction.followUp({ content: 'a' })); + expectType>(interaction.launchActivity({ withResponse: true })); + expectType>(interaction.launchActivity({ withResponse: false })); + expectType>( + interaction.launchActivity({ withResponse: booleanValue }), + ); } else if (interaction.inRawGuild()) { expectAssignable(interaction); expectType(interaction.guild); @@ -1999,6 +2020,11 @@ client.on('interactionCreate', async interaction => { expectType>>(interaction.editReply({ content: 'a' })); expectType>>(interaction.fetchReply()); expectType>>(interaction.followUp({ content: 'a' })); + expectType>(interaction.launchActivity({ withResponse: true })); + expectType>(interaction.launchActivity({ withResponse: false })); + expectType>( + interaction.launchActivity({ withResponse: booleanValue }), + ); } else if (interaction.inGuild()) { expectAssignable(interaction); expectType(interaction.guild); @@ -2016,6 +2042,11 @@ client.on('interactionCreate', async interaction => { expectType>(interaction.editReply({ content: 'a' })); expectType>(interaction.fetchReply()); expectType>(interaction.followUp({ content: 'a' })); + expectType>(interaction.launchActivity({ withResponse: true })); + expectType>(interaction.launchActivity({ withResponse: false })); + expectType>( + interaction.launchActivity({ withResponse: booleanValue }), + ); } } @@ -2184,6 +2215,84 @@ client.on('interactionCreate', async interaction => { interaction.options.getMessage('name'); } + if ( + interaction.type === InteractionType.ApplicationCommand && + interaction.commandType === ApplicationCommandType.PrimaryEntryPoint + ) { + expectType(interaction); + + // @ts-expect-error No options on primary entry point commands + interaction.options; + if (interaction.inCachedGuild()) { + expectAssignable(interaction); + expectAssignable(interaction.guild); + expectAssignable>(interaction); + expectType>(interaction.reply({ content: 'a', withResponse: true })); + expectType>(interaction.deferReply({ withResponse: true })); + expectType>(interaction.deferReply()); + expectType>(interaction.reply({ content: 'a', withResponse: false })); + expectType>(interaction.deferReply({ withResponse: false })); + expectType>( + interaction.reply({ content: 'a', withResponse: booleanValue }), + ); + expectType>( + interaction.deferReply({ withResponse: booleanValue }), + ); + expectType>>(interaction.editReply({ content: 'a' })); + expectType>>(interaction.fetchReply()); + expectType>>(interaction.followUp({ content: 'a' })); + expectType>(interaction.launchActivity({ withResponse: true })); + expectType>(interaction.launchActivity({ withResponse: false })); + expectType>( + interaction.launchActivity({ withResponse: booleanValue }), + ); + } else if (interaction.inRawGuild()) { + expectAssignable(interaction); + expectType(interaction.guild); + expectType>(interaction.reply({ content: 'a', withResponse: true })); + expectType>(interaction.deferReply({ withResponse: true })); + expectType>(interaction.deferReply()); + expectType>(interaction.reply({ content: 'a', withResponse: false })); + expectType>(interaction.deferReply({ withResponse: false })); + expectType>( + interaction.reply({ content: 'a', withResponse: booleanValue }), + ); + expectType>( + interaction.deferReply({ withResponse: booleanValue }), + ); + expectType>>(interaction.editReply({ content: 'a' })); + expectType>>(interaction.fetchReply()); + expectType>>(interaction.followUp({ content: 'a' })); + expectType>(interaction.launchActivity({ withResponse: true })); + expectType>(interaction.launchActivity({ withResponse: false })); + expectType>( + interaction.launchActivity({ withResponse: booleanValue }), + ); + } else if (interaction.inGuild()) { + expectAssignable(interaction); + expectType(interaction.guild); + expectType>(interaction.reply({ content: 'a', withResponse: true })); + expectType>(interaction.deferReply({ withResponse: true })); + expectType>(interaction.deferReply()); + expectType>(interaction.reply({ content: 'a', withResponse: false })); + expectType>(interaction.deferReply({ withResponse: false })); + expectType>( + interaction.reply({ content: 'a', withResponse: booleanValue }), + ); + expectType>( + interaction.deferReply({ withResponse: booleanValue }), + ); + expectType>(interaction.editReply({ content: 'a' })); + expectType>(interaction.fetchReply()); + expectType>(interaction.followUp({ content: 'a' })); + expectType>(interaction.launchActivity({ withResponse: true })); + expectType>(interaction.launchActivity({ withResponse: false })); + expectType>( + interaction.launchActivity({ withResponse: booleanValue }), + ); + } + } + if (interaction.isRepliable()) { expectAssignable(interaction); interaction.reply('test'); @@ -2212,6 +2321,7 @@ client.on('interactionCreate', async interaction => { expectType>>(interaction.deferUpdate({ withResponse: true })); expectType>(interaction.deferUpdate()); expectType>>(interaction.followUp({ content: 'a' })); + expectType>(interaction.launchActivity({ withResponse: true })); } else if (interaction.inRawGuild()) { expectAssignable(interaction); expectType(interaction.guild); @@ -2223,6 +2333,7 @@ client.on('interactionCreate', async interaction => { expectType>>(interaction.deferUpdate({ withResponse: true })); expectType>(interaction.deferUpdate()); expectType>>(interaction.followUp({ content: 'a' })); + expectType>(interaction.launchActivity({ withResponse: true })); } else if (interaction.inGuild()) { expectAssignable(interaction); expectType(interaction.guild); @@ -2234,6 +2345,7 @@ client.on('interactionCreate', async interaction => { expectType>(interaction.deferUpdate({ withResponse: true })); expectType>(interaction.deferUpdate()); expectType>(interaction.followUp({ content: 'a' })); + expectType>(interaction.launchActivity({ withResponse: true })); } } }); From 51c919e7adb62ffc660f86c8c4f31948844f4874 Mon Sep 17 00:00:00 2001 From: imnaiyar <137700126+imnaiyar@users.noreply.github.com.> Date: Thu, 13 Mar 2025 02:15:05 +0530 Subject: [PATCH 2/9] chore: update tests --- packages/discord.js/typings/index.test-d.ts | 44 ++++++++++----------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/packages/discord.js/typings/index.test-d.ts b/packages/discord.js/typings/index.test-d.ts index 011c1d523e18..4e41a80fd7ee 100644 --- a/packages/discord.js/typings/index.test-d.ts +++ b/packages/discord.js/typings/index.test-d.ts @@ -1885,9 +1885,9 @@ client.on('interactionCreate', async interaction => { expectType>>(interaction.deferUpdate({ withResponse: true })); expectType>(interaction.deferUpdate()); expectType>>(interaction.followUp({ content: 'a' })); - expectType>(interaction.launchActivity({ withResponse: true })); + expectType>>(interaction.launchActivity({ withResponse: true })); expectType>(interaction.launchActivity({ withResponse: false })); - expectType>( + expectType | undefined>>( interaction.launchActivity({ withResponse: booleanValue }), ); } else if (interaction.inRawGuild()) { @@ -1916,9 +1916,9 @@ client.on('interactionCreate', async interaction => { expectType>>(interaction.deferUpdate({ withResponse: true })); expectType>(interaction.deferUpdate()); expectType>>(interaction.followUp({ content: 'a' })); - expectType>(interaction.launchActivity({ withResponse: true })); + expectType>>(interaction.launchActivity({ withResponse: true })); expectType>(interaction.launchActivity({ withResponse: false })); - expectType>( + expectType | undefined>>( interaction.launchActivity({ withResponse: booleanValue }), ); } else if (interaction.inGuild()) { @@ -1998,9 +1998,9 @@ client.on('interactionCreate', async interaction => { expectType>>(interaction.editReply({ content: 'a' })); expectType>>(interaction.fetchReply()); expectType>>(interaction.followUp({ content: 'a' })); - expectType>(interaction.launchActivity({ withResponse: true })); + expectType>>(interaction.launchActivity({ withResponse: true })); expectType>(interaction.launchActivity({ withResponse: false })); - expectType>( + expectType | undefined>>( interaction.launchActivity({ withResponse: booleanValue }), ); } else if (interaction.inRawGuild()) { @@ -2020,9 +2020,9 @@ client.on('interactionCreate', async interaction => { expectType>>(interaction.editReply({ content: 'a' })); expectType>>(interaction.fetchReply()); expectType>>(interaction.followUp({ content: 'a' })); - expectType>(interaction.launchActivity({ withResponse: true })); + expectType>>(interaction.launchActivity({ withResponse: true })); expectType>(interaction.launchActivity({ withResponse: false })); - expectType>( + expectType | undefined>>( interaction.launchActivity({ withResponse: booleanValue }), ); } else if (interaction.inGuild()) { @@ -2227,45 +2227,45 @@ client.on('interactionCreate', async interaction => { expectAssignable(interaction); expectAssignable(interaction.guild); expectAssignable>(interaction); - expectType>(interaction.reply({ content: 'a', withResponse: true })); - expectType>(interaction.deferReply({ withResponse: true })); + expectType>>(interaction.reply({ content: 'a', withResponse: true })); + expectType>>(interaction.deferReply({ withResponse: true })); expectType>(interaction.deferReply()); expectType>(interaction.reply({ content: 'a', withResponse: false })); expectType>(interaction.deferReply({ withResponse: false })); - expectType>( + expectType | undefined>>( interaction.reply({ content: 'a', withResponse: booleanValue }), ); - expectType>( + expectType | undefined>>( interaction.deferReply({ withResponse: booleanValue }), ); expectType>>(interaction.editReply({ content: 'a' })); expectType>>(interaction.fetchReply()); expectType>>(interaction.followUp({ content: 'a' })); - expectType>(interaction.launchActivity({ withResponse: true })); + expectType>>(interaction.launchActivity({ withResponse: true })); expectType>(interaction.launchActivity({ withResponse: false })); - expectType>( + expectType | undefined>>( interaction.launchActivity({ withResponse: booleanValue }), ); } else if (interaction.inRawGuild()) { expectAssignable(interaction); expectType(interaction.guild); - expectType>(interaction.reply({ content: 'a', withResponse: true })); - expectType>(interaction.deferReply({ withResponse: true })); + expectType>>(interaction.reply({ content: 'a', withResponse: true })); + expectType>>(interaction.deferReply({ withResponse: true })); expectType>(interaction.deferReply()); expectType>(interaction.reply({ content: 'a', withResponse: false })); expectType>(interaction.deferReply({ withResponse: false })); - expectType>( + expectType | undefined>>( interaction.reply({ content: 'a', withResponse: booleanValue }), ); - expectType>( + expectType | undefined>>( interaction.deferReply({ withResponse: booleanValue }), ); expectType>>(interaction.editReply({ content: 'a' })); expectType>>(interaction.fetchReply()); expectType>>(interaction.followUp({ content: 'a' })); - expectType>(interaction.launchActivity({ withResponse: true })); + expectType>>(interaction.launchActivity({ withResponse: true })); expectType>(interaction.launchActivity({ withResponse: false })); - expectType>( + expectType | undefined>>( interaction.launchActivity({ withResponse: booleanValue }), ); } else if (interaction.inGuild()) { @@ -2321,7 +2321,7 @@ client.on('interactionCreate', async interaction => { expectType>>(interaction.deferUpdate({ withResponse: true })); expectType>(interaction.deferUpdate()); expectType>>(interaction.followUp({ content: 'a' })); - expectType>(interaction.launchActivity({ withResponse: true })); + expectType>>(interaction.launchActivity({ withResponse: true })); } else if (interaction.inRawGuild()) { expectAssignable(interaction); expectType(interaction.guild); @@ -2333,7 +2333,7 @@ client.on('interactionCreate', async interaction => { expectType>>(interaction.deferUpdate({ withResponse: true })); expectType>(interaction.deferUpdate()); expectType>>(interaction.followUp({ content: 'a' })); - expectType>(interaction.launchActivity({ withResponse: true })); + expectType>>(interaction.launchActivity({ withResponse: true })); } else if (interaction.inGuild()) { expectAssignable(interaction); expectType(interaction.guild); From da340436cfd94bc3f53311f6194a958148b350a9 Mon Sep 17 00:00:00 2001 From: imnaiyar <137700126+imnaiyar@users.noreply.github.com.> Date: Tue, 18 Mar 2025 14:15:45 +0530 Subject: [PATCH 3/9] chore: suggested change --- packages/discord.js/src/structures/ApplicationCommand.js | 5 ----- packages/discord.js/src/util/APITypes.js | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/discord.js/src/structures/ApplicationCommand.js b/packages/discord.js/src/structures/ApplicationCommand.js index ac1a758a0e7d..b20c414fe5bf 100644 --- a/packages/discord.js/src/structures/ApplicationCommand.js +++ b/packages/discord.js/src/structures/ApplicationCommand.js @@ -613,8 +613,3 @@ exports.ApplicationCommand = ApplicationCommand; * @external ApplicationCommandOptionAllowedChannelTypes * @see {@link https://discord.js.org/docs/packages/builders/stable/ApplicationCommandOptionAllowedChannelTypes:TypeAlias} */ - -/** - * @external EntryPointCommandHandlerType - * @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/EntryPointCommandHandlerType} - */ diff --git a/packages/discord.js/src/util/APITypes.js b/packages/discord.js/src/util/APITypes.js index 6a38ed450bef..c40af6c289cc 100644 --- a/packages/discord.js/src/util/APITypes.js +++ b/packages/discord.js/src/util/APITypes.js @@ -325,6 +325,11 @@ * @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/EntitlementType} */ +/** + * @external EntryPointCommandHandlerType + * @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/EntryPointCommandHandlerType} + */ + /** * @external ForumLayoutType * @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/ForumLayoutType} From f1b8cd455dd6c865ad5b50b77400f0f2c28e686e Mon Sep 17 00:00:00 2001 From: Naiyar <137700126+imnaiyar@users.noreply.github.com> Date: Fri, 25 Apr 2025 00:44:56 +0600 Subject: [PATCH 4/9] chore: suggestion Co-authored-by: Almeida --- packages/discord.js/src/structures/ApplicationCommand.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/discord.js/src/structures/ApplicationCommand.js b/packages/discord.js/src/structures/ApplicationCommand.js index 15be037b3c85..efdd53bb2dd8 100644 --- a/packages/discord.js/src/structures/ApplicationCommand.js +++ b/packages/discord.js/src/structures/ApplicationCommand.js @@ -165,8 +165,8 @@ class ApplicationCommand extends Base { if ('handler' in data) { /** * Determines whether the interaction is handled by the app's interactions handler or by Discord. - * Only available for {@link ApplicationCommandType.PrimaryEntryPoint} command - * and for apps with {@link ApplicationFlags.Embedded} flag (i.e, applications that have an Activity) + * Only available for {@link ApplicationCommandType.PrimaryEntryPoint} commands on + * applications with the {@link ApplicationFlags.Embedded} flag (i.e, those that have an Activity) * * @type {?EntryPointCommandHandlerType} */ From ae1b5ec76cb536e3d6f9d738b0d1286ee9160b82 Mon Sep 17 00:00:00 2001 From: Naiyar <137700126+imnaiyar@users.noreply.github.com> Date: Fri, 25 Apr 2025 00:45:09 +0600 Subject: [PATCH 5/9] chore: suggestion Co-authored-by: Almeida --- packages/discord.js/src/structures/ApplicationCommand.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/discord.js/src/structures/ApplicationCommand.js b/packages/discord.js/src/structures/ApplicationCommand.js index efdd53bb2dd8..0042df2113bd 100644 --- a/packages/discord.js/src/structures/ApplicationCommand.js +++ b/packages/discord.js/src/structures/ApplicationCommand.js @@ -226,8 +226,8 @@ class ApplicationCommand extends Base { * @property {ApplicationCommandOptionData[]} [options] Options for the command * @property {?PermissionResolvable} [defaultMemberPermissions] The bitfield used to determine the default permissions * a member needs in order to run the command - * @property {ApplicationIntegrationType[]} [integrationTypes] Installation context(s) where the command is available - * @property {InteractionContextType[]} [contexts] Interaction context(s) where the command can be used + * @property {ApplicationIntegrationType[]} [integrationTypes] Installation contexts where the command is available + * @property {InteractionContextType[]} [contexts] Interaction contexts where the command can be used * @property {EntryPointCommandHandlerType} [handler] Determines whether the interaction is handled by the app's */ From 5452218e084952645043249ab4674f7ebb79dae6 Mon Sep 17 00:00:00 2001 From: Naiyar <137700126+imnaiyar@users.noreply.github.com> Date: Fri, 25 Apr 2025 00:45:28 +0600 Subject: [PATCH 6/9] chore: suggestion Co-authored-by: Almeida --- packages/discord.js/src/structures/ApplicationCommand.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/discord.js/src/structures/ApplicationCommand.js b/packages/discord.js/src/structures/ApplicationCommand.js index 0042df2113bd..335e2ee7b4bd 100644 --- a/packages/discord.js/src/structures/ApplicationCommand.js +++ b/packages/discord.js/src/structures/ApplicationCommand.js @@ -228,7 +228,8 @@ class ApplicationCommand extends Base { * a member needs in order to run the command * @property {ApplicationIntegrationType[]} [integrationTypes] Installation contexts where the command is available * @property {InteractionContextType[]} [contexts] Interaction contexts where the command can be used - * @property {EntryPointCommandHandlerType} [handler] Determines whether the interaction is handled by the app's + * @property {EntryPointCommandHandlerType} [handler] Whether the interaction is handled by the app's + * interactions handler or by Discord. */ /** From 3e8841e1c09eda08c6ffa9e8a3f6b4b4e6917f69 Mon Sep 17 00:00:00 2001 From: Naiyar <137700126+imnaiyar@users.noreply.github.com> Date: Fri, 25 Apr 2025 00:45:43 +0600 Subject: [PATCH 7/9] chore: suggestion Co-authored-by: Almeida --- .../src/structures/PrimaryEntryPointCommandInteraction.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/discord.js/src/structures/PrimaryEntryPointCommandInteraction.js b/packages/discord.js/src/structures/PrimaryEntryPointCommandInteraction.js index e6eaf1b48ea2..e757e19c3b1a 100644 --- a/packages/discord.js/src/structures/PrimaryEntryPointCommandInteraction.js +++ b/packages/discord.js/src/structures/PrimaryEntryPointCommandInteraction.js @@ -1,6 +1,7 @@ 'use strict'; const { CommandInteraction } = require('./CommandInteraction.js'); + /** * Represents a primary entry point command interaction. * @extends {CommandInteraction} From bf07f42d1118095ef2fee6e87201400f33227e41 Mon Sep 17 00:00:00 2001 From: Naiyar <137700126+imnaiyar@users.noreply.github.com> Date: Fri, 25 Apr 2025 00:46:00 +0600 Subject: [PATCH 8/9] chore: suggestion Co-authored-by: Almeida --- .../src/structures/interfaces/InteractionResponses.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/discord.js/src/structures/interfaces/InteractionResponses.js b/packages/discord.js/src/structures/interfaces/InteractionResponses.js index 9ac40b057801..c32b82bf0180 100644 --- a/packages/discord.js/src/structures/interfaces/InteractionResponses.js +++ b/packages/discord.js/src/structures/interfaces/InteractionResponses.js @@ -272,7 +272,7 @@ class InteractionResponses { } /** - * Launches activity, if enabled + * Launches this application's activity, if enabled * @param {LaunchActivityOptions} [options={}] Options for launching the activity * @returns {Promise} */ From 8ec69410f4fac6cae36db304cb4de98a64c8f544 Mon Sep 17 00:00:00 2001 From: Naiyar <137700126+imnaiyar@users.noreply.github.com> Date: Fri, 25 Apr 2025 00:47:29 +0600 Subject: [PATCH 9/9] chore: remove extra info closing tag --- packages/discord.js/src/structures/ApplicationCommand.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/discord.js/src/structures/ApplicationCommand.js b/packages/discord.js/src/structures/ApplicationCommand.js index 335e2ee7b4bd..95ab6fff8ee0 100644 --- a/packages/discord.js/src/structures/ApplicationCommand.js +++ b/packages/discord.js/src/structures/ApplicationCommand.js @@ -167,7 +167,6 @@ class ApplicationCommand extends Base { * Determines whether the interaction is handled by the app's interactions handler or by Discord. * Only available for {@link ApplicationCommandType.PrimaryEntryPoint} commands on * applications with the {@link ApplicationFlags.Embedded} flag (i.e, those that have an Activity) - * * @type {?EntryPointCommandHandlerType} */ this.handler = data.handler;