From 030d263a9e018a766c5f399624fe4f8ec2b7349c Mon Sep 17 00:00:00 2001 From: BorgerKing <38166539+RDambrosio016@users.noreply.github.com> Date: Sat, 25 Jan 2020 14:00:53 -0500 Subject: [PATCH] feat(MessageReaction): add remove method and Client#messageReactionRemoveEmoji (#3723) * Add support for MessageReaction#remove and MESSAGE_REACTION_REMOVE_EMOJI * Remove reaction from cache Co-Authored-By: matthewfripp <50251454+matthewfripp@users.noreply.github.com> * fix: message may be partial * Clarify what the event entails * Document client in MessageReaction Co-Authored-By: SpaceEEC * await the REST call * Add MessageReaction#remove to typings Co-authored-by: matthewfripp <50251454+matthewfripp@users.noreply.github.com> Co-authored-by: SpaceEEC --- src/client/actions/Action.js | 2 +- src/client/actions/ActionsManager.js | 1 + .../actions/MessageReactionRemoveEmoji.js | 28 +++++++++++++++++++ .../handlers/MESSAGE_REACTION_REMOVE_EMOJI.js | 5 ++++ src/structures/MessageReaction.js | 17 +++++++++++ src/util/Constants.js | 2 ++ typings/index.d.ts | 2 ++ 7 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/client/actions/MessageReactionRemoveEmoji.js create mode 100644 src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_EMOJI.js diff --git a/src/client/actions/Action.js b/src/client/actions/Action.js index bc9ed267ade9..ce4fd6db2221 100644 --- a/src/client/actions/Action.js +++ b/src/client/actions/Action.js @@ -54,7 +54,7 @@ class GenericAction { return this.getPayload({ emoji: data.emoji, count: message.partial ? null : 0, - me: user.id === this.client.user.id, + me: user ? user.id === this.client.user.id : false, }, message.reactions, id, PartialTypes.REACTION); } diff --git a/src/client/actions/ActionsManager.js b/src/client/actions/ActionsManager.js index 730f507c0b68..7e1df121f81e 100644 --- a/src/client/actions/ActionsManager.js +++ b/src/client/actions/ActionsManager.js @@ -11,6 +11,7 @@ class ActionsManager { this.register(require('./MessageReactionAdd')); this.register(require('./MessageReactionRemove')); this.register(require('./MessageReactionRemoveAll')); + this.register(require('./MessageReactionRemoveEmoji')); this.register(require('./ChannelCreate')); this.register(require('./ChannelDelete')); this.register(require('./ChannelUpdate')); diff --git a/src/client/actions/MessageReactionRemoveEmoji.js b/src/client/actions/MessageReactionRemoveEmoji.js new file mode 100644 index 000000000000..ab0eaa7708ea --- /dev/null +++ b/src/client/actions/MessageReactionRemoveEmoji.js @@ -0,0 +1,28 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); + +class MessageReactionRemoveEmoji extends Action { + handle(data) { + const channel = this.getChannel(data); + if (!channel || channel.type === 'voice') return false; + + const message = this.getMessage(data, channel); + if (!message) return false; + + const reaction = this.getReaction(data, message); + if (!reaction) return false; + if (!message.partial) message.reactions.delete(reaction.emoji.id || reaction.emoji.name); + + /** + * Emitted when a bot removes an emoji reaction from a cached message. + * @event Client#messageReactionRemoveEmoji + * @param {MessageReaction} reaction The reaction that was removed + */ + this.client.emit(Events.MESSAGE_REACTION_REMOVE_EMOJI, reaction); + return { reaction }; + } +} + +module.exports = MessageReactionRemoveEmoji; diff --git a/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_EMOJI.js b/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_EMOJI.js new file mode 100644 index 000000000000..579444c97da5 --- /dev/null +++ b/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_EMOJI.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.MessageReactionRemoveEmoji.handle(packet.d); +}; diff --git a/src/structures/MessageReaction.js b/src/structures/MessageReaction.js index f32f0843cd45..5cb9210fb77e 100644 --- a/src/structures/MessageReaction.js +++ b/src/structures/MessageReaction.js @@ -15,6 +15,13 @@ class MessageReaction { * @param {Message} message The message the reaction refers to */ constructor(client, data, message) { + /** + * The client that instantiated this message reaction + * @name MessageReaction#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: client }); /** * The message that this reaction refers to * @type {Message} @@ -47,6 +54,16 @@ class MessageReaction { if (this.count == undefined) this.count = data.count; } + /** + * Removes all users from this reaction. + * @returns {Promise} + */ + async remove() { + await this.client.api.channels(this.message.channel.id).messages(this.message.id).reactions(this._emoji.identifier) + .delete(); + return this; + } + /** * The emoji of this reaction, either an GuildEmoji object for known custom emojis, or a ReactionEmoji * object which has fewer properties. Whatever the prototype of the emoji, it will still have diff --git a/src/util/Constants.js b/src/util/Constants.js index a8f93a856b18..0417d881c5ea 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -262,6 +262,7 @@ exports.Events = { MESSAGE_REACTION_ADD: 'messageReactionAdd', MESSAGE_REACTION_REMOVE: 'messageReactionRemove', MESSAGE_REACTION_REMOVE_ALL: 'messageReactionRemoveAll', + MESSAGE_REACTION_REMOVE_EMOJI: 'messageReactionRemoveEmoji', USER_UPDATE: 'userUpdate', PRESENCE_UPDATE: 'presenceUpdate', VOICE_SERVER_UPDATE: 'voiceServerUpdate', @@ -379,6 +380,7 @@ exports.WSEvents = keyMirror([ 'MESSAGE_REACTION_ADD', 'MESSAGE_REACTION_REMOVE', 'MESSAGE_REACTION_REMOVE_ALL', + 'MESSAGE_REACTION_REMOVE_EMOJI', 'USER_UPDATE', 'PRESENCE_UPDATE', 'TYPING_START', diff --git a/typings/index.d.ts b/typings/index.d.ts index fc23f027fd5a..8154f3f0f4a4 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -191,6 +191,7 @@ declare module 'discord.js' { public on(event: 'inviteCreate' | 'inviteDelete', listener: (invite: Invite) => void): this; public on(event: 'guildIntegrationsUpdate', listener: (guild: Guild) => void): this; public on(event: 'message' | 'messageDelete' | 'messageReactionRemoveAll', listener: (message: Message | PartialMessage) => void): this; + public on(event: 'messageReactionRemoveEmoji', listener: (reaction: MessageReaction) => void): this; public on(event: 'messageDeleteBulk', listener: (messages: Collection) => void): this; public on(event: 'messageReactionAdd' | 'messageReactionRemove', listener: (messageReaction: MessageReaction, user: User | PartialUser) => void): this; public on(event: 'messageUpdate', listener: (oldMessage: Message | PartialMessage, newMessage: Message | PartialMessage) => void): this; @@ -1113,6 +1114,7 @@ declare module 'discord.js' { public message: Message; public readonly partial: boolean; public users: ReactionUserStore; + public remove(): Promise; public fetch(): Promise; public toJSON(): object; }