/
MessageCollector.js
146 lines (130 loc) · 4.79 KB
/
MessageCollector.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
'use strict';
const Collector = require('./interfaces/Collector');
const { Events } = require('../util/Constants');
/**
* @typedef {CollectorOptions} MessageCollectorOptions
* @property {number} max The maximum amount of messages to collect
* @property {number} maxProcessed The maximum amount of messages to process
*/
/**
* Collects messages on a channel.
* Will automatically stop if the channel ({@link Client#event:channelDelete channelDelete}),
* thread ({@link Client#event:threadDelete threadDelete}), or
* guild ({@link Client#event:guildDelete guildDelete}) is deleted.
* @extends {Collector}
*/
class MessageCollector extends Collector {
/**
* @param {TextBasedChannels} channel The channel
* @param {MessageCollectorOptions} options The options to be applied to this collector
* @emits MessageCollector#message
*/
constructor(channel, options = {}) {
super(channel.client, options);
/**
* The channel
* @type {TextBasedChannels}
*/
this.channel = channel;
/**
* Total number of messages that were received in the channel during message collection
* @type {number}
*/
this.received = 0;
const bulkDeleteListener = messages => {
for (const message of messages.values()) this.handleDispose(message);
};
this._handleChannelDeletion = this._handleChannelDeletion.bind(this);
this._handleThreadDeletion = this._handleThreadDeletion.bind(this);
this._handleGuildDeletion = this._handleGuildDeletion.bind(this);
this.client.incrementMaxListeners();
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.THREAD_DELETE, this._handleThreadDeletion);
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.THREAD_DELETE, this._handleThreadDeletion);
this.client.removeListener(Events.GUILD_DELETE, this._handleGuildDeletion);
this.client.decrementMaxListeners();
});
}
/**
* Handles a message for possible collection.
* @param {Message} message The message that could be collected
* @returns {?Snowflake}
* @private
*/
collect(message) {
/**
* Emitted whenever a message is collected.
* @event MessageCollector#collect
* @param {Message} message The message that was collected
*/
if (message.channelId !== this.channel.id) return null;
this.received++;
return message.id;
}
/**
* Handles a message for possible disposal.
* @param {Message} message The message that could be disposed of
* @returns {?Snowflake}
*/
dispose(message) {
/**
* Emitted whenever a message is disposed of.
* @event MessageCollector#dispose
* @param {Message} message The message that was disposed of
*/
return message.channelId === this.channel.id ? message.id : null;
}
/**
* 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.collected.size >= this.options.max) return 'limit';
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 || channel.id === this.channel.parentId) {
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.channel.id) {
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.channel.guild?.id) {
this.stop('guildDelete');
}
}
}
module.exports = MessageCollector;