discord.js-selfv13 13.0.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of discord.js-selfv13 might be problematic. Click here for more details.

Files changed (188) hide show
  1. package/.dccache +1 -0
  2. package/LICENSE +190 -0
  3. package/README.md +87 -0
  4. package/browser.js +9 -0
  5. package/deploy/deploy-key.enc +0 -0
  6. package/deploy/deploy.sh +90 -0
  7. package/deploy/test.sh +34 -0
  8. package/docs/README.md +1 -0
  9. package/docs/examples/attachments.md +163 -0
  10. package/docs/examples/avatars.js +29 -0
  11. package/docs/examples/embed.js +38 -0
  12. package/docs/examples/greeting.js +30 -0
  13. package/docs/examples/moderation.md +145 -0
  14. package/docs/examples/ping.js +29 -0
  15. package/docs/examples/webhook.js +12 -0
  16. package/docs/general/faq.md +23 -0
  17. package/docs/general/updating.md +181 -0
  18. package/docs/general/welcome.md +95 -0
  19. package/docs/index.yml +30 -0
  20. package/docs/logo.svg +19 -0
  21. package/docs/topics/voice.md +113 -0
  22. package/docs/topics/web.md +38 -0
  23. package/package.json +147 -0
  24. package/src/client/Client.js +564 -0
  25. package/src/client/ClientDataManager.js +150 -0
  26. package/src/client/ClientDataResolver.js +376 -0
  27. package/src/client/ClientManager.js +74 -0
  28. package/src/client/WebhookClient.js +118 -0
  29. package/src/client/actions/Action.js +23 -0
  30. package/src/client/actions/ActionsManager.js +40 -0
  31. package/src/client/actions/ChannelCreate.js +11 -0
  32. package/src/client/actions/ChannelDelete.js +30 -0
  33. package/src/client/actions/ChannelUpdate.js +74 -0
  34. package/src/client/actions/GuildBanRemove.js +13 -0
  35. package/src/client/actions/GuildChannelsPositionUpdate.js +19 -0
  36. package/src/client/actions/GuildDelete.js +57 -0
  37. package/src/client/actions/GuildEmojiCreate.js +17 -0
  38. package/src/client/actions/GuildEmojiDelete.js +18 -0
  39. package/src/client/actions/GuildEmojiUpdate.js +17 -0
  40. package/src/client/actions/GuildEmojisUpdate.js +38 -0
  41. package/src/client/actions/GuildMemberGet.js +10 -0
  42. package/src/client/actions/GuildMemberRemove.js +41 -0
  43. package/src/client/actions/GuildRoleCreate.js +26 -0
  44. package/src/client/actions/GuildRoleDelete.js +42 -0
  45. package/src/client/actions/GuildRoleUpdate.js +41 -0
  46. package/src/client/actions/GuildRolesPositionUpdate.js +19 -0
  47. package/src/client/actions/GuildSync.js +29 -0
  48. package/src/client/actions/GuildUpdate.js +34 -0
  49. package/src/client/actions/MessageCreate.js +53 -0
  50. package/src/client/actions/MessageDelete.js +35 -0
  51. package/src/client/actions/MessageDeleteBulk.js +26 -0
  52. package/src/client/actions/MessageReactionAdd.js +37 -0
  53. package/src/client/actions/MessageReactionRemove.js +37 -0
  54. package/src/client/actions/MessageReactionRemoveAll.js +25 -0
  55. package/src/client/actions/MessageUpdate.js +40 -0
  56. package/src/client/actions/Ready.js +1 -0
  57. package/src/client/actions/Ready.js.bak +65 -0
  58. package/src/client/actions/UserGet.js +11 -0
  59. package/src/client/actions/UserNoteUpdate.js +30 -0
  60. package/src/client/actions/UserUpdate.js +33 -0
  61. package/src/client/rest/APIRequest.js +56 -0
  62. package/src/client/rest/DiscordAPIError.js +60 -0
  63. package/src/client/rest/RESTManager.js +58 -0
  64. package/src/client/rest/RESTMethods.js +1006 -0
  65. package/src/client/rest/RequestHandlers/Burst.js +90 -0
  66. package/src/client/rest/RequestHandlers/RequestHandler.js +54 -0
  67. package/src/client/rest/RequestHandlers/Sequential.js +132 -0
  68. package/src/client/rest/UserAgentManager.js +25 -0
  69. package/src/client/voice/ClientVoiceManager.js +81 -0
  70. package/src/client/voice/VoiceBroadcast.js +366 -0
  71. package/src/client/voice/VoiceConnection.js +530 -0
  72. package/src/client/voice/VoiceUDPClient.js +127 -0
  73. package/src/client/voice/VoiceWebSocket.js +246 -0
  74. package/src/client/voice/dispatcher/StreamDispatcher.js +331 -0
  75. package/src/client/voice/opus/BaseOpusEngine.js +60 -0
  76. package/src/client/voice/opus/NodeOpusEngine.js +40 -0
  77. package/src/client/voice/opus/OpusEngineList.js +28 -0
  78. package/src/client/voice/opus/OpusScriptEngine.js +45 -0
  79. package/src/client/voice/player/AudioPlayer.js +170 -0
  80. package/src/client/voice/receiver/VoiceReadable.js +17 -0
  81. package/src/client/voice/receiver/VoiceReceiver.js +219 -0
  82. package/src/client/voice/util/SecretKey.js +16 -0
  83. package/src/client/voice/util/Secretbox.js +33 -0
  84. package/src/client/voice/util/VolumeInterface.js +86 -0
  85. package/src/client/websocket/WebSocketConnection.js +506 -0
  86. package/src/client/websocket/WebSocketManager.js +90 -0
  87. package/src/client/websocket/packets/WebSocketPacketManager.js +110 -0
  88. package/src/client/websocket/packets/handlers/AbstractHandler.js +11 -0
  89. package/src/client/websocket/packets/handlers/ChannelCreate.js +17 -0
  90. package/src/client/websocket/packets/handlers/ChannelDelete.js +20 -0
  91. package/src/client/websocket/packets/handlers/ChannelPinsUpdate.js +37 -0
  92. package/src/client/websocket/packets/handlers/ChannelUpdate.js +11 -0
  93. package/src/client/websocket/packets/handlers/GuildBanAdd.js +23 -0
  94. package/src/client/websocket/packets/handlers/GuildBanRemove.js +20 -0
  95. package/src/client/websocket/packets/handlers/GuildCreate.js +22 -0
  96. package/src/client/websocket/packets/handlers/GuildDelete.js +19 -0
  97. package/src/client/websocket/packets/handlers/GuildEmojisUpdate.js +11 -0
  98. package/src/client/websocket/packets/handlers/GuildIntegrationsUpdate.js +19 -0
  99. package/src/client/websocket/packets/handlers/GuildMemberAdd.js +17 -0
  100. package/src/client/websocket/packets/handlers/GuildMemberRemove.js +13 -0
  101. package/src/client/websocket/packets/handlers/GuildMemberUpdate.js +18 -0
  102. package/src/client/websocket/packets/handlers/GuildMembersChunk.js +33 -0
  103. package/src/client/websocket/packets/handlers/GuildRoleCreate.js +11 -0
  104. package/src/client/websocket/packets/handlers/GuildRoleDelete.js +11 -0
  105. package/src/client/websocket/packets/handlers/GuildRoleUpdate.js +11 -0
  106. package/src/client/websocket/packets/handlers/GuildSync.js +11 -0
  107. package/src/client/websocket/packets/handlers/GuildUpdate.js +11 -0
  108. package/src/client/websocket/packets/handlers/MessageCreate.js +19 -0
  109. package/src/client/websocket/packets/handlers/MessageDelete.js +19 -0
  110. package/src/client/websocket/packets/handlers/MessageDeleteBulk.js +17 -0
  111. package/src/client/websocket/packets/handlers/MessageReactionAdd.js +11 -0
  112. package/src/client/websocket/packets/handlers/MessageReactionRemove.js +11 -0
  113. package/src/client/websocket/packets/handlers/MessageReactionRemoveAll.js +11 -0
  114. package/src/client/websocket/packets/handlers/MessageUpdate.js +11 -0
  115. package/src/client/websocket/packets/handlers/PresenceUpdate.js +76 -0
  116. package/src/client/websocket/packets/handlers/Ready.js +83 -0
  117. package/src/client/websocket/packets/handlers/RelationshipAdd.js +19 -0
  118. package/src/client/websocket/packets/handlers/RelationshipRemove.js +19 -0
  119. package/src/client/websocket/packets/handlers/Resumed.js +28 -0
  120. package/src/client/websocket/packets/handlers/TypingStart.js +68 -0
  121. package/src/client/websocket/packets/handlers/UserGuildSettingsUpdate.js +21 -0
  122. package/src/client/websocket/packets/handlers/UserNoteUpdate.js +12 -0
  123. package/src/client/websocket/packets/handlers/UserSettingsUpdate.js +18 -0
  124. package/src/client/websocket/packets/handlers/UserUpdate.js +11 -0
  125. package/src/client/websocket/packets/handlers/VoiceServerUpdate.js +19 -0
  126. package/src/client/websocket/packets/handlers/VoiceStateUpdate.js +52 -0
  127. package/src/client/websocket/packets/handlers/WebhooksUpdate.js +19 -0
  128. package/src/index.js +66 -0
  129. package/src/sharding/Shard.js +282 -0
  130. package/src/sharding/ShardClientUtil.js +146 -0
  131. package/src/sharding/ShardingManager.js +220 -0
  132. package/src/structures/Attachment.js +75 -0
  133. package/src/structures/CategoryChannel.js +22 -0
  134. package/src/structures/Channel.js +78 -0
  135. package/src/structures/ClientUser.js +447 -0
  136. package/src/structures/ClientUserChannelOverride.js +30 -0
  137. package/src/structures/ClientUserGuildSettings.js +60 -0
  138. package/src/structures/ClientUserSettings.js +80 -0
  139. package/src/structures/DMChannel.js +76 -0
  140. package/src/structures/Emoji.js +256 -0
  141. package/src/structures/GroupDMChannel.js +246 -0
  142. package/src/structures/Guild.js +1461 -0
  143. package/src/structures/GuildAuditLogs.js +371 -0
  144. package/src/structures/GuildChannel.js +537 -0
  145. package/src/structures/GuildMember.js +613 -0
  146. package/src/structures/Invite.js +164 -0
  147. package/src/structures/Message.js +605 -0
  148. package/src/structures/MessageAttachment.js +68 -0
  149. package/src/structures/MessageCollector.js +100 -0
  150. package/src/structures/MessageEmbed.js +386 -0
  151. package/src/structures/MessageMentions.js +144 -0
  152. package/src/structures/MessageReaction.js +96 -0
  153. package/src/structures/NewsChannel.js +24 -0
  154. package/src/structures/OAuth2Application.js +148 -0
  155. package/src/structures/PartialGuild.js +51 -0
  156. package/src/structures/PartialGuildChannel.js +44 -0
  157. package/src/structures/PermissionOverwrites.js +69 -0
  158. package/src/structures/Presence.js +241 -0
  159. package/src/structures/ReactionCollector.js +85 -0
  160. package/src/structures/ReactionEmoji.js +49 -0
  161. package/src/structures/RichEmbed.js +295 -0
  162. package/src/structures/Role.js +376 -0
  163. package/src/structures/StoreChannel.js +25 -0
  164. package/src/structures/TextChannel.js +154 -0
  165. package/src/structures/User.js +329 -0
  166. package/src/structures/UserConnection.js +48 -0
  167. package/src/structures/UserProfile.js +62 -0
  168. package/src/structures/VoiceChannel.js +146 -0
  169. package/src/structures/VoiceRegion.js +50 -0
  170. package/src/structures/Webhook.js +304 -0
  171. package/src/structures/interfaces/Collector.js +179 -0
  172. package/src/structures/interfaces/TextBasedChannel.js +635 -0
  173. package/src/structures/shared/resolvePermissions.js +26 -0
  174. package/src/util/Collection.js +532 -0
  175. package/src/util/Constants.js +845 -0
  176. package/src/util/Permissions.js +306 -0
  177. package/src/util/Snowflake.js +82 -0
  178. package/src/util/Util.js +221 -0
  179. package/test/random.js +207 -0
  180. package/test/shard.js +31 -0
  181. package/test/sharder.js +7 -0
  182. package/test/voice.js +78 -0
  183. package/test/webpack.html +31 -0
  184. package/tsconfig.json +13 -0
  185. package/tslint.json +62 -0
  186. package/typings/discord.js-test.ts +69 -0
  187. package/typings/index.d.ts +2190 -0
  188. package/webpack.config.js +62 -0
