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.
- package/.dccache +1 -0
- package/LICENSE +190 -0
- package/README.md +87 -0
- package/browser.js +9 -0
- package/deploy/deploy-key.enc +0 -0
- package/deploy/deploy.sh +90 -0
- package/deploy/test.sh +34 -0
- package/docs/README.md +1 -0
- package/docs/examples/attachments.md +163 -0
- package/docs/examples/avatars.js +29 -0
- package/docs/examples/embed.js +38 -0
- package/docs/examples/greeting.js +30 -0
- package/docs/examples/moderation.md +145 -0
- package/docs/examples/ping.js +29 -0
- package/docs/examples/webhook.js +12 -0
- package/docs/general/faq.md +23 -0
- package/docs/general/updating.md +181 -0
- package/docs/general/welcome.md +95 -0
- package/docs/index.yml +30 -0
- package/docs/logo.svg +19 -0
- package/docs/topics/voice.md +113 -0
- package/docs/topics/web.md +38 -0
- package/package.json +147 -0
- package/src/client/Client.js +564 -0
- package/src/client/ClientDataManager.js +150 -0
- package/src/client/ClientDataResolver.js +376 -0
- package/src/client/ClientManager.js +74 -0
- package/src/client/WebhookClient.js +118 -0
- package/src/client/actions/Action.js +23 -0
- package/src/client/actions/ActionsManager.js +40 -0
- package/src/client/actions/ChannelCreate.js +11 -0
- package/src/client/actions/ChannelDelete.js +30 -0
- package/src/client/actions/ChannelUpdate.js +74 -0
- package/src/client/actions/GuildBanRemove.js +13 -0
- package/src/client/actions/GuildChannelsPositionUpdate.js +19 -0
- package/src/client/actions/GuildDelete.js +57 -0
- package/src/client/actions/GuildEmojiCreate.js +17 -0
- package/src/client/actions/GuildEmojiDelete.js +18 -0
- package/src/client/actions/GuildEmojiUpdate.js +17 -0
- package/src/client/actions/GuildEmojisUpdate.js +38 -0
- package/src/client/actions/GuildMemberGet.js +10 -0
- package/src/client/actions/GuildMemberRemove.js +41 -0
- package/src/client/actions/GuildRoleCreate.js +26 -0
- package/src/client/actions/GuildRoleDelete.js +42 -0
- package/src/client/actions/GuildRoleUpdate.js +41 -0
- package/src/client/actions/GuildRolesPositionUpdate.js +19 -0
- package/src/client/actions/GuildSync.js +29 -0
- package/src/client/actions/GuildUpdate.js +34 -0
- package/src/client/actions/MessageCreate.js +53 -0
- package/src/client/actions/MessageDelete.js +35 -0
- package/src/client/actions/MessageDeleteBulk.js +26 -0
- package/src/client/actions/MessageReactionAdd.js +37 -0
- package/src/client/actions/MessageReactionRemove.js +37 -0
- package/src/client/actions/MessageReactionRemoveAll.js +25 -0
- package/src/client/actions/MessageUpdate.js +40 -0
- package/src/client/actions/Ready.js +1 -0
- package/src/client/actions/Ready.js.bak +65 -0
- package/src/client/actions/UserGet.js +11 -0
- package/src/client/actions/UserNoteUpdate.js +30 -0
- package/src/client/actions/UserUpdate.js +33 -0
- package/src/client/rest/APIRequest.js +56 -0
- package/src/client/rest/DiscordAPIError.js +60 -0
- package/src/client/rest/RESTManager.js +58 -0
- package/src/client/rest/RESTMethods.js +1006 -0
- package/src/client/rest/RequestHandlers/Burst.js +90 -0
- package/src/client/rest/RequestHandlers/RequestHandler.js +54 -0
- package/src/client/rest/RequestHandlers/Sequential.js +132 -0
- package/src/client/rest/UserAgentManager.js +25 -0
- package/src/client/voice/ClientVoiceManager.js +81 -0
- package/src/client/voice/VoiceBroadcast.js +366 -0
- package/src/client/voice/VoiceConnection.js +530 -0
- package/src/client/voice/VoiceUDPClient.js +127 -0
- package/src/client/voice/VoiceWebSocket.js +246 -0
- package/src/client/voice/dispatcher/StreamDispatcher.js +331 -0
- package/src/client/voice/opus/BaseOpusEngine.js +60 -0
- package/src/client/voice/opus/NodeOpusEngine.js +40 -0
- package/src/client/voice/opus/OpusEngineList.js +28 -0
- package/src/client/voice/opus/OpusScriptEngine.js +45 -0
- package/src/client/voice/player/AudioPlayer.js +170 -0
- package/src/client/voice/receiver/VoiceReadable.js +17 -0
- package/src/client/voice/receiver/VoiceReceiver.js +219 -0
- package/src/client/voice/util/SecretKey.js +16 -0
- package/src/client/voice/util/Secretbox.js +33 -0
- package/src/client/voice/util/VolumeInterface.js +86 -0
- package/src/client/websocket/WebSocketConnection.js +506 -0
- package/src/client/websocket/WebSocketManager.js +90 -0
- package/src/client/websocket/packets/WebSocketPacketManager.js +110 -0
- package/src/client/websocket/packets/handlers/AbstractHandler.js +11 -0
- package/src/client/websocket/packets/handlers/ChannelCreate.js +17 -0
- package/src/client/websocket/packets/handlers/ChannelDelete.js +20 -0
- package/src/client/websocket/packets/handlers/ChannelPinsUpdate.js +37 -0
- package/src/client/websocket/packets/handlers/ChannelUpdate.js +11 -0
- package/src/client/websocket/packets/handlers/GuildBanAdd.js +23 -0
- package/src/client/websocket/packets/handlers/GuildBanRemove.js +20 -0
- package/src/client/websocket/packets/handlers/GuildCreate.js +22 -0
- package/src/client/websocket/packets/handlers/GuildDelete.js +19 -0
- package/src/client/websocket/packets/handlers/GuildEmojisUpdate.js +11 -0
- package/src/client/websocket/packets/handlers/GuildIntegrationsUpdate.js +19 -0
- package/src/client/websocket/packets/handlers/GuildMemberAdd.js +17 -0
- package/src/client/websocket/packets/handlers/GuildMemberRemove.js +13 -0
- package/src/client/websocket/packets/handlers/GuildMemberUpdate.js +18 -0
- package/src/client/websocket/packets/handlers/GuildMembersChunk.js +33 -0
- package/src/client/websocket/packets/handlers/GuildRoleCreate.js +11 -0
- package/src/client/websocket/packets/handlers/GuildRoleDelete.js +11 -0
- package/src/client/websocket/packets/handlers/GuildRoleUpdate.js +11 -0
- package/src/client/websocket/packets/handlers/GuildSync.js +11 -0
- package/src/client/websocket/packets/handlers/GuildUpdate.js +11 -0
- package/src/client/websocket/packets/handlers/MessageCreate.js +19 -0
- package/src/client/websocket/packets/handlers/MessageDelete.js +19 -0
- package/src/client/websocket/packets/handlers/MessageDeleteBulk.js +17 -0
- package/src/client/websocket/packets/handlers/MessageReactionAdd.js +11 -0
- package/src/client/websocket/packets/handlers/MessageReactionRemove.js +11 -0
- package/src/client/websocket/packets/handlers/MessageReactionRemoveAll.js +11 -0
- package/src/client/websocket/packets/handlers/MessageUpdate.js +11 -0
- package/src/client/websocket/packets/handlers/PresenceUpdate.js +76 -0
- package/src/client/websocket/packets/handlers/Ready.js +83 -0
- package/src/client/websocket/packets/handlers/RelationshipAdd.js +19 -0
- package/src/client/websocket/packets/handlers/RelationshipRemove.js +19 -0
- package/src/client/websocket/packets/handlers/Resumed.js +28 -0
- package/src/client/websocket/packets/handlers/TypingStart.js +68 -0
- package/src/client/websocket/packets/handlers/UserGuildSettingsUpdate.js +21 -0
- package/src/client/websocket/packets/handlers/UserNoteUpdate.js +12 -0
- package/src/client/websocket/packets/handlers/UserSettingsUpdate.js +18 -0
- package/src/client/websocket/packets/handlers/UserUpdate.js +11 -0
- package/src/client/websocket/packets/handlers/VoiceServerUpdate.js +19 -0
- package/src/client/websocket/packets/handlers/VoiceStateUpdate.js +52 -0
- package/src/client/websocket/packets/handlers/WebhooksUpdate.js +19 -0
- package/src/index.js +66 -0
- package/src/sharding/Shard.js +282 -0
- package/src/sharding/ShardClientUtil.js +146 -0
- package/src/sharding/ShardingManager.js +220 -0
- package/src/structures/Attachment.js +75 -0
- package/src/structures/CategoryChannel.js +22 -0
- package/src/structures/Channel.js +78 -0
- package/src/structures/ClientUser.js +447 -0
- package/src/structures/ClientUserChannelOverride.js +30 -0
- package/src/structures/ClientUserGuildSettings.js +60 -0
- package/src/structures/ClientUserSettings.js +80 -0
- package/src/structures/DMChannel.js +76 -0
- package/src/structures/Emoji.js +256 -0
- package/src/structures/GroupDMChannel.js +246 -0
- package/src/structures/Guild.js +1461 -0
- package/src/structures/GuildAuditLogs.js +371 -0
- package/src/structures/GuildChannel.js +537 -0
- package/src/structures/GuildMember.js +613 -0
- package/src/structures/Invite.js +164 -0
- package/src/structures/Message.js +605 -0
- package/src/structures/MessageAttachment.js +68 -0
- package/src/structures/MessageCollector.js +100 -0
- package/src/structures/MessageEmbed.js +386 -0
- package/src/structures/MessageMentions.js +144 -0
- package/src/structures/MessageReaction.js +96 -0
- package/src/structures/NewsChannel.js +24 -0
- package/src/structures/OAuth2Application.js +148 -0
- package/src/structures/PartialGuild.js +51 -0
- package/src/structures/PartialGuildChannel.js +44 -0
- package/src/structures/PermissionOverwrites.js +69 -0
- package/src/structures/Presence.js +241 -0
- package/src/structures/ReactionCollector.js +85 -0
- package/src/structures/ReactionEmoji.js +49 -0
- package/src/structures/RichEmbed.js +295 -0
- package/src/structures/Role.js +376 -0
- package/src/structures/StoreChannel.js +25 -0
- package/src/structures/TextChannel.js +154 -0
- package/src/structures/User.js +329 -0
- package/src/structures/UserConnection.js +48 -0
- package/src/structures/UserProfile.js +62 -0
- package/src/structures/VoiceChannel.js +146 -0
- package/src/structures/VoiceRegion.js +50 -0
- package/src/structures/Webhook.js +304 -0
- package/src/structures/interfaces/Collector.js +179 -0
- package/src/structures/interfaces/TextBasedChannel.js +635 -0
- package/src/structures/shared/resolvePermissions.js +26 -0
- package/src/util/Collection.js +532 -0
- package/src/util/Constants.js +845 -0
- package/src/util/Permissions.js +306 -0
- package/src/util/Snowflake.js +82 -0
- package/src/util/Util.js +221 -0
- package/test/random.js +207 -0
- package/test/shard.js +31 -0
- package/test/sharder.js +7 -0
- package/test/voice.js +78 -0
- package/test/webpack.html +31 -0
- package/tsconfig.json +13 -0
- package/tslint.json +62 -0
- package/typings/discord.js-test.ts +69 -0
- package/typings/index.d.ts +2190 -0
- 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;
|