MessageCollector.js (4407B)
1 'use strict'; 2 3 const Collector = require('./interfaces/Collector'); 4 const { Events } = require('../util/Constants'); 5 6 /** 7 * @typedef {CollectorOptions} MessageCollectorOptions 8 * @property {number} max The maximum amount of messages to collect 9 * @property {number} maxProcessed The maximum amount of messages to process 10 */ 11 12 /** 13 * Collects messages on a channel. 14 * Will automatically stop if the channel (`'channelDelete'`) or guild (`'guildDelete'`) are deleted. 15 * @extends {Collector} 16 */ 17 class MessageCollector extends Collector { 18 /** 19 * @param {TextChannel|DMChannel} channel The channel 20 * @param {CollectorFilter} filter The filter to be applied to this collector 21 * @param {MessageCollectorOptions} options The options to be applied to this collector 22 * @emits MessageCollector#message 23 */ 24 constructor(channel, filter, options = {}) { 25 super(channel.client, filter, options); 26 27 /** 28 * The channel 29 * @type {TextBasedChannel} 30 */ 31 this.channel = channel; 32 33 /** 34 * Total number of messages that were received in the channel during message collection 35 * @type {number} 36 */ 37 this.received = 0; 38 39 const bulkDeleteListener = messages => { 40 for (const message of messages.values()) this.handleDispose(message); 41 }; 42 this._handleChannelDeletion = this._handleChannelDeletion.bind(this); 43 this._handleGuildDeletion = this._handleGuildDeletion.bind(this); 44 45 if (this.client.getMaxListeners() !== 0) this.client.setMaxListeners(this.client.getMaxListeners() + 1); 46 this.client.on(Events.MESSAGE_CREATE, this.handleCollect); 47 this.client.on(Events.MESSAGE_DELETE, this.handleDispose); 48 this.client.on(Events.MESSAGE_BULK_DELETE, bulkDeleteListener); 49 this.client.on(Events.CHANNEL_DELETE, this._handleChannelDeletion); 50 this.client.on(Events.GUILD_DELETE, this._handleGuildDeletion); 51 52 this.once('end', () => { 53 this.client.removeListener(Events.MESSAGE_CREATE, this.handleCollect); 54 this.client.removeListener(Events.MESSAGE_DELETE, this.handleDispose); 55 this.client.removeListener(Events.MESSAGE_BULK_DELETE, bulkDeleteListener); 56 this.client.removeListener(Events.CHANNEL_DELETE, this._handleChannelDeletion); 57 this.client.removeListener(Events.GUILD_DELETE, this._handleGuildDeletion); 58 if (this.client.getMaxListeners() !== 0) this.client.setMaxListeners(this.client.getMaxListeners() - 1); 59 }); 60 } 61 62 /** 63 * Handles a message for possible collection. 64 * @param {Message} message The message that could be collected 65 * @returns {?Snowflake} 66 * @private 67 */ 68 collect(message) { 69 /** 70 * Emitted whenever a message is collected. 71 * @event MessageCollector#collect 72 * @param {Message} message The message that was collected 73 */ 74 if (message.channel.id !== this.channel.id) return null; 75 this.received++; 76 return message.id; 77 } 78 79 /** 80 * Handles a message for possible disposal. 81 * @param {Message} message The message that could be disposed of 82 * @returns {?Snowflake} 83 */ 84 dispose(message) { 85 /** 86 * Emitted whenever a message is disposed of. 87 * @event MessageCollector#dispose 88 * @param {Message} message The message that was disposed of 89 */ 90 return message.channel.id === this.channel.id ? message.id : null; 91 } 92 93 /** 94 * Checks after un/collection to see if the collector is done. 95 * @returns {?string} 96 * @private 97 */ 98 endReason() { 99 if (this.options.max && this.collected.size >= this.options.max) return 'limit'; 100 if (this.options.maxProcessed && this.received === this.options.maxProcessed) return 'processedLimit'; 101 return null; 102 } 103 104 /** 105 * Handles checking if the channel has been deleted, and if so, stops the collector with the reason 'channelDelete'. 106 * @private 107 * @param {GuildChannel} channel The channel that was deleted 108 * @returns {void} 109 */ 110 _handleChannelDeletion(channel) { 111 if (channel.id === this.channel.id) { 112 this.stop('channelDelete'); 113 } 114 } 115 116 /** 117 * Handles checking if the guild has been deleted, and if so, stops the collector with the reason 'guildDelete'. 118 * @private 119 * @param {Guild} guild The guild that was deleted 120 * @returns {void} 121 */ 122 _handleGuildDeletion(guild) { 123 if (this.channel.guild && guild.id === this.channel.guild.id) { 124 this.stop('guildDelete'); 125 } 126 } 127 } 128 129 module.exports = MessageCollector;