diff --git a/src/structures/MessageCollector.js b/src/structures/MessageCollector.js index 5d45be089..f357722b5 100644 --- a/src/structures/MessageCollector.js +++ b/src/structures/MessageCollector.js @@ -11,6 +11,7 @@ const { Events } = require('../util/Constants'); /** * Collects messages on a channel. + * Will automatically stop if the channel (`'channelDelete'`) or guild (`'guildDelete'`) are deleted. * @extends {Collector} */ class MessageCollector extends Collector { @@ -38,16 +39,22 @@ class MessageCollector extends Collector { const bulkDeleteListener = (messages => { for (const message of messages.values()) this.handleDispose(message); }).bind(this); + this._handleChannelDeletion = this._handleChannelDeletion.bind(this); + this._handleGuildDeletion = this._handleGuildDeletion.bind(this); if (this.client.getMaxListeners() !== 0) this.client.setMaxListeners(this.client.getMaxListeners() + 1); this.client.on(Events.MESSAGE_CREATE, this.handleCollect); this.client.on(Events.MESSAGE_DELETE, this.handleDispose); this.client.on(Events.MESSAGE_BULK_DELETE, bulkDeleteListener); + this.client.on(Events.CHANNEL_DELETE, this._handleChannelDeletion); + this.client.on(Events.GUILD_DELETE, this._handleGuildDeletion); this.once('end', () => { this.client.removeListener(Events.MESSAGE_CREATE, this.handleCollect); this.client.removeListener(Events.MESSAGE_DELETE, this.handleDispose); this.client.removeListener(Events.MESSAGE_BULK_DELETE, bulkDeleteListener); + this.client.removeListener(Events.CHANNEL_DELETE, this._handleChannelDeletion); + this.client.removeListener(Events.GUILD_DELETE, this._handleGuildDeletion); if (this.client.getMaxListeners() !== 0) this.client.setMaxListeners(this.client.getMaxListeners() - 1); }); } @@ -93,6 +100,30 @@ class MessageCollector extends Collector { if (this.options.maxProcessed && this.received === this.options.maxProcessed) return 'processedLimit'; return null; } + + /** + * 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.channel.id) { + this.stop('channelDelete'); + } + } + + /** + * 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 (this.channel.guild && guild.id === this.channel.guild.id) { + this.stop('guildDelete'); + } + } } module.exports = MessageCollector; diff --git a/src/structures/ReactionCollector.js b/src/structures/ReactionCollector.js index 8e84fb672..e7d5aeb16 100644 --- a/src/structures/ReactionCollector.js +++ b/src/structures/ReactionCollector.js @@ -13,6 +13,8 @@ const { Events } = require('../util/Constants'); /** * Collects reactions on messages. + * Will automatically stop if the message (`'messageDelete'`), + * channel (`'channelDelete'`), or guild (`'guildDelete'`) are deleted. * @extends {Collector} */ class ReactionCollector extends Collector { @@ -43,16 +45,25 @@ class ReactionCollector extends Collector { this.total = 0; this.empty = this.empty.bind(this); + this._handleChannelDeletion = this._handleChannelDeletion.bind(this); + this._handleGuildDeletion = this._handleGuildDeletion.bind(this); + this._handleMessageDeletion = this._handleMessageDeletion.bind(this); if (this.client.getMaxListeners() !== 0) this.client.setMaxListeners(this.client.getMaxListeners() + 1); this.client.on(Events.MESSAGE_REACTION_ADD, this.handleCollect); this.client.on(Events.MESSAGE_REACTION_REMOVE, this.handleDispose); this.client.on(Events.MESSAGE_REACTION_REMOVE_ALL, this.empty); + this.client.on(Events.MESSAGE_DELETE, this._handleMessageDeletion); + this.client.on(Events.CHANNEL_DELETE, this._handleChannelDeletion); + this.client.on(Events.GUILD_DELETE, this._handleGuildDeletion); this.once('end', () => { this.client.removeListener(Events.MESSAGE_REACTION_ADD, this.handleCollect); this.client.removeListener(Events.MESSAGE_REACTION_REMOVE, this.handleDispose); this.client.removeListener(Events.MESSAGE_REACTION_REMOVE_ALL, this.empty); + this.client.removeListener(Events.MESSAGE_DELETE, this._handleMessageDeletion); + this.client.removeListener(Events.CHANNEL_DELETE, this._handleChannelDeletion); + this.client.removeListener(Events.GUILD_DELETE, this._handleGuildDeletion); if (this.client.getMaxListeners() !== 0) this.client.setMaxListeners(this.client.getMaxListeners() - 1); }); @@ -131,6 +142,42 @@ class ReactionCollector extends Collector { return null; } + /** + * 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.channel.id) { + this.stop('channelDelete'); + } + } + + /** + * 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 (this.message.guild && 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 diff --git a/typings/index.d.ts b/typings/index.d.ts index d567e6db6..6d719a347 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1023,6 +1023,9 @@ declare module 'discord.js' { export class MessageCollector extends Collector { constructor(channel: TextChannel | DMChannel, filter: CollectorFilter, options?: MessageCollectorOptions); + private _handleChannelDeletion(channel: GuildChannel): void; + private _handleGuildDeletion(guild: Guild): void; + public channel: Channel; public options: MessageCollectorOptions; public received: number; @@ -1153,6 +1156,10 @@ declare module 'discord.js' { export class ReactionCollector extends Collector { constructor(message: Message, filter: CollectorFilter, options?: ReactionCollectorOptions); + private _handleChannelDeletion(channel: GuildChannel): void; + private _handleGuildDeletion(guild: Guild): void; + private _handleMessageDeletion(message: Message): void; + public message: Message; public options: ReactionCollectorOptions; public total: number;