diff --git a/src/structures/Interaction.js b/src/structures/Interaction.js index e1a5d410fa7e..4676a3484097 100644 --- a/src/structures/Interaction.js +++ b/src/structures/Interaction.js @@ -226,6 +226,16 @@ class Interaction extends Base { MessageComponentTypes[this.componentType] === MessageComponentTypes.SELECT_MENU ); } + + /** + * Indicates whether this interaction can be replied to. + * @returns {boolean} + */ + isRepliable() { + return ![InteractionTypes.PING, InteractionTypes.APPLICATION_COMMAND_AUTOCOMPLETE].includes( + InteractionTypes[this.type], + ); + } } module.exports = Interaction; diff --git a/typings/index.d.ts b/typings/index.d.ts index a99088e2494d..6d2a8c77c094 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -321,6 +321,21 @@ export type GuildCacheMessage = CacheTypeReducer< Message | APIMessage >; +export interface InteractionResponseFields { + deferred: boolean; + ephemeral: boolean | null; + replied: boolean; + webhook: InteractionWebhook; + reply(options: InteractionReplyOptions & { fetchReply: true }): Promise>; + reply(options: string | MessagePayload | InteractionReplyOptions): Promise; + deleteReply(): Promise; + editReply(options: string | MessagePayload | WebhookEditMessageOptions): Promise>; + deferReply(options: InteractionDeferReplyOptions & { fetchReply: true }): Promise>; + deferReply(options?: InteractionDeferReplyOptions): Promise; + fetchReply(): Promise>; + followUp(options: string | MessagePayload | InteractionReplyOptions): Promise>; +} + export abstract class BaseCommandInteraction extends Interaction { public readonly command: ApplicationCommand | ApplicationCommand<{ guild: GuildResolvable }> | null; public options: Omit< @@ -1352,6 +1367,7 @@ export class Interaction extends Base { public isMessageContextMenu(): this is MessageContextMenuInteraction; public isMessageComponent(): this is MessageComponentInteraction; public isSelectMenu(): this is SelectMenuInteraction; + public isRepliable(): this is this & InteractionResponseFields; } export class InteractionCollector extends Collector { diff --git a/typings/index.test-d.ts b/typings/index.test-d.ts index 9d9281bc1422..0a78e3093440 100644 --- a/typings/index.test-d.ts +++ b/typings/index.test-d.ts @@ -93,6 +93,7 @@ import { MessageActionRowComponent, MessageSelectMenu, PartialDMChannel, + InteractionResponseFields, } from '.'; import type { ApplicationCommandOptionTypes } from './enums'; import { expectAssignable, expectDeprecated, expectNotAssignable, expectNotType, expectType } from 'tsd'; @@ -1145,6 +1146,16 @@ client.on('interactionCreate', async interaction => { expectType(interaction.options.getSubcommandGroup(booleanValue)); expectType(interaction.options.getSubcommandGroup(false)); } + + if (interaction.isRepliable()) { + expectAssignable(interaction); + interaction.reply('test'); + } + + if (interaction.isCommand() && interaction.isRepliable()) { + expectAssignable(interaction); + expectAssignable(interaction); + } }); declare const shard: Shard;