From 4fe063f0d00562b5987447a6b2b5900b64faec96 Mon Sep 17 00:00:00 2001 From: GrapeColor <40069549+GrapeColor@users.noreply.github.com> Date: Wed, 1 Dec 2021 20:31:37 +0900 Subject: [PATCH] feat: add `UserContextMenuInteraction` and `MessageContextMenuInteraction` (#7003) Co-authored-by: Rodry <38259440+ImRodry@users.noreply.github.com> Co-authored-by: Suneet Tipirneni <77477100+suneettipirneni@users.noreply.github.com> Co-authored-by: Vlad Frangu Co-authored-by: GrapeColor --- src/client/actions/InteractionCreate.js | 7 +++-- src/index.js | 2 ++ src/structures/Interaction.js | 18 +++++++++++- .../MessageContextMenuInteraction.js | 20 +++++++++++++ src/structures/UserContextMenuInteraction.js | 29 +++++++++++++++++++ typings/index.d.ts | 17 +++++++++++ 6 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 src/structures/MessageContextMenuInteraction.js create mode 100644 src/structures/UserContextMenuInteraction.js diff --git a/src/client/actions/InteractionCreate.js b/src/client/actions/InteractionCreate.js index 7a4338fbb476..2671c8a9ce7c 100644 --- a/src/client/actions/InteractionCreate.js +++ b/src/client/actions/InteractionCreate.js @@ -4,8 +4,9 @@ const Action = require('./Action'); const AutocompleteInteraction = require('../../structures/AutocompleteInteraction'); const ButtonInteraction = require('../../structures/ButtonInteraction'); const CommandInteraction = require('../../structures/CommandInteraction'); -const ContextMenuInteraction = require('../../structures/ContextMenuInteraction'); +const MessageContextMenuInteraction = require('../../structures/MessageContextMenuInteraction'); const SelectMenuInteraction = require('../../structures/SelectMenuInteraction'); +const UserContextMenuInteraction = require('../../structures/UserContextMenuInteraction'); const { Events, InteractionTypes, MessageComponentTypes, ApplicationCommandTypes } = require('../../util/Constants'); let deprecationEmitted = false; @@ -25,8 +26,10 @@ class InteractionCreateAction extends Action { InteractionType = CommandInteraction; break; case ApplicationCommandTypes.USER: + InteractionType = UserContextMenuInteraction; + break; case ApplicationCommandTypes.MESSAGE: - InteractionType = ContextMenuInteraction; + InteractionType = MessageContextMenuInteraction; break; default: client.emit( diff --git a/src/index.js b/src/index.js index aaf5f970304b..5561c7aa3818 100644 --- a/src/index.js +++ b/src/index.js @@ -113,6 +113,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.MessageEmbed = require('./structures/MessageEmbed'); exports.MessageMentions = require('./structures/MessageMentions'); exports.MessagePayload = require('./structures/MessagePayload'); @@ -140,6 +141,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.VoiceChannel = require('./structures/VoiceChannel'); exports.VoiceRegion = require('./structures/VoiceRegion'); exports.VoiceState = require('./structures/VoiceState'); diff --git a/src/structures/Interaction.js b/src/structures/Interaction.js index 99c6441fa0de..d82420c069f6 100644 --- a/src/structures/Interaction.js +++ b/src/structures/Interaction.js @@ -1,7 +1,7 @@ 'use strict'; const Base = require('./Base'); -const { InteractionTypes, MessageComponentTypes } = require('../util/Constants'); +const { InteractionTypes, MessageComponentTypes, ApplicationCommandTypes } = require('../util/Constants'); const Permissions = require('../util/Permissions'); const SnowflakeUtil = require('../util/SnowflakeUtil'); @@ -160,6 +160,22 @@ class Interaction extends Base { return InteractionTypes[this.type] === InteractionTypes.APPLICATION_COMMAND && typeof this.targetId !== 'undefined'; } + /** + * Indicates whether this interaction is a {@link UserContextMenuInteraction} + * @returns {boolean} + */ + isUserContextMenu() { + return this.isContextMenu() && ApplicationCommandTypes[this.targetType] === ApplicationCommandTypes.USER; + } + + /** + * Indicates whether this interaction is a {@link MessageContextMenuInteraction} + * @returns {boolean} + */ + isMessageContextMenu() { + return this.isContextMenu() && ApplicationCommandTypes[this.targetType] === ApplicationCommandTypes.MESSAGE; + } + /** * Indicates whether this interaction is an {@link AutocompleteInteraction} * @returns {boolean} diff --git a/src/structures/MessageContextMenuInteraction.js b/src/structures/MessageContextMenuInteraction.js new file mode 100644 index 000000000000..0855f30ba607 --- /dev/null +++ b/src/structures/MessageContextMenuInteraction.js @@ -0,0 +1,20 @@ +'use strict'; + +const ContextMenuInteraction = require('./ContextMenuInteraction'); + +/** + * Represents a message context menu interaction. + * @extends {ContextMenuInteraction} + */ +class MessageContextMenuInteraction extends ContextMenuInteraction { + /** + * The message this interaction was sent from + * @type {Message|APIMessage} + * @readonly + */ + get targetMessage() { + return this.options.getMessage('message'); + } +} + +module.exports = MessageContextMenuInteraction; diff --git a/src/structures/UserContextMenuInteraction.js b/src/structures/UserContextMenuInteraction.js new file mode 100644 index 000000000000..98dad00fc93d --- /dev/null +++ b/src/structures/UserContextMenuInteraction.js @@ -0,0 +1,29 @@ +'use strict'; + +const ContextMenuInteraction = require('./ContextMenuInteraction'); + +/** + * Represents a user context menu interaction. + * @extends {ContextMenuInteraction} + */ +class UserContextMenuInteraction extends ContextMenuInteraction { + /** + * The user this interaction was sent from + * @type {User} + * @readonly + */ + get targetUser() { + return this.options.getUser('user'); + } + + /** + * The member this interaction was sent from + * @type {?(GuildMember|APIGuildMember)} + * @readonly + */ + get targetMember() { + return this.options.getMember('user'); + } +} + +module.exports = UserContextMenuInteraction; diff --git a/typings/index.d.ts b/typings/index.d.ts index bd0587d10c3b..123991aeb6ab 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1227,6 +1227,8 @@ export class Interaction extends Base { public isCommand(): this is CommandInteraction; public isAutocomplete(): this is AutocompleteInteraction; public isContextMenu(): this is ContextMenuInteraction; + public isUserContextMenu(): this is UserContextMenuInteraction; + public isMessageContextMenu(): this is MessageContextMenuInteraction; public isMessageComponent(): this is MessageComponentInteraction; public isSelectMenu(): this is SelectMenuInteraction; } @@ -1536,6 +1538,13 @@ export class MessageComponentInteraction e public static resolveType(type: MessageComponentTypeResolvable): MessageComponentType; } +export class MessageContextMenuInteraction extends ContextMenuInteraction { + public readonly targetMessage: CacheTypeReducer; + public inGuild(): this is MessageContextMenuInteraction<'present'>; + public inCachedGuild(): this is MessageContextMenuInteraction<'cached'>; + public inRawGuild(): this is MessageContextMenuInteraction<'raw'>; +} + export class MessageEmbed { private _fieldEquals(field: EmbedField, other: EmbedField): boolean; @@ -2188,6 +2197,14 @@ export class User extends PartialTextBasedChannel(Base) { public toString(): UserMention; } +export class UserContextMenuInteraction extends ContextMenuInteraction { + public readonly targetUser: User; + public readonly targetMember: CacheTypeReducer; + public inGuild(): this is UserContextMenuInteraction<'present'>; + public inCachedGuild(): this is UserContextMenuInteraction<'cached'>; + public inRawGuild(): this is UserContextMenuInteraction<'raw'>; +} + export class UserFlags extends BitField { public static FLAGS: Record; public static resolve(bit?: BitFieldResolvable): number;