cloudstorm 0.1.4 → 0.3.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/src/Shard.js DELETED
@@ -1,174 +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 DiscordConnector = require('./connector/DiscordConnector');
9
- const OP_CODES = require('./Constants').GATEWAY_OP_CODES;
10
-
11
- /**
12
- * @typedef Shard
13
- * @description Shard class, which provides a wrapper around the DiscordConnector with metadata like the id of the shard
14
- *
15
- * This class is automatically instantiated by the library and is documented for reference
16
- * @property {Number} id - Id of the shard
17
- * @property {Client} client - main class used for forwarding events
18
- * @property {Boolean} forceIdentify - whether the connector should not try to resume and re-identify
19
- * @property {Boolean} ready - if this shard has successfully connected and identified with the gateway
20
- * @property {DiscordConnector} connector - connector used for connecting to discord
21
- */
22
- class Shard extends EventEmitter {
23
- /**
24
- * Create a new Shard
25
- * @param {Number} id - Id of the shard
26
- * @param {Client} client - main class used for forwarding events
27
- * @private
28
- */
29
- constructor(id, client) {
30
- super();
31
- this.id = id;
32
- this.client = client;
33
- this.forceIdentify = false;
34
- this.ready = false;
35
- this.connector = new DiscordConnector(id, client);
36
- this.connector.on('event', (event) => {
37
- event.shard_id = this.id;
38
- /**
39
- * @event Client#event
40
- * @type {Object}
41
- * @description Emitted when an event is received from discord, this event is a raw discord event.
42
- *
43
- * Packets that are guaranteed to be emitted to you are OP 0 (DISPATCH) and OP 4 (VOICE STATE UPDATE)
44
- *
45
- * **Other OPs may be catched by the library and used for internal processing, so you should not count on them**
46
- * @example
47
- * //Connect bot to discord and listen for received events
48
- * let bot = new CloudStorm(token)
49
- * await bot.connect()
50
- * bot.on('event', (event) => {
51
- * // Do something with the event
52
- * });
53
- */
54
- this.client.emit('event', event);
55
- switch (event.op) {
56
- case OP_CODES.DISPATCH:
57
- /**
58
- * @event Client#dispatch
59
- * @type {Object}
60
- * @description Emitted when a OP **dispatch** event is received by the bot
61
- *
62
- * Dispatch events are usual events that happen on discord like message_create, presence_update, etc..
63
- */
64
- this.client.emit('dispatch', event);
65
- break;
66
- case OP_CODES.VOICE_STATE_UPDATE:
67
- /**
68
- * @event Client#voiceStateUpdate
69
- * @type {Object}
70
- * @description Emitted when a OP **voice state update** event is received by the bot
71
- * @property {String} guild_id - id of the guild
72
- * @property {String|null} channel_id - id of the channel that was joined or null if the user is leaving the channel
73
- * @property {Boolean} self_mute - if the user is muted
74
- * @property {Boolean} self_deaf - if the user is deafened
75
- */
76
- this.client.emit('voiceStateUpdate', event);
77
- break;
78
- default:
79
- break;
80
- }
81
- });
82
- this.connector.on('disconnect', (...args) => {
83
- this.ready = false;
84
- /**
85
- * @event Shard#disconnect
86
- * @type {void}
87
- * @description Emitted when the shard get's disconnected from the gateway
88
- * @private
89
- */
90
- this.emit('disconnect', ...args);
91
- });
92
- this.connector.on('error', (err) => {
93
- /**
94
- * @event Shard#error
95
- * @type {Error}
96
- * @description Emitted when the shard (or internal components of it) error
97
- * @private
98
- */
99
- this.emit('error', err);
100
- });
101
- this.connector.on('ready', (resume) => {
102
- /**
103
- * @event Shard#ready
104
- * @type {Boolean}
105
- * @description Emitted when the shard turns ready, has a boolean that can be used to check if the shard got a full ready or just a resume
106
- * @private
107
- */
108
- this.emit('ready', resume);
109
- });
110
- this.connector.on('queueIdentify', () => {
111
- /**
112
- * @event Shard#queueIdentify
113
- * @type {Number}
114
- * @description Emitted when the underlying connector received an op9 code to tell the shard manager that the shard needs to be queued for re-identifying
115
- * @private
116
- */
117
- this.emit('queueIdentify', this.id);
118
- });
119
- }
120
-
121
- /**
122
- * Create a new Connection to discord
123
- * @protected
124
- */
125
- connect() {
126
- if (this.forceIdentify) {
127
- this.connector.forceIdentify = true;
128
- this.forceIdentify = false;
129
- }
130
- this.connector.connect();
131
- }
132
-
133
- /**
134
- * Close the current connection
135
- * @returns {Promise.<void>}
136
- * @protected
137
- */
138
- disconnect() {
139
- return this.connector.disconnect();
140
- }
141
-
142
- /**
143
- * Send a status update payload to discord
144
- * @param {Presence} data - data to send
145
- * @returns {Promise.<void>}
146
- * @protected
147
- */
148
- statusUpdate(data) {
149
- return this.connector.statusUpdate(data);
150
- }
151
-
152
- /**
153
- * Send a voice state update payload to discord
154
- * @param {VoiceStateUpdate} data - data to send
155
- * @returns {Promise.<void>}
156
- * @protected
157
- */
158
- voiceStateUpdate(data) {
159
- return this.connector.voiceStateUpdate(data);
160
- }
161
-
162
- /**
163
- * Send a request guild members payload to discord
164
- * @param {RequestGuildMembers} data - data to send
165
- * @returns {Promise.<void>}
166
- * @protected
167
- */
168
- requestGuildMembers(data) {
169
- return this.connector.requestGuildMembers(data);
170
- }
171
-
172
- }
173
-
174
- module.exports = Shard;
@@ -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;