@@ -0,0 +1,564 @@
1
+ const EventEmitter = require('events');
2
+ const Constants = require('../util/Constants');
3
+ const Permissions = require('../util/Permissions');
4
+ const Util = require('../util/Util');
5
+ const RESTManager = require('./rest/RESTManager');
6
+ const ClientDataManager = require('./ClientDataManager');
7
+ const ClientManager = require('./ClientManager');
8
+ const ClientDataResolver = require('./ClientDataResolver');
9
+ const ClientVoiceManager = require('./voice/ClientVoiceManager');
10
+ const WebSocketManager = require('./websocket/WebSocketManager');
11
+ const ActionsManager = require('./actions/ActionsManager');
12
+ const Collection = require('../util/Collection');
13
+ const Presence = require('../structures/Presence').Presence;
14
+ const ShardClientUtil = require('../sharding/ShardClientUtil');
15
+ const VoiceBroadcast = require('./voice/VoiceBroadcast');
16
+
17
+ /**
18
+ * The main hub for interacting with the Discord API, and the starting point for any bot.
19
+ * @extends {EventEmitter}
20
+ */
21
+ class Client extends EventEmitter {
22
+ /**
23
+ * @param {ClientOptions} [options] Options for the client
24
+ */
25
+ constructor(options = {}) {
26
+ super();
27
+
28
+ // Obtain shard details from environment
29
+ if (!options.shardId && 'SHARD_ID' in process.env) options.shardId = Number(process.env.SHARD_ID);
30
+ if (!options.shardCount && 'SHARD_COUNT' in process.env) options.shardCount = Number(process.env.SHARD_COUNT);
31
+
32
+ /**
33
+ * The options the client was instantiated with
34
+ * @type {ClientOptions}
35
+ */
36
+ this.options = Util.mergeDefault(Constants.DefaultOptions, options);
37
+ this._validateOptions();
38
+
39
+ /**
40
+ * The REST manager of the client
41
+ * @type {RESTManager}
42
+ * @private
43
+ */
44
+ this.rest = new RESTManager(this);
45
+
46
+ /**
47
+ * The data manager of the client
48
+ * @type {ClientDataManager}
49
+ * @private
50
+ */
51
+ this.dataManager = new ClientDataManager(this);
52
+
53
+ /**
54
+ * The manager of the client
55
+ * @type {ClientManager}
56
+ * @private
57
+ */
58
+ this.manager = new ClientManager(this);
59
+
60
+ /**
61
+ * The WebSocket manager of the client
62
+ * @type {WebSocketManager}
63
+ * @private
64
+ */
65
+ this.ws = new WebSocketManager(this);
66
+
67
+ /**
68
+ * The data resolver of the client
69
+ * @type {ClientDataResolver}
70
+ * @private
71
+ */
72
+ this.resolver = new ClientDataResolver(this);
73
+
74
+ /**
75
+ * The action manager of the client
76
+ * @type {ActionsManager}
77
+ * @private
78
+ */
79
+ this.actions = new ActionsManager(this);
80
+
81
+ /**
82
+ * The voice manager of the client (`null` in browsers)
83
+ * @type {?ClientVoiceManager}
84
+ * @private
85
+ */
86
+ this.voice = !this.browser ? new ClientVoiceManager(this) : null;
87
+
88
+ /**
89
+ * The shard helpers for the client
90
+ * (only if the process was spawned as a child, such as from a {@link ShardingManager})
91
+ * @type {?ShardClientUtil}
92
+ */
93
+ this.shard = process.send ? ShardClientUtil.singleton(this) : null;
94
+
95
+ /**
96
+ * All of the {@link User} objects that have been cached at any point, mapped by their IDs
97
+ * @type {Collection<Snowflake, User>}
98
+ */
99
+ this.users = new Collection();
100
+
101
+ /**
102
+ * All of the guilds the client is currently handling, mapped by their IDs -
103
+ * as long as sharding isn't being used, this will be *every* guild the bot is a member of
104
+ * @type {Collection<Snowflake, Guild>}
105
+ */
106
+ this.guilds = new Collection();
107
+
108
+ /**
109
+ * All of the {@link Channel}s that the client is currently handling, mapped by their IDs -
110
+ * as long as sharding isn't being used, this will be *every* channel in *every* guild, and all DM channels
111
+ * @type {Collection<Snowflake, Channel>}
112
+ */
113
+ this.channels = new Collection();
114
+
115
+ /**
116
+ * Presences that have been received for the client user's friends, mapped by user IDs
117
+ * <warn>This is only filled when using a user account.</warn>
118
+ * @type {Collection<Snowflake, Presence>}
119
+ * @deprecated
120
+ */
121
+ this.presences = new Collection();
122
+
123
+ Object.defineProperty(this, 'token', { writable: true });
124
+ if (!this.token && 'CLIENT_TOKEN' in process.env) {
125
+ /**
126
+ * Authorization token for the logged in user/bot
127
+ * <warn>This should be kept private at all times.</warn>
128
+ * @type {?string}
129
+ */
130
+ this.token = process.env.CLIENT_TOKEN;
131
+ } else {
132
+ this.token = null;
133
+ }
134
+
135
+ /**
136
+ * User that the client is logged in as
137
+ * @type {?ClientUser}
138
+ */
139
+ this.user = null;
140
+
141
+ /**
142
+ * Time at which the client was last regarded as being in the `READY` state
143
+ * (each time the client disconnects and successfully reconnects, this will be overwritten)
144
+ * @type {?Date}
145
+ */
146
+ this.readyAt = null;
147
+
148
+ /**
149
+ * Active voice broadcasts that have been created
150
+ * @type {VoiceBroadcast[]}
151
+ */
152
+ this.broadcasts = [];
153
+
154
+ /**
155
+ * Previous heartbeat pings of the websocket (most recent first, limited to three elements)
156
+ * @type {number[]}
157
+ */
158
+ this.pings = [];
159
+
160
+ /**
161
+ * Timeouts set by {@link Client#setTimeout} that are still active
162
+ * @type {Set<Timeout>}
163
+ * @private
164
+ */
165
+ this._timeouts = new Set();
166
+
167
+ /**
168
+ * Intervals set by {@link Client#setInterval} that are still active
169
+ * @type {Set<Timeout>}
170
+ * @private
171
+ */
172
+ this._intervals = new Set();
173
+
174
+ if (this.options.messageSweepInterval > 0) {
175
+ this.setInterval(this.sweepMessages.bind(this), this.options.messageSweepInterval * 1000);
176
+ }
177
+ }
178
+
179
+ /**
180
+ * Timestamp of the latest ping's start time
181
+ * @type {number}
182
+ * @private
183
+ */
184
+ get _pingTimestamp() {
185
+ return this.ws.connection ? this.ws.connection.lastPingTimestamp : 0;
186
+ }
187
+
188
+ /**
189
+ * Current status of the client's connection to Discord
190
+ * @type {Status}
191
+ * @readonly
192
+ */
193
+ get status() {
194
+ return this.ws.connection ? this.ws.connection.status : Constants.Status.IDLE;
195
+ }
196
+
197
+ /**
198
+ * How long it has been since the client last entered the `READY` state in milliseconds
199
+ * @type {?number}
200
+ * @readonly
201
+ */
202
+ get uptime() {
203
+ return this.readyAt ? Date.now() - this.readyAt : null;
204
+ }
205
+
206
+ /**
207
+ * Average heartbeat ping of the websocket, obtained by averaging the {@link Client#pings} property
208
+ * @type {number}
209
+ * @readonly
210
+ */
211
+ get ping() {
212
+ return this.pings.reduce((prev, p) => prev + p, 0) / this.pings.length;
213
+ }
214
+
215
+ /**
216
+ * All active voice connections that have been established, mapped by guild ID
217
+ * @type {Collection<Snowflake, VoiceConnection>}
218
+ * @readonly
219
+ */
220
+ get voiceConnections() {
221
+ if (this.browser) return new Collection();
222
+ return this.voice.connections;
223
+ }
224
+
225
+ /**
226
+ * All custom emojis that the client has access to, mapped by their IDs
227
+ * @type {Collection<Snowflake, Emoji>}
228
+ * @readonly
229
+ */
230
+ get emojis() {
231
+ const emojis = new Collection();
232
+ for (const guild of this.guilds.values()) {
233
+ for (const emoji of guild.emojis.values()) emojis.set(emoji.id, emoji);
234
+ }
235
+ return emojis;
236
+ }
237
+
238
+ /**
239
+ * Timestamp of the time the client was last `READY` at
240
+ * @type {?number}
241
+ * @readonly
242
+ */
243
+ get readyTimestamp() {
244
+ return this.readyAt ? this.readyAt.getTime() : null;
245
+ }
246
+
247
+ /**
248
+ * Whether the client is in a browser environment
249
+ * @type {boolean}
250
+ * @readonly
251
+ */
252
+ get browser() {
253
+ return typeof window !== 'undefined';
254
+ }
255
+
256
+ /**
257
+ * Creates a voice broadcast.
258
+ * @returns {VoiceBroadcast}
259
+ */
260
+ createVoiceBroadcast() {
261
+ const broadcast = new VoiceBroadcast(this);
262
+ this.broadcasts.push(broadcast);
263
+ return broadcast;
264
+ }
265
+
266
+ /**
267
+ * Logs the client in, establishing a websocket connection to Discord.
268
+ * <info>Both bot and regular user accounts are supported, but it is highly recommended to use a bot account whenever
269
+ * possible. User accounts are subject to harsher ratelimits and other restrictions that don't apply to bot accounts.
270
+ * Bot accounts also have access to many features that user accounts cannot utilise. Automating a user account is
271
+ * considered a violation of the ToS.</info>
272
+ * @param {string} token Token of the account to log in with
273
+ * @returns {Promise<string>} Token of the account used
274
+ * @example
275
+ * client.login('my token')
276
+ * .then(console.log)
277
+ * .catch(console.error);
278
+ */
279
+ login(token = this.token) {
280
+ return this.rest.methods.login(token);
281
+ }
282
+
283
+ /**
284
+ * Logs out, terminates the connection to Discord, and destroys the client.
285
+ * @returns {Promise}
286
+ */
287
+ destroy() {
288
+ for (const t of this._timeouts) clearTimeout(t);
289
+ for (const i of this._intervals) clearInterval(i);
290
+ this._timeouts.clear();
291
+ this._intervals.clear();
292
+ return this.manager.destroy();
293
+ }
294
+
295
+ /**
296
+ * Requests a sync of guild data with Discord.
297
+ * <info>This can be done automatically every 30 seconds by enabling {@link ClientOptions#sync}.</info>
298
+ * <warn>This is only available when using a user account.</warn>
299
+ * @param {Guild[]|Collection<Snowflake, Guild>} [guilds=this.guilds] An array or collection of guilds to sync
300
+ * @deprecated
301
+ */
302
+ syncGuilds(guilds = this.guilds) {
303
+ if (this.user.bot) return;
304
+ this.ws.send({
305
+ op: 12,
306
+ d: guilds instanceof Collection ? guilds.keyArray() : guilds.map(g => g.id),
307
+ });
308
+ }
309
+
310
+ /**
311
+ * Obtains a user from Discord, or the user cache if it's already available.
312
+ * <warn>This is only available when using a bot account.</warn>
313
+ * @param {Snowflake} id ID of the user
314
+ * @param {boolean} [cache=true] Whether to cache the new user object if it isn't already
315
+ * @returns {Promise<User>}
316
+ */
317
+ fetchUser(id, cache = true) {
318
+ if (this.users.has(id)) return Promise.resolve(this.users.get(id));
319
+ return this.rest.methods.getUser(id, cache);
320
+ }
321
+
322
+ /**
323
+ * Obtains an invite from Discord.
324
+ * @param {InviteResolvable} invite Invite code or URL
325
+ * @returns {Promise<Invite>}
326
+ * @example
327
+ * client.fetchInvite('https://discord.gg/bRCvFy9')
328
+ * .then(invite => console.log(`Obtained invite with code: ${invite.code}`))
329
+ * .catch(console.error);
330
+ */
331
+ fetchInvite(invite) {
332
+ const code = this.resolver.resolveInviteCode(invite);
333
+ return this.rest.methods.getInvite(code);
334
+ }
335
+
336
+ /**
337
+ * Obtains a webhook from Discord.
338
+ * @param {Snowflake} id ID of the webhook
339
+ * @param {string} [token] Token for the webhook
340
+ * @returns {Promise<Webhook>}
341
+ * @example
342
+ * client.fetchWebhook('id', 'token')
343
+ * .then(webhook => console.log(`Obtained webhook with name: ${webhook.name}`))
344
+ * .catch(console.error);
345
+ */
346
+ fetchWebhook(id, token) {
347
+ return this.rest.methods.getWebhook(id, token);
348
+ }
349
+
350
+ /**
351
+ * Obtains the available voice regions from Discord.
352
+ * @returns {Collection<string, VoiceRegion>}
353
+ * @example
354
+ * client.fetchVoiceRegions()
355
+ * .then(regions => console.log(`Available regions are: ${regions.map(region => region.name).join(', ')}`))
356
+ * .catch(console.error);
357
+ */
358
+ fetchVoiceRegions() {
359
+ return this.rest.methods.fetchVoiceRegions();
360
+ }
361
+
362
+ /**
363
+ * Sweeps all text-based channels' messages and removes the ones older than the max message lifetime.
364
+ * If the message has been edited, the time of the edit is used rather than the time of the original message.
365
+ * @param {number} [lifetime=this.options.messageCacheLifetime] Messages that are older than this (in seconds)
366
+ * will be removed from the caches. The default is based on {@link ClientOptions#messageCacheLifetime}
367
+ * @returns {number} Amount of messages that were removed from the caches,
368
+ * or -1 if the message cache lifetime is unlimited
369
+ */
370
+ sweepMessages(lifetime = this.options.messageCacheLifetime) {
371
+ if (typeof lifetime !== 'number' || isNaN(lifetime)) throw new TypeError('The lifetime must be a number.');
372
+ if (lifetime <= 0) {
373
+ this.emit('debug', 'Didn\'t sweep messages - lifetime is unlimited');
374
+ return -1;
375
+ }
376
+
377
+ const lifetimeMs = lifetime * 1000;
378
+ const now = Date.now();
379
+ let channels = 0;
380
+ let messages = 0;
381
+
382
+ for (const channel of this.channels.values()) {
383
+ if (!channel.messages) continue;
384
+ channels++;
385
+
386
+ messages += channel.messages.sweep(
387
+ message => now - (message.editedTimestamp || message.createdTimestamp) > lifetimeMs
388
+ );
389
+ }
390
+
391
+ this.emit('debug', `Swept ${messages} messages older than ${lifetime} seconds in ${channels} text-based channels`);
392
+ return messages;
393
+ }
394
+
395
+ /**
396
+ * Obtains the OAuth Application of the bot from Discord.
397
+ * <warn>Bots can only fetch their own profile.</warn>
398
+ * @param {Snowflake} [id='@me'] ID of application to fetch
399
+ * @returns {Promise<OAuth2Application>}
400
+ * @example
401
+ * client.fetchApplication()
402
+ * .then(application => console.log(`Obtained application with name: ${application.name}`))
403
+ * .catch(console.error);
404
+ */
405
+ fetchApplication(id = '@me') {
406
+ if (id !== '@me') process.emitWarning('fetchApplication: use "@me" as an argument', 'DeprecationWarning');
407
+ return this.rest.methods.getApplication(id);
408
+ }
409
+
410
+ /**
411
+ * Generates a link that can be used to invite the bot to a guild.
412
+ * <warn>This is only available when using a bot account.</warn>
413
+ * @param {PermissionResolvable} [permissions] Permissions to request
414
+ * @returns {Promise<string>}
415
+ * @example
416
+ * client.generateInvite(['SEND_MESSAGES', 'MANAGE_GUILD', 'MENTION_EVERYONE'])
417
+ * .then(link => console.log(`Generated bot invite link: ${link}`))
418
+ * .catch(console.error);
419
+ */
420
+ generateInvite(permissions) {
421
+ permissions = typeof permissions === 'undefined' ? 0 : Permissions.resolve(permissions);
422
+ return this.fetchApplication().then(application =>
423
+ `https://discordapp.com/oauth2/authorize?client_id=${application.id}&permissions=${permissions}&scope=bot`
424
+ );
425
+ }
426
+
427
+ /**
428
+ * Sets a timeout that will be automatically cancelled if the client is destroyed.
429
+ * @param {Function} fn Function to execute
430
+ * @param {number} delay Time to wait before executing (in milliseconds)
431
+ * @param {...*} args Arguments for the function
432
+ * @returns {Timeout}
433
+ */
434
+ setTimeout(fn, delay, ...args) {
435
+ const timeout = setTimeout(() => {
436
+ fn(...args);
437
+ this._timeouts.delete(timeout);
438
+ }, delay);
439
+ this._timeouts.add(timeout);
440
+ return timeout;
441
+ }
442
+
443
+ /**
444
+ * Clears a timeout.
445
+ * @param {Timeout} timeout Timeout to cancel
446
+ */
447
+ clearTimeout(timeout) {
448
+ clearTimeout(timeout);
449
+ this._timeouts.delete(timeout);
450
+ }
451
+
452
+ /**
453
+ * Sets an interval that will be automatically cancelled if the client is destroyed.
454
+ * @param {Function} fn Function to execute
455
+ * @param {number} delay Time to wait before executing (in milliseconds)
456
+ * @param {...*} args Arguments for the function
457
+ * @returns {Timeout}
458
+ */
459
+ setInterval(fn, delay, ...args) {
460
+ const interval = setInterval(fn, delay, ...args);
461
+ this._intervals.add(interval);
462
+ return interval;
463
+ }
464
+
465
+ /**
466
+ * Clears an interval.
467
+ * @param {Timeout} interval Interval to cancel
468
+ */
469
+ clearInterval(interval) {
470
+ clearInterval(interval);
471
+ this._intervals.delete(interval);
472
+ }
473
+
474
+ /**
475
+ * Adds a ping to {@link Client#pings}.
476
+ * @param {number} startTime Starting time of the ping
477
+ * @private
478
+ */
479
+ _pong(startTime) {
480
+ this.pings.unshift(Date.now() - startTime);
481
+ if (this.pings.length > 3) this.pings.length = 3;
482
+ this.ws.lastHeartbeatAck = true;
483
+ }
484
+
485
+ /**
486
+ * Adds/updates a friend's presence in {@link Client#presences}.
487
+ * @param {Snowflake} id ID of the user
488
+ * @param {Object} presence Raw presence object from Discord
489
+ * @private
490
+ */
491
+ _setPresence(id, presence) {
492
+ if (this.presences.has(id)) {
493
+ this.presences.get(id).update(presence);
494
+ return;
495
+ }
496
+ this.presences.set(id, new Presence(presence, this));
497
+ }
498
+
499
+ /**
500
+ * Calls {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval} on a script
501
+ * with the client as `this`.
502
+ * @param {string} script Script to eval
503
+ * @returns {*}
504
+ * @private
505
+ */
506
+ _eval(script) {
507
+ return eval(script);
508
+ }
509
+
510
+ /**
511
+ * Validates the client options.
512
+ * @param {ClientOptions} [options=this.options] Options to validate
513
+ * @private
514
+ */
515
+ _validateOptions(options = this.options) { // eslint-disable-line complexity
516
+ if (typeof options.shardCount !== 'number' || isNaN(options.shardCount)) {
517
+ throw new TypeError('The shardCount option must be a number.');
518
+ }
519
+ if (typeof options.shardId !== 'number' || isNaN(options.shardId)) {
520
+ throw new TypeError('The shardId option must be a number.');
521
+ }
522
+ if (options.shardCount < 0) throw new RangeError('The shardCount option must be at least 0.');
523
+ if (options.shardId < 0) throw new RangeError('The shardId option must be at least 0.');
524
+ if (options.shardId !== 0 && options.shardId >= options.shardCount) {
525
+ throw new RangeError('The shardId option must be less than shardCount.');
526
+ }
527
+ if (typeof options.messageCacheMaxSize !== 'number' || isNaN(options.messageCacheMaxSize)) {
528
+ throw new TypeError('The messageCacheMaxSize option must be a number.');
529
+ }
530
+ if (typeof options.messageCacheLifetime !== 'number' || isNaN(options.messageCacheLifetime)) {
531
+ throw new TypeError('The messageCacheLifetime option must be a number.');
532
+ }
533
+ if (typeof options.messageSweepInterval !== 'number' || isNaN(options.messageSweepInterval)) {
534
+ throw new TypeError('The messageSweepInterval option must be a number.');
535
+ }
536
+ if (typeof options.fetchAllMembers !== 'boolean') {
537
+ throw new TypeError('The fetchAllMembers option must be a boolean.');
538
+ }
539
+ if (typeof options.disableEveryone !== 'boolean') {
540
+ throw new TypeError('The disableEveryone option must be a boolean.');
541
+ }
542
+ if (typeof options.restWsBridgeTimeout !== 'number' || isNaN(options.restWsBridgeTimeout)) {
543
+ throw new TypeError('The restWsBridgeTimeout option must be a number.');
544
+ }
545
+ if (!(options.disabledEvents instanceof Array)) throw new TypeError('The disabledEvents option must be an Array.');
546
+ if (typeof options.retryLimit !== 'number' || isNaN(options.retryLimit)) {
547
+ throw new TypeError('The retryLimit options must be a number.');
548
+ }
549
+ }
550
+ }
551
+
552
+ module.exports = Client;
553
+
554
+ /**
555
+ * Emitted for general warnings.
556
+ * @event Client#warn
557
+ * @param {string} info The warning
558
+ */
559
+
560
+ /**
561
+ * Emitted for general debugging information.
562
+ * @event Client#debug
563
+ * @param {string} info The debug information
564
+ */
@@ -0,0 +1,150 @@
1
+ const Constants = require('../util/Constants');
2
+ const Util = require('../util/Util');
3
+ const Guild = require('../structures/Guild');
4
+ const User = require('../structures/User');
5
+ const Emoji = require('../structures/Emoji');
6
+ const GuildChannel = require('../structures/GuildChannel');
7
+ const TextChannel = require('../structures/TextChannel');
8
+ const VoiceChannel = require('../structures/VoiceChannel');
9
+ const CategoryChannel = require('../structures/CategoryChannel');
10
+ const NewsChannel = require('../structures/NewsChannel');
11
+ const StoreChannel = require('../structures/StoreChannel');
12
+ const DMChannel = require('../structures/DMChannel');
13
+ const GroupDMChannel = require('../structures/GroupDMChannel');
14
+
15
+ class ClientDataManager {
16
+ constructor(client) {
17
+ this.client = client;
18
+ }
19
+
20
+ get pastReady() {
21
+ return this.client.ws.connection.status === Constants.Status.READY;
22
+ }
23
+
24
+ newGuild(data) {
25
+ const already = this.client.guilds.has(data.id);
26
+ const guild = new Guild(this.client, data);
27
+ this.client.guilds.set(guild.id, guild);
28
+ if (this.pastReady && !already) {
29
+ /**
30
+ * Emitted whenever the client joins a guild.
31
+ * @event Client#guildCreate
32
+ * @param {Guild} guild The created guild
33
+ */
34
+ if (this.client.options.fetchAllMembers) {
35
+ guild.fetchMembers().then(() => { this.client.emit(Constants.Events.GUILD_CREATE, guild); });
36
+ } else {
37
+ this.client.emit(Constants.Events.GUILD_CREATE, guild);
38
+ }
39
+ }
40
+
41
+ return guild;
42
+ }
43
+
44
+ newUser(data, cache = true) {
45
+ if (this.client.users.has(data.id)) return this.client.users.get(data.id);
46
+ const user = new User(this.client, data);
47
+ if (cache) this.client.users.set(user.id, user);
48
+ return user;
49
+ }
50
+
51
+ newChannel(data, guild) {
52
+ const already = this.client.channels.has(data.id);
53
+ let channel;
54
+ if (data.type === Constants.ChannelTypes.DM) {
55
+ channel = new DMChannel(this.client, data);
56
+ } else if (data.type === Constants.ChannelTypes.GROUP_DM) {
57
+ channel = new GroupDMChannel(this.client, data);
58
+ } else {
59
+ guild = guild || this.client.guilds.get(data.guild_id);
60
+ if (already) {
61
+ channel = this.client.channels.get(data.id);
62
+ } else if (guild) {
63
+ switch (data.type) {
64
+ case Constants.ChannelTypes.TEXT:
65
+ channel = new TextChannel(guild, data);
66
+ break;
67
+ case Constants.ChannelTypes.VOICE:
68
+ channel = new VoiceChannel(guild, data);
69
+ break;
70
+ case Constants.ChannelTypes.CATEGORY:
71
+ channel = new CategoryChannel(guild, data);
72
+ break;
73
+ case Constants.ChannelTypes.NEWS:
74
+ channel = new NewsChannel(guild, data);
75
+ break;
76
+ case Constants.ChannelTypes.STORE:
77
+ channel = new StoreChannel(guild, data);
78
+ break;
79
+ }
80
+ if (channel) {
81
+ guild.channels.set(channel.id, channel);
82
+ }
83
+ }
84
+ }
85
+
86
+ if (channel && !already) {
87
+ if (this.pastReady) this.client.emit(Constants.Events.CHANNEL_CREATE, channel);
88
+ this.client.channels.set(channel.id, channel);
89
+ return channel;
90
+ } else if (already && channel) {
91
+ return channel;
92
+ }
93
+
94
+ return null;
95
+ }
96
+
97
+ newEmoji(data, guild) {
98
+ const already = guild.emojis.has(data.id);
99
+ if (data && !already) {
100
+ let emoji = new Emoji(guild, data);
101
+ this.client.emit(Constants.Events.GUILD_EMOJI_CREATE, emoji);
102
+ guild.emojis.set(emoji.id, emoji);
103
+ return emoji;
104
+ } else if (already) {
105
+ return guild.emojis.get(data.id);
106
+ }
107
+
108
+ return null;
109
+ }
110
+
111
+ killEmoji(emoji) {
112
+ if (!(emoji instanceof Emoji && emoji.guild)) return;
113
+ this.client.emit(Constants.Events.GUILD_EMOJI_DELETE, emoji);
114
+ emoji.guild.emojis.delete(emoji.id);
115
+ }
116
+
117
+ killGuild(guild) {
118
+ const already = this.client.guilds.has(guild.id);
119
+ this.client.guilds.delete(guild.id);
120
+ if (already && this.pastReady) this.client.emit(Constants.Events.GUILD_DELETE, guild);
121
+ }
122
+
123
+ killUser(user) {
124
+ this.client.users.delete(user.id);
125
+ }
126
+
127
+ killChannel(channel) {
128
+ this.client.channels.delete(channel.id);
129
+ if (channel instanceof GuildChannel) channel.guild.channels.delete(channel.id);
130
+ }
131
+
132
+ updateGuild(currentGuild, newData) {
133
+ const oldGuild = Util.cloneObject(currentGuild);
134
+ currentGuild.setup(newData);
135
+ if (this.pastReady) this.client.emit(Constants.Events.GUILD_UPDATE, oldGuild, currentGuild);
136
+ }
137
+
138
+ updateChannel(currentChannel, newData) {
139
+ currentChannel.setup(newData);
140
+ }
141
+
142
+ updateEmoji(currentEmoji, newData) {
143
+ const oldEmoji = Util.cloneObject(currentEmoji);
144
+ currentEmoji.setup(newData);
145
+ this.client.emit(Constants.Events.GUILD_EMOJI_UPDATE, oldEmoji, currentEmoji);
146
+ return currentEmoji;
147
+ }
148
+ }
149
+
150
+ module.exports = ClientDataManager;