cloudstorm 0.1.4 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +7 -7
- package/README.md +61 -47
- package/dist/Client.d.ts +160 -0
- package/dist/Client.js +177 -0
- package/dist/Constants.d.ts +49 -0
- package/dist/Constants.js +51 -0
- package/dist/Intents.d.ts +23 -0
- package/dist/Intents.js +34 -0
- package/dist/Shard.d.ts +75 -0
- package/dist/Shard.js +94 -0
- package/dist/ShardManager.d.ts +84 -0
- package/dist/ShardManager.js +211 -0
- package/dist/Types.d.ts +70 -0
- package/dist/Types.js +2 -0
- package/dist/connector/DiscordConnector.d.ts +142 -0
- package/dist/connector/DiscordConnector.js +414 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +24 -0
- package/dist/structures/BetterWs.d.ts +87 -0
- package/dist/structures/BetterWs.js +194 -0
- package/dist/structures/RatelimitBucket.d.ts +41 -0
- package/dist/structures/RatelimitBucket.js +103 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +40 -30
- package/.eslintrc.json +0 -28
- package/.jsdoc.json +0 -18
- package/.travis.yml +0 -17
- package/docma.config.json +0 -51
- package/example/amqp/index.js +0 -31
- package/example/basic/index.js +0 -18
- package/index.d.ts +0 -220
- package/index.js +0 -10
- package/src/Client.js +0 -229
- package/src/Constants.js +0 -16
- package/src/Shard.js +0 -174
- package/src/ShardManager.js +0 -309
- package/src/connector/DiscordConnector.js +0 -403
- package/src/structures/BetterWs.js +0 -234
- package/src/structures/RatelimitBucket.js +0 -89
package/src/ShardManager.js
DELETED
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
let Shard = require('./Shard');
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @typedef ShardManager
|
|
6
|
-
* @description Class used for managing shards for the user
|
|
7
|
-
*
|
|
8
|
-
* This class is automatically instantiated by the library and is documented for reference
|
|
9
|
-
* @property {Client} client - client that created this shard manager
|
|
10
|
-
* @property {Object} options - options of the [client](Client.html)
|
|
11
|
-
* @property {Object} shards - Object with a map of shards, mapped by shard id
|
|
12
|
-
* @property {Array} connectQueue - Array containing shards that are not connected yet or have to be reconnected
|
|
13
|
-
* @property {Date} lastConnectionAttempt - unix timestamp of the last time a shard tried connecting to discord
|
|
14
|
-
* @property {Number} connectQueueInterval - Time in milliseconds for the interval checking any shards that may need to be connected to discord
|
|
15
|
-
*/
|
|
16
|
-
class ShardManager {
|
|
17
|
-
/**
|
|
18
|
-
* Create a new ShardManager
|
|
19
|
-
* @param {Client} client
|
|
20
|
-
* @private
|
|
21
|
-
*/
|
|
22
|
-
constructor(client) {
|
|
23
|
-
this.client = client;
|
|
24
|
-
this.options = client.options;
|
|
25
|
-
if (!this.options.connectQueueInterval) {
|
|
26
|
-
this.options.connectQueueInterval = 1000 * 5;
|
|
27
|
-
}
|
|
28
|
-
this.shards = {};
|
|
29
|
-
this.connectQueue = [];
|
|
30
|
-
this.lastConnectionAttempt = null;
|
|
31
|
-
this.connectQueueInterval = setInterval(() => {
|
|
32
|
-
this._checkQueue();
|
|
33
|
-
}, this.options.connectQueueInterval);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Create the shard instances and add them to the connection queue
|
|
38
|
-
* @protected
|
|
39
|
-
*/
|
|
40
|
-
spawn() {
|
|
41
|
-
for (let i = this.options.firstShardId; i < this.options.lastShardId + 1; i++) {
|
|
42
|
-
/**
|
|
43
|
-
* @event Client#debug
|
|
44
|
-
* @type {String}
|
|
45
|
-
* @description used for debugging of the internals of the library
|
|
46
|
-
* @private
|
|
47
|
-
*/
|
|
48
|
-
this.client.emit('debug', `Spawned shard ${i}`);
|
|
49
|
-
this.shards[i] = new Shard(i, this.client);
|
|
50
|
-
this.connectQueue.push({action: 'connect', shard: this.shards[i]});
|
|
51
|
-
this._addListener(this.shards[i]);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Disconnect all shards
|
|
57
|
-
* @protected
|
|
58
|
-
*/
|
|
59
|
-
disconnect() {
|
|
60
|
-
for (let shardKey in this.shards) {
|
|
61
|
-
if (this.shards.hasOwnProperty(shardKey)) {
|
|
62
|
-
let shard = this.shards[shardKey];
|
|
63
|
-
shard.disconnect();
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Actually connect/re-identify a single shard by calling it's connect() or identify() method and reset the connection timer
|
|
70
|
-
* @param {Object} data - Object with a shard and action key
|
|
71
|
-
* @param {String} data.action - Action to execute, can either be `connect` or `identify`
|
|
72
|
-
* @param {Shard} data.shard - shard that should connect to discord
|
|
73
|
-
* @private
|
|
74
|
-
*/
|
|
75
|
-
_connectShard({action, shard}) {
|
|
76
|
-
/**
|
|
77
|
-
* @event Client#debug
|
|
78
|
-
* @type {String}
|
|
79
|
-
* @description used for debugging of the internals of the library
|
|
80
|
-
* @private
|
|
81
|
-
*/
|
|
82
|
-
this.client.emit('debug', `${action === 'connect' ? 'Connecting' : 'Identifying'} Shard ${shard.id} Status: ${shard.connector.status} Ready: ${shard.ready}`);
|
|
83
|
-
if (this.lastConnectionAttempt <= Date.now() - 6000) {
|
|
84
|
-
switch (action) {
|
|
85
|
-
case 'identify':
|
|
86
|
-
this.lastConnectionAttempt = Date.now();
|
|
87
|
-
this.client.emit('debug', `Identifying shard ${shard.id}`);
|
|
88
|
-
shard.connector.identify(true);
|
|
89
|
-
break;
|
|
90
|
-
case 'connect':
|
|
91
|
-
default:
|
|
92
|
-
if (shard.connector.status !== 'connecting' && !shard.ready) {
|
|
93
|
-
this.lastConnectionAttempt = Date.now();
|
|
94
|
-
this.client.emit('debug', `Connecting shard ${shard.id}`);
|
|
95
|
-
shard.connect();
|
|
96
|
-
}
|
|
97
|
-
break;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Check if there are shards that are not connected yet and connect them if over 6 seconds have passed since the last attempt
|
|
104
|
-
* @private
|
|
105
|
-
*/
|
|
106
|
-
_checkQueue() {
|
|
107
|
-
/**
|
|
108
|
-
* @event Client#debug
|
|
109
|
-
* @type {String}
|
|
110
|
-
* @description used for debugging of the internals of the library
|
|
111
|
-
* @private
|
|
112
|
-
*/
|
|
113
|
-
this.client.emit('debug', `Checking queue Length: ${this.connectQueue.length} LastAttempt: ${this.lastConnectionAttempt} Current Time: ${Date.now()}`);
|
|
114
|
-
if (this.connectQueue.length > 0 && this.lastConnectionAttempt <= Date.now() - 6000) {
|
|
115
|
-
this._connectShard(...this.connectQueue.splice(0, 1));
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Add event listeners to a shard to that the manager can act on received events
|
|
121
|
-
* @param {Shard} shard - shard to add the event listeners to
|
|
122
|
-
* @private
|
|
123
|
-
*/
|
|
124
|
-
_addListener(shard) {
|
|
125
|
-
shard.on('ready', (resume) => {
|
|
126
|
-
this.shards[shard.id].ready = true;
|
|
127
|
-
/**
|
|
128
|
-
* @event Client#debug
|
|
129
|
-
* @type {String}
|
|
130
|
-
* @description used for debugging of the internals of the library
|
|
131
|
-
* @private
|
|
132
|
-
*/
|
|
133
|
-
this.client.emit('debug', `Shard ${shard.id} ${resume ? 'has resumed' : 'is ready'}`);
|
|
134
|
-
/**
|
|
135
|
-
* @event Client#shardReady
|
|
136
|
-
* @type {Object}
|
|
137
|
-
* @property {Number} id - id of the shard
|
|
138
|
-
* @property {Boolean} ready - whether the shard turned ready or resumed
|
|
139
|
-
* @description Emitted when a single shard resumes or turns ready
|
|
140
|
-
*/
|
|
141
|
-
this.client.emit('shardReady', {id: shard.id, ready: !resume});
|
|
142
|
-
this._checkReady();
|
|
143
|
-
});
|
|
144
|
-
shard.on('error', (error) => {
|
|
145
|
-
/**
|
|
146
|
-
* @event Client#error
|
|
147
|
-
* @type {Error}
|
|
148
|
-
* @description Emitted when an error occurs somewhere in the library
|
|
149
|
-
*/
|
|
150
|
-
this.client.emit('error', error);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
shard.on('disconnect', (code, reason, forceIdentify, gracefulClose) => {
|
|
154
|
-
/**
|
|
155
|
-
* @event Client#debug
|
|
156
|
-
* @type {String}
|
|
157
|
-
* @description used for debugging of the internals of the library
|
|
158
|
-
* @private
|
|
159
|
-
*/
|
|
160
|
-
this.client.emit('debug', `${shard.id} ws closed with code ${code} and reason: ${reason}`);
|
|
161
|
-
if (code === 1000 && gracefulClose) {
|
|
162
|
-
this._checkDisconnect();
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
shard.forceIdentify = forceIdentify;
|
|
166
|
-
this.connectQueue.push({action: 'connect', shard});
|
|
167
|
-
});
|
|
168
|
-
shard.on('queueIdentify', (shardId) => {
|
|
169
|
-
if (!this.shards[shardId]) {
|
|
170
|
-
this.client.emit('debug', `Received a queueIdentify event for not existing shard ${shardId}`);
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
this.connectQueue.unshift({action: 'identify', shard: this.shards[shardId]});
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Checks if all shards are ready
|
|
179
|
-
* @private
|
|
180
|
-
*/
|
|
181
|
-
_checkReady() {
|
|
182
|
-
for (let shardId in this.shards) {
|
|
183
|
-
if (this.shards.hasOwnProperty(shardId)) {
|
|
184
|
-
if (!this.shards[shardId].ready) {
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* @event Client#ready
|
|
191
|
-
* @type {void}
|
|
192
|
-
* @description Emitted when all shards turn ready
|
|
193
|
-
* @example
|
|
194
|
-
* //Connect bot to discord and get a log in the console once it's ready
|
|
195
|
-
* let bot = new CloudStorm(token)
|
|
196
|
-
* await bot.connect()
|
|
197
|
-
* bot.on('ready', () => {
|
|
198
|
-
* // The bot has connected to discord successfully and authenticated with the gateway
|
|
199
|
-
* });
|
|
200
|
-
*/
|
|
201
|
-
this.client.emit('ready');
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Checks if all shards are disconnected
|
|
206
|
-
* @private
|
|
207
|
-
*/
|
|
208
|
-
_checkDisconnect() {
|
|
209
|
-
for (let shardId in this.shards) {
|
|
210
|
-
if (this.shards.hasOwnProperty(shardId)) {
|
|
211
|
-
if (this.shards[shardId].connector.status !== 'disconnected') {
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* @event Client#disconnected
|
|
218
|
-
* @type {void}
|
|
219
|
-
* @description Emitted when all shards have disconnected successfully
|
|
220
|
-
*/
|
|
221
|
-
this.client.emit('disconnected');
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Update the status of all currently connected shards
|
|
226
|
-
* @param {Presence} data - payload to send
|
|
227
|
-
* @protected
|
|
228
|
-
*/
|
|
229
|
-
statusUpdate(data = {}) {
|
|
230
|
-
let shardPromises = [];
|
|
231
|
-
for (let shardKey in this.shards) {
|
|
232
|
-
if (this.shards.hasOwnProperty(shardKey)) {
|
|
233
|
-
let shard = this.shards[shardKey];
|
|
234
|
-
if (shard.ready) {
|
|
235
|
-
shardPromises.push(shard.statusUpdate(data));
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
return Promise.all(shardPromises);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Update the status of a single connected shard
|
|
244
|
-
* @param {Number} shardId - internal id of the shard
|
|
245
|
-
* @param {Presence} data - payload to send
|
|
246
|
-
* @protected
|
|
247
|
-
*/
|
|
248
|
-
shardStatusUpdate(shardId, data = {}) {
|
|
249
|
-
return new Promise((res, rej) => {
|
|
250
|
-
let shard = this.shards[shardId];
|
|
251
|
-
if (!shard) {
|
|
252
|
-
rej(new Error(`Shard ${shardId} does not exist`));
|
|
253
|
-
}
|
|
254
|
-
if (!shard.ready) {
|
|
255
|
-
shard.once('ready', () => {
|
|
256
|
-
shard.statusUpdate(data).then(result => res(result)).catch(e => rej(e));
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
shard.statusUpdate(data).then(result => res(result)).catch(e => rej(e));
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Send a voice state update payload with a certain shard
|
|
265
|
-
* @param {Number} shardId - id of the shard
|
|
266
|
-
* @param {VoiceStateUpdate} data - payload to send
|
|
267
|
-
* @returns {Promise.<void>}
|
|
268
|
-
* @protected
|
|
269
|
-
*/
|
|
270
|
-
voiceStateUpdate(shardId, data) {
|
|
271
|
-
return new Promise((res, rej) => {
|
|
272
|
-
let shard = this.shards[shardId];
|
|
273
|
-
if (!shard) {
|
|
274
|
-
rej(new Error(`Shard ${shardId} does not exist`));
|
|
275
|
-
}
|
|
276
|
-
if (!shard.ready) {
|
|
277
|
-
shard.once('ready', () => {
|
|
278
|
-
shard.voiceStateUpdate(data).then(result => res(result)).catch(e => rej(e));
|
|
279
|
-
});
|
|
280
|
-
}
|
|
281
|
-
shard.voiceStateUpdate(data).then(result => res(result)).catch(e => rej(e));
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
/**
|
|
286
|
-
* Send a request guild members payload with a certain shard
|
|
287
|
-
* @param {Number} shardId - id of the shard
|
|
288
|
-
* @param {RequestGuildMembers} data - payload to send
|
|
289
|
-
* @returns {Promise.<void>}
|
|
290
|
-
* @protected
|
|
291
|
-
*/
|
|
292
|
-
requestGuildMembers(shardId, data) {
|
|
293
|
-
return new Promise((res, rej) => {
|
|
294
|
-
let shard = this.shards[shardId];
|
|
295
|
-
if (!shard) {
|
|
296
|
-
rej(new Error(`Shard ${shardId} does not exist`));
|
|
297
|
-
}
|
|
298
|
-
if (!shard.ready) {
|
|
299
|
-
shard.once('ready', () => {
|
|
300
|
-
shard.requestGuildMembers(data).then(result => res(result)).catch(e => rej(e));
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
shard.requestGuildMembers(data).then(result => res(result)).catch(e => rej(e));
|
|
304
|
-
});
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
module.exports = ShardManager;
|
|
@@ -1,403 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
let EventEmitter;
|
|
3
|
-
try {
|
|
4
|
-
EventEmitter = require('eventemitter3');
|
|
5
|
-
} catch (e) {
|
|
6
|
-
EventEmitter = require('events').EventEmitter;
|
|
7
|
-
}
|
|
8
|
-
const BetterWs = require('../structures/BetterWs');
|
|
9
|
-
const OP = require('../Constants').GATEWAY_OP_CODES;
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* @typedef DiscordConnector
|
|
13
|
-
* @description Class used for acting based on received events
|
|
14
|
-
*
|
|
15
|
-
* This class is automatically instantiated by the library and is documented for reference
|
|
16
|
-
* @property {String} id - id of the shard that created this class
|
|
17
|
-
* @property {Client} client - Main client instance
|
|
18
|
-
* @property {Object} options - options passed from the main client instance
|
|
19
|
-
* @property {Boolean} reconnect - whether autoreconnect is enabled
|
|
20
|
-
* @property {BetterWs} betterWs - Websocket class used for connecting to discord
|
|
21
|
-
* @property {Object} heartbeatInterval - interval within which heartbeats should be sent to discord
|
|
22
|
-
* @property {String[]} _trace - trace of servers used when connecting to discord
|
|
23
|
-
* @property {Number} seq - sequence value used on RESUMES and heartbeats
|
|
24
|
-
* @property {String} status - status of this connector
|
|
25
|
-
* @property {String} sessionId - session id of the current session, used in RESUMES
|
|
26
|
-
* @property {Boolean} forceIdentify - whether the connector should just IDENTIFY again and don't try to resume
|
|
27
|
-
*/
|
|
28
|
-
class DiscordConnector extends EventEmitter {
|
|
29
|
-
/**
|
|
30
|
-
* Create a new Discord Connector
|
|
31
|
-
* @param {String} id - id of the shard that created this class
|
|
32
|
-
* @param {Client} client - Main client instance
|
|
33
|
-
* @private
|
|
34
|
-
*/
|
|
35
|
-
constructor(id, client) {
|
|
36
|
-
super();
|
|
37
|
-
this.id = id;
|
|
38
|
-
this.client = client;
|
|
39
|
-
this.options = client.options;
|
|
40
|
-
this.reconnect = this.options.reconnect;
|
|
41
|
-
this.betterWs = null;
|
|
42
|
-
this.heartbeatInterval = null;
|
|
43
|
-
this._trace = null;
|
|
44
|
-
this.seq = 0;
|
|
45
|
-
this.status = 'init';
|
|
46
|
-
this.sessionId = null;
|
|
47
|
-
this.forceIdentify = false;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Connect to discord
|
|
52
|
-
* @protected
|
|
53
|
-
*/
|
|
54
|
-
connect() {
|
|
55
|
-
if (!this.betterWs) {
|
|
56
|
-
this.betterWs = new BetterWs(this.options.endpoint);
|
|
57
|
-
} else {
|
|
58
|
-
this.betterWs.removeAllListeners();
|
|
59
|
-
this.betterWs.recreateWs(this.options.endpoint);
|
|
60
|
-
}
|
|
61
|
-
this.betterWs.on('ws_open', () => {
|
|
62
|
-
this.status = 'connecting';
|
|
63
|
-
});
|
|
64
|
-
this.betterWs.on('ws_message', (msg) => {
|
|
65
|
-
this.messageAction(msg);
|
|
66
|
-
});
|
|
67
|
-
this.betterWs.on('ws_close', (code, reason) => {
|
|
68
|
-
this.client.emit('debug', `Websocket of shard ${this.id} closed with code ${code} and reason: ${reason}`);
|
|
69
|
-
this.handleWsClose(code, reason);
|
|
70
|
-
});
|
|
71
|
-
this.betterWs.on('debug', event => {
|
|
72
|
-
/**
|
|
73
|
-
* @event Client#debug
|
|
74
|
-
* @type {Object}
|
|
75
|
-
* @description Debug event used for debugging the library
|
|
76
|
-
* @private
|
|
77
|
-
*/
|
|
78
|
-
this.client.emit('debug', event);
|
|
79
|
-
});
|
|
80
|
-
this.betterWs.on('debug_send', data => {
|
|
81
|
-
/**
|
|
82
|
-
* @event Client#rawSend
|
|
83
|
-
* @type {Object}
|
|
84
|
-
* @description Websocket payload which was sent to discord, this event is emitted on **every single** websocket message that was sent.
|
|
85
|
-
*/
|
|
86
|
-
this.client.emit('rawSend', data);
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Close the websocket connection and disconnect
|
|
92
|
-
* @returns {Promise.<void>}
|
|
93
|
-
* @protected
|
|
94
|
-
*/
|
|
95
|
-
disconnect() {
|
|
96
|
-
return this.betterWs.close(1000, 'Disconnect from User');
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Called with a parsed Websocket message to execute further actions
|
|
101
|
-
* @param {Object} message - message that was received
|
|
102
|
-
* @protected
|
|
103
|
-
*/
|
|
104
|
-
messageAction(message) {
|
|
105
|
-
/**
|
|
106
|
-
* @event Client#rawReceive
|
|
107
|
-
* @type {Object}
|
|
108
|
-
* @description Websocket message received from discord, this event is emitted on **every single** websocket message you may receive.
|
|
109
|
-
*/
|
|
110
|
-
this.client.emit('rawReceive', message);
|
|
111
|
-
if (message.s) {
|
|
112
|
-
if (message.s > this.seq + 1) {
|
|
113
|
-
this.client.emit('debug', `Shard ${this.id}, invalid sequence: current: ${this.seq} message: ${message.s}`);
|
|
114
|
-
this.seq = message.s;
|
|
115
|
-
this.resume();
|
|
116
|
-
}
|
|
117
|
-
this.seq = message.s;
|
|
118
|
-
}
|
|
119
|
-
switch (message.op) {
|
|
120
|
-
case OP.DISPATCH:
|
|
121
|
-
this.handleDispatch(message);
|
|
122
|
-
break;
|
|
123
|
-
case OP.HELLO:
|
|
124
|
-
this.heartbeat();
|
|
125
|
-
this.heartbeatInterval = setInterval(() => {
|
|
126
|
-
this.heartbeat(message.d.heartbeat_interval);
|
|
127
|
-
}, message.d.heartbeat_interval - 5000);
|
|
128
|
-
this._trace = message.d._trace;
|
|
129
|
-
this.identify();
|
|
130
|
-
this.client.emit('debug', `Shard ${this.id} received HELLO`);
|
|
131
|
-
break;
|
|
132
|
-
case OP.HEARTBEAT:
|
|
133
|
-
this.heartbeat();
|
|
134
|
-
break;
|
|
135
|
-
case OP.HEARTBEAT_ACK:
|
|
136
|
-
break;
|
|
137
|
-
case OP.RECONNECT:
|
|
138
|
-
this.reset();
|
|
139
|
-
this.betterWs.close();
|
|
140
|
-
break;
|
|
141
|
-
case OP.INVALID_SESSION:
|
|
142
|
-
if (message.d && this.sessionId) {
|
|
143
|
-
this.resume();
|
|
144
|
-
} else {
|
|
145
|
-
this.seq = 0;
|
|
146
|
-
this.sessionId = '';
|
|
147
|
-
/**
|
|
148
|
-
* @event DiscordConnector#queueIdentify
|
|
149
|
-
* @type {Number}
|
|
150
|
-
* @description Emitted when the connector received an op9 code
|
|
151
|
-
* @private
|
|
152
|
-
*/
|
|
153
|
-
this.emit('queueIdentify', this.id);
|
|
154
|
-
}
|
|
155
|
-
break;
|
|
156
|
-
default:
|
|
157
|
-
/**
|
|
158
|
-
* @event DiscordConnector#event
|
|
159
|
-
* @type {Object}
|
|
160
|
-
* @description Forward the event
|
|
161
|
-
* @private
|
|
162
|
-
*/
|
|
163
|
-
this.emit('event', message);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Reset this connector
|
|
169
|
-
* @protected
|
|
170
|
-
*/
|
|
171
|
-
reset() {
|
|
172
|
-
this.sessionId = null;
|
|
173
|
-
this.seq = 0;
|
|
174
|
-
this._trace = null;
|
|
175
|
-
clearInterval(this.heartbeatInterval);
|
|
176
|
-
this.heartbeatInterval = null;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Send a identify payload to the gateway
|
|
181
|
-
* @param {Boolean} force - Whether CloudStorm should send an IDENTIFY even if there's a session that could be resumed
|
|
182
|
-
* @returns {Promise.<void>}
|
|
183
|
-
* @protected
|
|
184
|
-
*/
|
|
185
|
-
identify(force) {
|
|
186
|
-
if (this.sessionId && !this.forceIdentify && !force) {
|
|
187
|
-
return this.resume();
|
|
188
|
-
}
|
|
189
|
-
let data = {
|
|
190
|
-
op: OP.IDENTIFY, d: {
|
|
191
|
-
token: this.options.token,
|
|
192
|
-
properties: {
|
|
193
|
-
os: process.platform,
|
|
194
|
-
browser: 'CloudStorm',
|
|
195
|
-
device: 'CloudStorm'
|
|
196
|
-
},
|
|
197
|
-
large_threshold: this.options.largeGuildThreshold,
|
|
198
|
-
shard: [this.id, this.options.shardAmount],
|
|
199
|
-
presence: this.options.initialPresence ? this._checkPresenceData(this.options.initialPresence) : null
|
|
200
|
-
}
|
|
201
|
-
};
|
|
202
|
-
this.forceIdentify = false;
|
|
203
|
-
return this.betterWs.sendMessage(data);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* Send a resume payload to the gateway
|
|
208
|
-
* @returns {Promise.<void>}
|
|
209
|
-
* @protected
|
|
210
|
-
*/
|
|
211
|
-
resume() {
|
|
212
|
-
return this.betterWs.sendMessage({
|
|
213
|
-
op: OP.RESUME,
|
|
214
|
-
d: {seq: this.seq, token: this.options.token, session_id: this.sessionId}
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Send a heartbeat to discord
|
|
220
|
-
* @protected
|
|
221
|
-
*/
|
|
222
|
-
heartbeat() {
|
|
223
|
-
this.betterWs.sendMessage({op: OP.HEARTBEAT, d: this.seq});
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Handle dispatch events
|
|
228
|
-
* @param {Object} message - message received from the websocket
|
|
229
|
-
* @protected
|
|
230
|
-
*/
|
|
231
|
-
handleDispatch(message) {
|
|
232
|
-
switch (message.t) {
|
|
233
|
-
case 'READY':
|
|
234
|
-
case 'RESUMED':
|
|
235
|
-
if (message.t === 'READY') {
|
|
236
|
-
this.sessionId = message.d.session_id;
|
|
237
|
-
}
|
|
238
|
-
this.status = 'ready';
|
|
239
|
-
this._trace = message.d._trace;
|
|
240
|
-
/**
|
|
241
|
-
* @event DiscordConnector#ready
|
|
242
|
-
* @type {void}
|
|
243
|
-
* @description Emitted once the connector is ready (again)
|
|
244
|
-
* @private
|
|
245
|
-
*/
|
|
246
|
-
this.emit('ready', message.t === 'RESUMED');
|
|
247
|
-
/**
|
|
248
|
-
* @event DiscordConnector#event
|
|
249
|
-
* @type {Object}
|
|
250
|
-
* @description Emitted once an event was received from discord
|
|
251
|
-
* @private
|
|
252
|
-
*/
|
|
253
|
-
this.emit('event', message);
|
|
254
|
-
break;
|
|
255
|
-
default:
|
|
256
|
-
/**
|
|
257
|
-
* @event DiscordConnector#event
|
|
258
|
-
* @type {Object}
|
|
259
|
-
* @description Emitted once an event was received from discord
|
|
260
|
-
* @private
|
|
261
|
-
*/
|
|
262
|
-
this.emit('event', message);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
* Handle a close from the underlying websocket
|
|
268
|
-
* @param {Number} code - websocket close code
|
|
269
|
-
* @param {String} reason - close reason if any
|
|
270
|
-
* @protected
|
|
271
|
-
*/
|
|
272
|
-
handleWsClose(code, reason) {
|
|
273
|
-
let forceIdentify = false;
|
|
274
|
-
let gracefulClose = false;
|
|
275
|
-
this.status = 'disconnected';
|
|
276
|
-
if (code === 4004) {
|
|
277
|
-
/**
|
|
278
|
-
* @event DiscordConnector#error
|
|
279
|
-
* @type {String}
|
|
280
|
-
* @description Emitted when the token was invalid
|
|
281
|
-
* @private
|
|
282
|
-
*/
|
|
283
|
-
this.emit('error', 'Tried to connect with an invalid token');
|
|
284
|
-
return;
|
|
285
|
-
}
|
|
286
|
-
if (code === 4010) {
|
|
287
|
-
/**
|
|
288
|
-
* @event DiscordConnector#error
|
|
289
|
-
* @type {String}
|
|
290
|
-
* @description Emitted when the user tried to connect with bad sharding data
|
|
291
|
-
* @private
|
|
292
|
-
*/
|
|
293
|
-
this.emit('error', 'Invalid sharding data, check your client options');
|
|
294
|
-
return;
|
|
295
|
-
}
|
|
296
|
-
if (code === 4011) {
|
|
297
|
-
/**
|
|
298
|
-
* @event DiscordConnector#error
|
|
299
|
-
* @type {String}
|
|
300
|
-
* @description Emitted when the shard would be on over 2500 guilds
|
|
301
|
-
* @private
|
|
302
|
-
*/
|
|
303
|
-
this.emit('error', 'Shard would be on over 2500 guilds. Add more shards');
|
|
304
|
-
return;
|
|
305
|
-
}
|
|
306
|
-
// force identify if the session is marked as invalid
|
|
307
|
-
if (code === 4009) {
|
|
308
|
-
forceIdentify = true;
|
|
309
|
-
}
|
|
310
|
-
// don't try to reconnect when true
|
|
311
|
-
if (code === 1000 && reason === 'Disconnect from User') {
|
|
312
|
-
gracefulClose = true;
|
|
313
|
-
}
|
|
314
|
-
clearInterval(this.heartbeatInterval);
|
|
315
|
-
this.betterWs.removeAllListeners();
|
|
316
|
-
/**
|
|
317
|
-
* @event DiscordConnector#disconnect
|
|
318
|
-
* @type {Object}
|
|
319
|
-
* @property {Number} code - websocket disconnect code
|
|
320
|
-
* @private
|
|
321
|
-
*/
|
|
322
|
-
this.emit('disconnect', code, reason, forceIdentify, gracefulClose);
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
/**
|
|
326
|
-
* Send a status update payload to discord
|
|
327
|
-
* @param {Presence} data - presence data to send
|
|
328
|
-
* @protected
|
|
329
|
-
*/
|
|
330
|
-
statusUpdate(data = {}) {
|
|
331
|
-
return this.betterWs.sendMessage({op: OP.STATUS_UPDATE, d: this._checkPresenceData(data)});
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
/**
|
|
335
|
-
* Send a voice state update payload to discord
|
|
336
|
-
* @param {VoiceStateUpdate} data - voice state update data to send
|
|
337
|
-
* @returns {Promise.<void>}
|
|
338
|
-
* @protected
|
|
339
|
-
*/
|
|
340
|
-
voiceStateUpdate(data) {
|
|
341
|
-
if (!data) {
|
|
342
|
-
return Promise.resolve();
|
|
343
|
-
}
|
|
344
|
-
return this.betterWs.sendMessage({op: OP.VOICE_STATE_UPDATE, d: this._checkVoiceStateUpdateData(data)});
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
/**
|
|
348
|
-
* Send a request guild members payload to discord
|
|
349
|
-
* @param {RequestGuildMembers} data - data to send
|
|
350
|
-
* @returns {Promise.<void>}
|
|
351
|
-
* @protected
|
|
352
|
-
*/
|
|
353
|
-
requestGuildMembers(data = {}) {
|
|
354
|
-
return this.betterWs.sendMessage({op: OP.REQUEST_GUILD_MEMBERS, d: this._checkRequestGuildMembersData(data)});
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
/**
|
|
358
|
-
* Checks the presence data and fills in missing elements
|
|
359
|
-
* @param {Object} data - data to send
|
|
360
|
-
* @returns {Object} data after it's fixed/checked
|
|
361
|
-
* @private
|
|
362
|
-
*/
|
|
363
|
-
_checkPresenceData(data) {
|
|
364
|
-
data.status = data.status || 'online';
|
|
365
|
-
data.game = data.game || null;
|
|
366
|
-
if (data.game && !data.game.type) {
|
|
367
|
-
data.game.type = data.game.url ? 1 : 0;
|
|
368
|
-
}
|
|
369
|
-
if (data.game && !data.game.name) {
|
|
370
|
-
data.game = null;
|
|
371
|
-
}
|
|
372
|
-
data.afk = data.afk || false;
|
|
373
|
-
data.since = data.since || false;
|
|
374
|
-
return data;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
/**
|
|
378
|
-
* Checks the voice state update data and fills in missing elements
|
|
379
|
-
* @param {Object} data - data to send
|
|
380
|
-
* @returns {Object} data after it's fixed/checked
|
|
381
|
-
* @private
|
|
382
|
-
*/
|
|
383
|
-
_checkVoiceStateUpdateData(data) {
|
|
384
|
-
data.channel_id = data.channel_id || null;
|
|
385
|
-
data.self_mute = data.self_mute || false;
|
|
386
|
-
data.self_deaf = data.self_deaf || false;
|
|
387
|
-
return data;
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
/**
|
|
391
|
-
* Checks the request guild members data and fills in missing elements
|
|
392
|
-
* @param {Object} data - data to send
|
|
393
|
-
* @returns {Object} data after it's fixed/checked
|
|
394
|
-
* @private
|
|
395
|
-
*/
|
|
396
|
-
_checkRequestGuildMembersData(data) {
|
|
397
|
-
data.query = data.query || '';
|
|
398
|
-
data.limit = data.limit || 0;
|
|
399
|
-
return data;
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
module.exports = DiscordConnector;
|