summaryrefslogtreecommitdiff
path: root/node_modules/discord.js/src/structures/ReactionCollector.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/discord.js/src/structures/ReactionCollector.js')
-rw-r--r--node_modules/discord.js/src/structures/ReactionCollector.js229
1 files changed, 229 insertions, 0 deletions
diff --git a/node_modules/discord.js/src/structures/ReactionCollector.js b/node_modules/discord.js/src/structures/ReactionCollector.js
new file mode 100644
index 0000000..924b33b
--- /dev/null
+++ b/node_modules/discord.js/src/structures/ReactionCollector.js
@@ -0,0 +1,229 @@
+'use strict';
+
+const { Collection } = require('@discordjs/collection');
+const Collector = require('./interfaces/Collector');
+const Events = require('../util/Events');
+
+/**
+ * @typedef {CollectorOptions} ReactionCollectorOptions
+ * @property {number} max The maximum total amount of reactions to collect
+ * @property {number} maxEmojis The maximum number of emojis to collect
+ * @property {number} maxUsers The maximum number of users to react
+ */
+
+/**
+ * Collects reactions on messages.
+ * Will automatically stop if the message ({@link Client#event:messageDelete messageDelete} or
+ * {@link Client#event:messageDeleteBulk messageDeleteBulk}),
+ * channel ({@link Client#event:channelDelete channelDelete}),
+ * thread ({@link Client#event:threadDelete threadDelete}), or
+ * guild ({@link Client#event:guildDelete guildDelete}) is deleted.
+ * @extends {Collector}
+ */
+class ReactionCollector extends Collector {
+ /**
+ * @param {Message} message The message upon which to collect reactions
+ * @param {ReactionCollectorOptions} [options={}] The options to apply to this collector
+ */
+ constructor(message, options = {}) {
+ super(message.client, options);
+
+ /**
+ * The message upon which to collect reactions
+ * @type {Message}
+ */
+ this.message = message;
+
+ /**
+ * The users that have reacted to this message
+ * @type {Collection}
+ */
+ this.users = new Collection();
+
+ /**
+ * The total number of reactions collected
+ * @type {number}
+ */
+ this.total = 0;
+
+ this.empty = this.empty.bind(this);
+ this._handleChannelDeletion = this._handleChannelDeletion.bind(this);
+ this._handleThreadDeletion = this._handleThreadDeletion.bind(this);
+ this._handleGuildDeletion = this._handleGuildDeletion.bind(this);
+ this._handleMessageDeletion = this._handleMessageDeletion.bind(this);
+
+ const bulkDeleteListener = messages => {
+ if (messages.has(this.message.id)) this.stop('messageDelete');
+ };
+
+ this.client.incrementMaxListeners();
+ this.client.on(Events.MessageReactionAdd, this.handleCollect);
+ this.client.on(Events.MessageReactionRemove, this.handleDispose);
+ this.client.on(Events.MessageReactionRemoveAll, this.empty);
+ this.client.on(Events.MessageDelete, this._handleMessageDeletion);
+ this.client.on(Events.MessageBulkDelete, bulkDeleteListener);
+ this.client.on(Events.ChannelDelete, this._handleChannelDeletion);
+ this.client.on(Events.ThreadDelete, this._handleThreadDeletion);
+ this.client.on(Events.GuildDelete, this._handleGuildDeletion);
+
+ this.once('end', () => {
+ this.client.removeListener(Events.MessageReactionAdd, this.handleCollect);
+ this.client.removeListener(Events.MessageReactionRemove, this.handleDispose);
+ this.client.removeListener(Events.MessageReactionRemoveAll, this.empty);
+ this.client.removeListener(Events.MessageDelete, this._handleMessageDeletion);
+ this.client.removeListener(Events.MessageBulkDelete, bulkDeleteListener);
+ this.client.removeListener(Events.ChannelDelete, this._handleChannelDeletion);
+ this.client.removeListener(Events.ThreadDelete, this._handleThreadDeletion);
+ this.client.removeListener(Events.GuildDelete, this._handleGuildDeletion);
+ this.client.decrementMaxListeners();
+ });
+
+ this.on('collect', (reaction, user) => {
+ /**
+ * Emitted whenever a reaction is newly created on a message. Will emit only when a new reaction is
+ * added to the message, as opposed to {@link Collector#collect} which will
+ * be emitted even when a reaction has already been added to the message.
+ * @event ReactionCollector#create
+ * @param {MessageReaction} reaction The reaction that was added
+ * @param {User} user The user that added the reaction
+ */
+ if (reaction.count === 1) {
+ this.emit('create', reaction, user);
+ }
+ this.total++;
+ this.users.set(user.id, user);
+ });
+
+ this.on('remove', (reaction, user) => {
+ this.total--;
+ if (!this.collected.some(r => r.users.cache.has(user.id))) this.users.delete(user.id);
+ });
+ }
+
+ /**
+ * Handles an incoming reaction for possible collection.
+ * @param {MessageReaction} reaction The reaction to possibly collect
+ * @param {User} user The user that added the reaction
+ * @returns {?(Snowflake|string)}
+ * @private
+ */
+ collect(reaction) {
+ /**
+ * Emitted whenever a reaction is collected.
+ * @event ReactionCollector#collect
+ * @param {MessageReaction} reaction The reaction that was collected
+ * @param {User} user The user that added the reaction
+ */
+ if (reaction.message.id !== this.message.id) return null;
+
+ return ReactionCollector.key(reaction);
+ }
+
+ /**
+ * Handles a reaction deletion for possible disposal.
+ * @param {MessageReaction} reaction The reaction to possibly dispose of
+ * @param {User} user The user that removed the reaction
+ * @returns {?(Snowflake|string)}
+ */
+ dispose(reaction, user) {
+ /**
+ * Emitted when the reaction had all the users removed and the `dispose` option is set to true.
+ * @event ReactionCollector#dispose
+ * @param {MessageReaction} reaction The reaction that was disposed of
+ * @param {User} user The user that removed the reaction
+ */
+ if (reaction.message.id !== this.message.id) return null;
+
+ /**
+ * Emitted when the reaction had one user removed and the `dispose` option is set to true.
+ * @event ReactionCollector#remove
+ * @param {MessageReaction} reaction The reaction that was removed
+ * @param {User} user The user that removed the reaction
+ */
+ if (this.collected.has(ReactionCollector.key(reaction)) && this.users.has(user.id)) {
+ this.emit('remove', reaction, user);
+ }
+ return reaction.count ? null : ReactionCollector.key(reaction);
+ }
+
+ /**
+ * Empties this reaction collector.
+ */
+ empty() {
+ this.total = 0;
+ this.collected.clear();
+ this.users.clear();
+ this.checkEnd();
+ }
+
+ /**
+ * The reason this collector has ended with, or null if it hasn't ended yet
+ * @type {?string}
+ * @readonly
+ */
+ get endReason() {
+ if (this.options.max && this.total >= this.options.max) return 'limit';
+ if (this.options.maxEmojis && this.collected.size >= this.options.maxEmojis) return 'emojiLimit';
+ if (this.options.maxUsers && this.users.size >= this.options.maxUsers) return 'userLimit';
+ return super.endReason;
+ }
+
+ /**
+ * Handles checking if the message has been deleted, and if so, stops the collector with the reason 'messageDelete'.
+ * @private
+ * @param {Message} message The message that was deleted
+ * @returns {void}
+ */
+ _handleMessageDeletion(message) {
+ if (message.id === this.message.id) {
+ this.stop('messageDelete');
+ }
+ }
+
+ /**
+ * Handles checking if the channel has been deleted, and if so, stops the collector with the reason 'channelDelete'.
+ * @private
+ * @param {GuildChannel} channel The channel that was deleted
+ * @returns {void}
+ */
+ _handleChannelDeletion(channel) {
+ if (channel.id === this.message.channelId || channel.threads?.cache.has(this.message.channelId)) {
+ this.stop('channelDelete');
+ }
+ }
+
+ /**
+ * Handles checking if the thread has been deleted, and if so, stops the collector with the reason 'threadDelete'.
+ * @private
+ * @param {ThreadChannel} thread The thread that was deleted
+ * @returns {void}
+ */
+ _handleThreadDeletion(thread) {
+ if (thread.id === this.message.channelId) {
+ this.stop('threadDelete');
+ }
+ }
+
+ /**
+ * Handles checking if the guild has been deleted, and if so, stops the collector with the reason 'guildDelete'.
+ * @private
+ * @param {Guild} guild The guild that was deleted
+ * @returns {void}
+ */
+ _handleGuildDeletion(guild) {
+ if (guild.id === this.message.guild?.id) {
+ this.stop('guildDelete');
+ }
+ }
+
+ /**
+ * Gets the collector key for a reaction.
+ * @param {MessageReaction} reaction The message reaction to get the key for
+ * @returns {Snowflake|string}
+ */
+ static key(reaction) {
+ return reaction.emoji.id ?? reaction.emoji.name;
+ }
+}
+
+module.exports = ReactionCollector;