diff --git a/packages/discord.js/src/client/actions/InteractionCreate.js b/packages/discord.js/src/client/actions/InteractionCreate.js index 04774a6b4..ff51fe210 100644 --- a/packages/discord.js/src/client/actions/InteractionCreate.js +++ b/packages/discord.js/src/client/actions/InteractionCreate.js @@ -5,9 +5,9 @@ const Action = require('./Action'); const AutocompleteInteraction = require('../../structures/AutocompleteInteraction'); const ButtonInteraction = require('../../structures/ButtonInteraction'); const CommandInteraction = require('../../structures/CommandInteraction'); -const MessageContextMenuInteraction = require('../../structures/MessageContextMenuInteraction'); +const MessageContextMenuCommandInteraction = require('../../structures/MessageContextMenuCommandInteraction'); const SelectMenuInteraction = require('../../structures/SelectMenuInteraction'); -const UserContextMenuInteraction = require('../../structures/UserContextMenuInteraction'); +const UserContextMenuCommandInteraction = require('../../structures/UserContextMenuCommandInteraction'); const { Events, InteractionTypes, MessageComponentTypes, ApplicationCommandTypes } = require('../../util/Constants'); let deprecationEmitted = false; @@ -27,10 +27,10 @@ class InteractionCreateAction extends Action { InteractionType = CommandInteraction; break; case ApplicationCommandTypes.USER: - InteractionType = UserContextMenuInteraction; + InteractionType = UserContextMenuCommandInteraction; break; case ApplicationCommandTypes.MESSAGE: - InteractionType = MessageContextMenuInteraction; + InteractionType = MessageContextMenuCommandInteraction; break; default: client.emit( diff --git a/packages/discord.js/src/index.js b/packages/discord.js/src/index.js index eb99a644d..cc40bfa3c 100644 --- a/packages/discord.js/src/index.js +++ b/packages/discord.js/src/index.js @@ -73,7 +73,6 @@ exports.Application = require('./structures/interfaces/Application'); exports.ApplicationCommand = require('./structures/ApplicationCommand'); exports.AutocompleteInteraction = require('./structures/AutocompleteInteraction'); exports.Base = require('./structures/Base'); -exports.BaseCommandInteraction = require('./structures/BaseCommandInteraction'); exports.BaseGuild = require('./structures/BaseGuild'); exports.BaseGuildEmoji = require('./structures/BaseGuildEmoji'); exports.BaseGuildTextChannel = require('./structures/BaseGuildTextChannel'); @@ -82,13 +81,14 @@ exports.BaseMessageComponent = require('./structures/BaseMessageComponent'); exports.ButtonInteraction = require('./structures/ButtonInteraction'); exports.CategoryChannel = require('./structures/CategoryChannel'); exports.Channel = require('./structures/Channel').Channel; +exports.ChatInputCommandInteraction = require('./structures/ChatInputCommandInteraction'); exports.ClientApplication = require('./structures/ClientApplication'); exports.ClientPresence = require('./structures/ClientPresence'); exports.ClientUser = require('./structures/ClientUser'); -exports.Collector = require('./structures/interfaces/Collector'); exports.CommandInteraction = require('./structures/CommandInteraction'); +exports.Collector = require('./structures/interfaces/Collector'); exports.CommandInteractionOptionResolver = require('./structures/CommandInteractionOptionResolver'); -exports.ContextMenuInteraction = require('./structures/ContextMenuInteraction'); +exports.ContextMenuCommandInteraction = require('./structures/ContextMenuCommandInteraction'); exports.DMChannel = require('./structures/DMChannel'); exports.Emoji = require('./structures/Emoji').Emoji; exports.Guild = require('./structures/Guild').Guild; @@ -116,7 +116,7 @@ exports.MessageAttachment = require('./structures/MessageAttachment'); exports.MessageButton = require('./structures/MessageButton'); exports.MessageCollector = require('./structures/MessageCollector'); exports.MessageComponentInteraction = require('./structures/MessageComponentInteraction'); -exports.MessageContextMenuInteraction = require('./structures/MessageContextMenuInteraction'); +exports.MessageContextMenuCommandInteraction = require('./structures/MessageContextMenuCommandInteraction'); exports.MessageEmbed = require('./structures/MessageEmbed'); exports.MessageMentions = require('./structures/MessageMentions'); exports.MessagePayload = require('./structures/MessagePayload'); @@ -144,7 +144,7 @@ exports.ThreadChannel = require('./structures/ThreadChannel'); exports.ThreadMember = require('./structures/ThreadMember'); exports.Typing = require('./structures/Typing'); exports.User = require('./structures/User'); -exports.UserContextMenuInteraction = require('./structures/UserContextMenuInteraction'); +exports.UserContextMenuCommandInteraction = require('./structures/UserContextMenuCommandInteraction'); exports.VoiceChannel = require('./structures/VoiceChannel'); exports.VoiceRegion = require('./structures/VoiceRegion'); exports.VoiceState = require('./structures/VoiceState'); diff --git a/packages/discord.js/src/structures/BaseCommandInteraction.js b/packages/discord.js/src/structures/BaseCommandInteraction.js deleted file mode 100644 index 0ddaf6bfe..000000000 --- a/packages/discord.js/src/structures/BaseCommandInteraction.js +++ /dev/null @@ -1,195 +0,0 @@ -'use strict'; - -const { Collection } = require('@discordjs/collection'); -const Interaction = require('./Interaction'); -const InteractionWebhook = require('./InteractionWebhook'); -const InteractionResponses = require('./interfaces/InteractionResponses'); -const { ApplicationCommandOptionTypes } = require('../util/Constants'); - -/** - * Represents a command interaction. - * @extends {Interaction} - * @implements {InteractionResponses} - * @abstract - */ -class BaseCommandInteraction extends Interaction { - constructor(client, data) { - super(client, data); - - /** - * The id of the channel this interaction was sent in - * @type {Snowflake} - * @name BaseCommandInteraction#channelId - */ - - /** - * The invoked application command's id - * @type {Snowflake} - */ - this.commandId = data.data.id; - - /** - * The invoked application command's name - * @type {string} - */ - this.commandName = data.data.name; - - /** - * Whether the reply to this interaction has been deferred - * @type {boolean} - */ - this.deferred = false; - - /** - * Whether this interaction has already been replied to - * @type {boolean} - */ - this.replied = false; - - /** - * Whether the reply to this interaction is ephemeral - * @type {?boolean} - */ - this.ephemeral = null; - - /** - * An associated interaction webhook, can be used to further interact with this interaction - * @type {InteractionWebhook} - */ - this.webhook = new InteractionWebhook(this.client, this.applicationId, this.token); - } - - /** - * The invoked application command, if it was fetched before - * @type {?ApplicationCommand} - */ - get command() { - const id = this.commandId; - return this.guild?.commands.cache.get(id) ?? this.client.application.commands.cache.get(id) ?? null; - } - - /** - * Represents the resolved data of a received command interaction. - * @typedef {Object} CommandInteractionResolvedData - * @property {Collection} [users] The resolved users - * @property {Collection} [members] The resolved guild members - * @property {Collection} [roles] The resolved roles - * @property {Collection} [channels] The resolved channels - * @property {Collection} [messages] The resolved messages - */ - - /** - * Transforms the resolved received from the API. - * @param {APIInteractionDataResolved} resolved The received resolved objects - * @returns {CommandInteractionResolvedData} - * @private - */ - transformResolved({ members, users, channels, roles, messages }) { - const result = {}; - - if (members) { - result.members = new Collection(); - for (const [id, member] of Object.entries(members)) { - const user = users[id]; - result.members.set(id, this.guild?.members._add({ user, ...member }) ?? member); - } - } - - if (users) { - result.users = new Collection(); - for (const user of Object.values(users)) { - result.users.set(user.id, this.client.users._add(user)); - } - } - - if (roles) { - result.roles = new Collection(); - for (const role of Object.values(roles)) { - result.roles.set(role.id, this.guild?.roles._add(role) ?? role); - } - } - - if (channels) { - result.channels = new Collection(); - for (const channel of Object.values(channels)) { - result.channels.set(channel.id, this.client.channels._add(channel, this.guild) ?? channel); - } - } - - if (messages) { - result.messages = new Collection(); - for (const message of Object.values(messages)) { - result.messages.set(message.id, this.channel?.messages?._add(message) ?? message); - } - } - - return result; - } - - /** - * Represents an option of a received command interaction. - * @typedef {Object} CommandInteractionOption - * @property {string} name The name of the option - * @property {ApplicationCommandOptionType} type The type of the option - * @property {boolean} [autocomplete] Whether the option is an autocomplete option - * @property {string|number|boolean} [value] The value of the option - * @property {CommandInteractionOption[]} [options] Additional options if this option is a - * subcommand (group) - * @property {User} [user] The resolved user - * @property {GuildMember|APIGuildMember} [member] The resolved member - * @property {GuildChannel|ThreadChannel|APIChannel} [channel] The resolved channel - * @property {Role|APIRole} [role] The resolved role - */ - - /** - * Transforms an option received from the API. - * @param {APIApplicationCommandOption} option The received option - * @param {APIInteractionDataResolved} resolved The resolved interaction data - * @returns {CommandInteractionOption} - * @private - */ - transformOption(option, resolved) { - const result = { - name: option.name, - type: ApplicationCommandOptionTypes[option.type], - }; - - if ('value' in option) result.value = option.value; - if ('options' in option) result.options = option.options.map(opt => this.transformOption(opt, resolved)); - - if (resolved) { - const user = resolved.users?.[option.value]; - if (user) result.user = this.client.users._add(user); - - const member = resolved.members?.[option.value]; - if (member) result.member = this.guild?.members._add({ user, ...member }) ?? member; - - const channel = resolved.channels?.[option.value]; - if (channel) result.channel = this.client.channels._add(channel, this.guild) ?? channel; - - const role = resolved.roles?.[option.value]; - if (role) result.role = this.guild?.roles._add(role) ?? role; - } - - return result; - } - - // These are here only for documentation purposes - they are implemented by InteractionResponses - /* eslint-disable no-empty-function */ - deferReply() {} - reply() {} - fetchReply() {} - editReply() {} - deleteReply() {} - followUp() {} -} - -InteractionResponses.applyToClass(BaseCommandInteraction, ['deferUpdate', 'update']); - -module.exports = BaseCommandInteraction; - -/* eslint-disable max-len */ -/** - * @external APIInteractionDataResolved - * @see {@link https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-resolved-data-structure} - */ diff --git a/packages/discord.js/src/structures/ChatInputCommandInteraction.js b/packages/discord.js/src/structures/ChatInputCommandInteraction.js new file mode 100644 index 000000000..f00f6ccee --- /dev/null +++ b/packages/discord.js/src/structures/ChatInputCommandInteraction.js @@ -0,0 +1,41 @@ +'use strict'; + +const CommandInteraction = require('./CommandInteraction'); +const CommandInteractionOptionResolver = require('./CommandInteractionOptionResolver'); + +/** + * Represents a command interaction. + * @extends {BaseCommandInteraction} + */ +class ChatInputCommandInteraction extends CommandInteraction { + constructor(client, data) { + super(client, data); + + /** + * The options passed to the command. + * @type {CommandInteractionOptionResolver} + */ + this.options = new CommandInteractionOptionResolver( + this.client, + data.data.options?.map(option => this.transformOption(option, data.data.resolved)) ?? [], + this.transformResolved(data.data.resolved ?? {}), + ); + } + + /** + * Returns a string representation of the command interaction. + * This can then be copied by a user and executed again in a new command while keeping the option order. + * @returns {string} + */ + toString() { + const properties = [ + this.commandName, + this.options._group, + this.options._subcommand, + ...this.options._hoistedOptions.map(o => `${o.name}:${o.value}`), + ]; + return `/${properties.filter(Boolean).join(' ')}`; + } +} + +module.exports = ChatInputCommandInteraction; diff --git a/packages/discord.js/src/structures/CommandInteraction.js b/packages/discord.js/src/structures/CommandInteraction.js index c5dcfa2a3..5d966f96d 100644 --- a/packages/discord.js/src/structures/CommandInteraction.js +++ b/packages/discord.js/src/structures/CommandInteraction.js @@ -1,41 +1,195 @@ 'use strict'; -const BaseCommandInteraction = require('./BaseCommandInteraction'); -const CommandInteractionOptionResolver = require('./CommandInteractionOptionResolver'); +const { Collection } = require('@discordjs/collection'); +const Interaction = require('./Interaction'); +const InteractionWebhook = require('./InteractionWebhook'); +const InteractionResponses = require('./interfaces/InteractionResponses'); +const { ApplicationCommandOptionTypes } = require('../util/Constants'); /** * Represents a command interaction. - * @extends {BaseCommandInteraction} + * @extends {Interaction} + * @implements {InteractionResponses} + * @abstract */ -class CommandInteraction extends BaseCommandInteraction { +class CommandInteraction extends Interaction { constructor(client, data) { super(client, data); /** - * The options passed to the command. - * @type {CommandInteractionOptionResolver} + * The id of the channel this interaction was sent in + * @type {Snowflake} + * @name BaseCommandInteraction#channelId */ - this.options = new CommandInteractionOptionResolver( - this.client, - data.data.options?.map(option => this.transformOption(option, data.data.resolved)) ?? [], - this.transformResolved(data.data.resolved ?? {}), - ); + + /** + * The invoked application command's id + * @type {Snowflake} + */ + this.commandId = data.data.id; + + /** + * The invoked application command's name + * @type {string} + */ + this.commandName = data.data.name; + + /** + * Whether the reply to this interaction has been deferred + * @type {boolean} + */ + this.deferred = false; + + /** + * Whether this interaction has already been replied to + * @type {boolean} + */ + this.replied = false; + + /** + * Whether the reply to this interaction is ephemeral + * @type {?boolean} + */ + this.ephemeral = null; + + /** + * An associated interaction webhook, can be used to further interact with this interaction + * @type {InteractionWebhook} + */ + this.webhook = new InteractionWebhook(this.client, this.applicationId, this.token); } /** - * Returns a string representation of the command interaction. - * This can then be copied by a user and executed again in a new command while keeping the option order. - * @returns {string} + * The invoked application command, if it was fetched before + * @type {?ApplicationCommand} */ - toString() { - const properties = [ - this.commandName, - this.options._group, - this.options._subcommand, - ...this.options._hoistedOptions.map(o => `${o.name}:${o.value}`), - ]; - return `/${properties.filter(Boolean).join(' ')}`; + get command() { + const id = this.commandId; + return this.guild?.commands.cache.get(id) ?? this.client.application.commands.cache.get(id) ?? null; } + + /** + * Represents the resolved data of a received command interaction. + * @typedef {Object} CommandInteractionResolvedData + * @property {Collection} [users] The resolved users + * @property {Collection} [members] The resolved guild members + * @property {Collection} [roles] The resolved roles + * @property {Collection} [channels] The resolved channels + * @property {Collection} [messages] The resolved messages + */ + + /** + * Transforms the resolved received from the API. + * @param {APIInteractionDataResolved} resolved The received resolved objects + * @returns {CommandInteractionResolvedData} + * @private + */ + transformResolved({ members, users, channels, roles, messages }) { + const result = {}; + + if (members) { + result.members = new Collection(); + for (const [id, member] of Object.entries(members)) { + const user = users[id]; + result.members.set(id, this.guild?.members._add({ user, ...member }) ?? member); + } + } + + if (users) { + result.users = new Collection(); + for (const user of Object.values(users)) { + result.users.set(user.id, this.client.users._add(user)); + } + } + + if (roles) { + result.roles = new Collection(); + for (const role of Object.values(roles)) { + result.roles.set(role.id, this.guild?.roles._add(role) ?? role); + } + } + + if (channels) { + result.channels = new Collection(); + for (const channel of Object.values(channels)) { + result.channels.set(channel.id, this.client.channels._add(channel, this.guild) ?? channel); + } + } + + if (messages) { + result.messages = new Collection(); + for (const message of Object.values(messages)) { + result.messages.set(message.id, this.channel?.messages?._add(message) ?? message); + } + } + + return result; + } + + /** + * Represents an option of a received command interaction. + * @typedef {Object} CommandInteractionOption + * @property {string} name The name of the option + * @property {ApplicationCommandOptionType} type The type of the option + * @property {boolean} [autocomplete] Whether the option is an autocomplete option + * @property {string|number|boolean} [value] The value of the option + * @property {CommandInteractionOption[]} [options] Additional options if this option is a + * subcommand (group) + * @property {User} [user] The resolved user + * @property {GuildMember|APIGuildMember} [member] The resolved member + * @property {GuildChannel|ThreadChannel|APIChannel} [channel] The resolved channel + * @property {Role|APIRole} [role] The resolved role + */ + + /** + * Transforms an option received from the API. + * @param {APIApplicationCommandOption} option The received option + * @param {APIInteractionDataResolved} resolved The resolved interaction data + * @returns {CommandInteractionOption} + * @private + */ + transformOption(option, resolved) { + const result = { + name: option.name, + type: ApplicationCommandOptionTypes[option.type], + }; + + if ('value' in option) result.value = option.value; + if ('options' in option) result.options = option.options.map(opt => this.transformOption(opt, resolved)); + + if (resolved) { + const user = resolved.users?.[option.value]; + if (user) result.user = this.client.users._add(user); + + const member = resolved.members?.[option.value]; + if (member) result.member = this.guild?.members._add({ user, ...member }) ?? member; + + const channel = resolved.channels?.[option.value]; + if (channel) result.channel = this.client.channels._add(channel, this.guild) ?? channel; + + const role = resolved.roles?.[option.value]; + if (role) result.role = this.guild?.roles._add(role) ?? role; + } + + return result; + } + + // These are here only for documentation purposes - they are implemented by InteractionResponses + /* eslint-disable no-empty-function */ + deferReply() {} + reply() {} + fetchReply() {} + editReply() {} + deleteReply() {} + followUp() {} } +InteractionResponses.applyToClass(CommandInteraction, ['deferUpdate', 'update']); + module.exports = CommandInteraction; + +/* eslint-disable max-len */ +/** + * @external APIInteractionDataResolved + * @see {@link https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-resolved-data-structure} + */ diff --git a/packages/discord.js/src/structures/ContextMenuInteraction.js b/packages/discord.js/src/structures/ContextMenuCommandInteraction.js similarity index 89% rename from packages/discord.js/src/structures/ContextMenuInteraction.js rename to packages/discord.js/src/structures/ContextMenuCommandInteraction.js index f4f6ef47d..46d352e67 100644 --- a/packages/discord.js/src/structures/ContextMenuInteraction.js +++ b/packages/discord.js/src/structures/ContextMenuCommandInteraction.js @@ -1,14 +1,14 @@ 'use strict'; -const BaseCommandInteraction = require('./BaseCommandInteraction'); +const CommandInteraction = require('./CommandInteraction'); const CommandInteractionOptionResolver = require('./CommandInteractionOptionResolver'); const { ApplicationCommandOptionTypes, ApplicationCommandTypes } = require('../util/Constants'); /** * Represents a context menu interaction. - * @extends {BaseCommandInteraction} + * @extends {CommandInteraction} */ -class ContextMenuInteraction extends BaseCommandInteraction { +class ContextMenuCommandInteraction extends CommandInteraction { constructor(client, data) { super(client, data); /** @@ -62,4 +62,4 @@ class ContextMenuInteraction extends BaseCommandInteraction { } } -module.exports = ContextMenuInteraction; +module.exports = ContextMenuCommandInteraction; diff --git a/packages/discord.js/src/structures/Interaction.js b/packages/discord.js/src/structures/Interaction.js index 7e54a64d0..4da57f31c 100644 --- a/packages/discord.js/src/structures/Interaction.js +++ b/packages/discord.js/src/structures/Interaction.js @@ -136,44 +136,44 @@ class Interaction extends Base { return Boolean(this.guildId && !this.guild && this.member); } - /** - * Indicates whether this interaction is a {@link BaseCommandInteraction}. - * @returns {boolean} - */ - isApplicationCommand() { - return InteractionTypes[this.type] === InteractionTypes.APPLICATION_COMMAND; - } - /** * Indicates whether this interaction is a {@link CommandInteraction}. * @returns {boolean} */ isCommand() { + return InteractionTypes[this.type] === InteractionTypes.APPLICATION_COMMAND; + } + + /** + * Indicates whether this interaction is a {@link ChatInputCommandInteraction}. + * @returns {boolean} + */ + isChatInputCommand() { return InteractionTypes[this.type] === InteractionTypes.APPLICATION_COMMAND && typeof this.targetId === 'undefined'; } /** - * Indicates whether this interaction is a {@link ContextMenuInteraction} + * Indicates whether this interaction is a {@link ContextMenuCommandInteraction} * @returns {boolean} */ - isContextMenu() { + isContextMenuCommand() { return InteractionTypes[this.type] === InteractionTypes.APPLICATION_COMMAND && typeof this.targetId !== 'undefined'; } /** - * Indicates whether this interaction is a {@link UserContextMenuInteraction} + * Indicates whether this interaction is a {@link UserContextMenuCommandInteraction} * @returns {boolean} */ - isUserContextMenu() { - return this.isContextMenu() && ApplicationCommandTypes[this.targetType] === ApplicationCommandTypes.USER; + isUserContextMenuCommand() { + return this.isContextMenuCommand() && ApplicationCommandTypes[this.targetType] === ApplicationCommandTypes.USER; } /** - * Indicates whether this interaction is a {@link MessageContextMenuInteraction} + * Indicates whether this interaction is a {@link MessageContextMenuCommandInteraction} * @returns {boolean} */ - isMessageContextMenu() { - return this.isContextMenu() && ApplicationCommandTypes[this.targetType] === ApplicationCommandTypes.MESSAGE; + isMessageContextMenuCommand() { + return this.isContextMenuCommand() && ApplicationCommandTypes[this.targetType] === ApplicationCommandTypes.MESSAGE; } /** diff --git a/packages/discord.js/src/structures/MessageContextMenuInteraction.js b/packages/discord.js/src/structures/MessageContextMenuCommandInteraction.js similarity index 58% rename from packages/discord.js/src/structures/MessageContextMenuInteraction.js rename to packages/discord.js/src/structures/MessageContextMenuCommandInteraction.js index 0855f30ba..6b839db81 100644 --- a/packages/discord.js/src/structures/MessageContextMenuInteraction.js +++ b/packages/discord.js/src/structures/MessageContextMenuCommandInteraction.js @@ -1,12 +1,12 @@ 'use strict'; -const ContextMenuInteraction = require('./ContextMenuInteraction'); +const ContextMenuCommandInteraction = require('./ContextMenuInteraction'); /** * Represents a message context menu interaction. * @extends {ContextMenuInteraction} */ -class MessageContextMenuInteraction extends ContextMenuInteraction { +class MessageContextMenuCommandInteraction extends ContextMenuCommandInteraction { /** * The message this interaction was sent from * @type {Message|APIMessage} @@ -17,4 +17,4 @@ class MessageContextMenuInteraction extends ContextMenuInteraction { } } -module.exports = MessageContextMenuInteraction; +module.exports = MessageContextMenuCommandInteraction; diff --git a/packages/discord.js/src/structures/UserContextMenuInteraction.js b/packages/discord.js/src/structures/UserContextMenuCommandInteraction.js similarity index 62% rename from packages/discord.js/src/structures/UserContextMenuInteraction.js rename to packages/discord.js/src/structures/UserContextMenuCommandInteraction.js index 98dad00fc..320b39419 100644 --- a/packages/discord.js/src/structures/UserContextMenuInteraction.js +++ b/packages/discord.js/src/structures/UserContextMenuCommandInteraction.js @@ -1,12 +1,12 @@ 'use strict'; -const ContextMenuInteraction = require('./ContextMenuInteraction'); +const ContextMenuCommandInteraction = require('./ContextMenuInteraction'); /** * Represents a user context menu interaction. - * @extends {ContextMenuInteraction} + * @extends {ContextMenuCommandInteraction} */ -class UserContextMenuInteraction extends ContextMenuInteraction { +class UserContextMenuCommandInteraction extends ContextMenuCommandInteraction { /** * The user this interaction was sent from * @type {User} @@ -26,4 +26,4 @@ class UserContextMenuInteraction extends ContextMenuInteraction { } } -module.exports = UserContextMenuInteraction; +module.exports = UserContextMenuCommandInteraction; diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 5552f2055..f17ca96a3 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -320,7 +320,7 @@ export type GuildCacheMessage = CacheTypeReducer< Message | APIMessage >; -export abstract class BaseCommandInteraction extends Interaction { +export abstract class CommandInteraction extends Interaction { public readonly command: ApplicationCommand | ApplicationCommand<{ guild: GuildResolvable }> | null; public options: Omit< CommandInteractionOptionResolver, @@ -343,9 +343,9 @@ export abstract class BaseCommandInteraction; - public inCachedGuild(): this is BaseCommandInteraction<'cached'>; - public inRawGuild(): this is BaseCommandInteraction<'raw'>; + public inGuild(): this is CommandInteraction<'raw' | 'cached'>; + public inCachedGuild(): this is CommandInteraction<'cached'>; + public inRawGuild(): this is CommandInteraction<'raw'>; public deferReply(options: InteractionDeferReplyOptions & { fetchReply: true }): Promise>; public deferReply(options?: InteractionDeferReplyOptions): Promise; public deleteReply(): Promise; @@ -720,11 +720,11 @@ export interface ApplicationCommandInteractionOptionResolver['member' | 'role' | 'user']> | null; } -export class CommandInteraction extends BaseCommandInteraction { +export class ChatInputCommandInteraction extends CommandInteraction { public options: Omit, 'getMessage' | 'getFocused'>; - public inGuild(): this is CommandInteraction<'raw' | 'cached'>; - public inCachedGuild(): this is CommandInteraction<'cached'>; - public inRawGuild(): this is CommandInteraction<'raw'>; + public inGuild(): this is ChatInputCommandInteraction<'raw' | 'cached'>; + public inCachedGuild(): this is ChatInputCommandInteraction<'cached'>; + public inRawGuild(): this is ChatInputCommandInteraction<'raw'>; public toString(): string; } @@ -800,7 +800,7 @@ export class CommandInteractionOptionResolver extends BaseCommandInteraction { +export class ContextMenuCommandInteraction extends CommandInteraction { public options: Omit< CommandInteractionOptionResolver, | 'getFocused' @@ -816,9 +816,9 @@ export class ContextMenuInteraction extend >; public targetId: Snowflake; public targetType: Exclude; - public inGuild(): this is ContextMenuInteraction<'raw' | 'cached'>; - public inCachedGuild(): this is ContextMenuInteraction<'cached'>; - public inRawGuild(): this is ContextMenuInteraction<'raw'>; + public inGuild(): this is ContextMenuCommandInteraction<'raw' | 'cached'>; + public inCachedGuild(): this is ContextMenuCommandInteraction<'cached'>; + public inRawGuild(): this is ContextMenuCommandInteraction<'raw'>; private resolveContextMenuOptions(data: APIApplicationCommandInteractionData): CommandInteractionOption[]; } @@ -1328,13 +1328,16 @@ export class Interaction extends Base { public inGuild(): this is Interaction<'raw' | 'cached'>; public inCachedGuild(): this is Interaction<'cached'>; public inRawGuild(): this is Interaction<'raw'>; - public isApplicationCommand(): this is BaseCommandInteraction; + public isApplicationCommand(): this is CommandInteraction; public isButton(): this is ButtonInteraction; public isCommand(): this is CommandInteraction; + public isChatInputCommand(): this is ChatInputCommandInteraction; + public isContextMenuCommand(): this is ContextMenuCommandInteraction; + public isMessageContextMenuCommand(): this is MessageContextMenuCommandInteraction; public isAutocomplete(): this is AutocompleteInteraction; - public isContextMenu(): this is ContextMenuInteraction; - public isUserContextMenu(): this is UserContextMenuInteraction; - public isMessageContextMenu(): this is MessageContextMenuInteraction; + public isContextMenu(): this is ContextMenuCommandInteraction; + public isUserContextMenu(): this is UserContextMenuCommandInteraction; + public isMessageContextMenu(): this is MessageContextMenuCommandInteraction; public isMessageComponent(): this is MessageComponentInteraction; public isSelectMenu(): this is SelectMenuInteraction; } @@ -1656,13 +1659,13 @@ export class MessageComponentInteraction e public static resolveType(type: MessageComponentTypeResolvable): MessageComponentType; } -export class MessageContextMenuInteraction< +export class MessageContextMenuCommandInteraction< Cached extends CacheType = CacheType, -> extends ContextMenuInteraction { +> extends ContextMenuCommandInteraction { public readonly targetMessage: NonNullable['message']>; - public inGuild(): this is MessageContextMenuInteraction<'raw' | 'cached'>; - public inCachedGuild(): this is MessageContextMenuInteraction<'cached'>; - public inRawGuild(): this is MessageContextMenuInteraction<'raw'>; + public inGuild(): this is MessageContextMenuCommandInteraction<'raw' | 'cached'>; + public inCachedGuild(): this is MessageContextMenuCommandInteraction<'cached'>; + public inRawGuild(): this is MessageContextMenuCommandInteraction<'raw'>; } export class MessageEmbed { @@ -2397,12 +2400,14 @@ export class User extends PartialTextBasedChannel(Base) { public toString(): UserMention; } -export class UserContextMenuInteraction extends ContextMenuInteraction { +export class UserContextMenuCommandInteraction< + Cached extends CacheType = CacheType, +> extends ContextMenuCommandInteraction { public readonly targetUser: User; public readonly targetMember: CacheTypeReducer; - public inGuild(): this is UserContextMenuInteraction<'raw' | 'cached'>; - public inCachedGuild(): this is UserContextMenuInteraction<'cached'>; - public inRawGuild(): this is UserContextMenuInteraction<'raw'>; + public inGuild(): this is UserContextMenuCommandInteraction<'raw' | 'cached'>; + public inCachedGuild(): this is UserContextMenuCommandInteraction<'cached'>; + public inRawGuild(): this is UserContextMenuCommandInteraction<'raw'>; } export class UserFlags extends BitField { diff --git a/packages/discord.js/typings/index.test-d.ts b/packages/discord.js/typings/index.test-d.ts index 52477639b..6ad705476 100644 --- a/packages/discord.js/typings/index.test-d.ts +++ b/packages/discord.js/typings/index.test-d.ts @@ -19,7 +19,7 @@ import { ApplicationCommandResolvable, ApplicationCommandSubCommandData, ApplicationCommandSubGroupData, - BaseCommandInteraction, + CommandInteraction, ButtonInteraction, CacheType, CategoryChannel, @@ -28,12 +28,12 @@ import { ClientUser, CloseEvent, Collection, - CommandInteraction, + ChatInputCommandInteraction, CommandInteractionOption, CommandInteractionOptionResolver, CommandOptionNonChoiceResolvableType, Constants, - ContextMenuInteraction, + ContextMenuCommandInteraction, DMChannel, Guild, GuildApplicationCommandManager, @@ -980,7 +980,7 @@ client.on('interactionCreate', interaction => { client.on('interactionCreate', async interaction => { if (interaction.inCachedGuild()) { expectAssignable(interaction.member); - expectNotType>(interaction); + expectNotType>(interaction); expectAssignable(interaction); } else if (interaction.inRawGuild()) { expectAssignable(interaction.member); @@ -991,16 +991,16 @@ client.on('interactionCreate', async interaction => { } if (interaction.isContextMenu()) { - expectType(interaction); + expectType(interaction); if (interaction.inCachedGuild()) { - expectAssignable(interaction); + expectAssignable(interaction); expectAssignable(interaction.guild); - expectAssignable>(interaction); + expectAssignable>(interaction); } else if (interaction.inRawGuild()) { - expectAssignable(interaction); + expectAssignable(interaction); expectType(interaction.guild); } else if (interaction.inGuild()) { - expectAssignable(interaction); + expectAssignable(interaction); expectType(interaction.guild); } } @@ -1091,10 +1091,10 @@ client.on('interactionCreate', async interaction => { } } - if (interaction.isCommand()) { + if (interaction.isChatInputCommand()) { if (interaction.inRawGuild()) { expectNotAssignable>(interaction); - expectAssignable(interaction); + expectAssignable(interaction); expectType>(interaction.reply({ fetchReply: true })); expectType(interaction.options.getMember('test')); expectType(interaction.options.getMember('test', true)); @@ -1109,7 +1109,7 @@ client.on('interactionCreate', async interaction => { expectType>(btn); expectType(interaction.options.getMember('test')); - expectAssignable(interaction); + expectAssignable(interaction); expectType>>(interaction.reply({ fetchReply: true })); expectType(interaction.options.getChannel('test', true)); @@ -1117,7 +1117,7 @@ client.on('interactionCreate', async interaction => { } else { // @ts-expect-error consumeCachedCommand(interaction); - expectType(interaction); + expectType(interaction); expectType>(interaction.reply({ fetchReply: true })); expectType(interaction.options.getMember('test')); expectType(interaction.options.getMember('test', true)); @@ -1126,7 +1126,7 @@ client.on('interactionCreate', async interaction => { expectType(interaction.options.getRole('test', true)); } - expectType(interaction); + expectType(interaction); expectType, 'getFocused' | 'getMessage'>>(interaction.options); expectType(interaction.options.data);