discord-sb.js 1.2.3 → 1.3.1
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/package.json +13 -12
- package/src/client/BaseClient.js +24 -0
- package/src/client/Client.js +11 -4
- package/src/client/WebhookClient.js +1 -1
- package/src/client/actions/Action.js +39 -22
- package/src/client/actions/InviteCreate.js +1 -1
- package/src/client/actions/InviteDelete.js +1 -1
- package/src/client/actions/MessageCreate.js +6 -6
- package/src/client/actions/MessageDelete.js +3 -1
- package/src/client/actions/MessageDeleteBulk.js +6 -9
- package/src/client/actions/MessageReactionAdd.js +12 -9
- package/src/client/actions/MessageReactionRemove.js +3 -14
- package/src/client/actions/MessageReactionRemoveAll.js +8 -5
- package/src/client/actions/MessageReactionRemoveEmoji.js +3 -1
- package/src/client/actions/MessageUpdate.js +3 -1
- package/src/client/actions/PresenceUpdate.js +8 -3
- package/src/client/actions/ThreadListSync.js +6 -5
- package/src/client/actions/ThreadMembersUpdate.js +10 -6
- package/src/client/actions/TypingStart.js +3 -1
- package/src/client/actions/VoiceStateUpdate.js +20 -7
- package/src/client/voice/ClientVoiceManager.js +18 -7
- package/src/client/voice/StreamEventRouter.js +60 -0
- package/src/client/voice/VoiceConnection.js +91 -167
- package/src/client/voice/networking/VoiceUDPClient.js +25 -11
- package/src/client/voice/networking/VoiceWebSocket.js +87 -26
- package/src/client/websocket/DispatchTable.js +7 -0
- package/src/client/websocket/GatewaySendScheduler.js +107 -0
- package/src/client/websocket/WebSocketManager.js +26 -22
- package/src/client/websocket/WebSocketShard.js +161 -51
- package/src/client/websocket/handlers/GUILD_CREATE.js +4 -5
- package/src/client/websocket/handlers/GUILD_MEMBERS_CHUNK.js +8 -2
- package/src/client/websocket/handlers/READY.js +72 -59
- package/src/client/websocket/handlers/USER_REQUIRED_ACTION_UPDATE.js +13 -9
- package/src/client/websocket/handlers/VOICE_SERVER_UPDATE.js +7 -1
- package/src/managers/GuildMemberManager.js +8 -3
- package/src/managers/MessageManager.js +27 -23
- package/src/managers/QuestManager.js +7 -9
- package/src/rest/APIRequest.js +40 -43
- package/src/rest/APIRouter.js +1 -1
- package/src/rest/RESTManager.js +69 -2
- package/src/rest/RateLimitCoordinator.js +156 -0
- package/src/rest/RequestHandler.js +162 -91
- package/src/structures/DMChannel.js +5 -2
- package/src/structures/GroupDMChannel.js +5 -2
- package/src/structures/interfaces/Collector.js +2 -1
- package/src/util/Constants.js +41 -2
- package/src/util/FastQueue.js +93 -0
- package/src/util/ListenerUtil.js +12 -0
- package/src/util/Options.js +2 -2
- package/src/util/RemoteAuth.js +9 -1
- package/typings/index.d.ts +64 -41
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const VoiceConnection = require('./VoiceConnection');
|
|
4
4
|
const { Error } = require('../../errors');
|
|
5
5
|
const { Events } = require('../../util/Constants');
|
|
6
|
+
const { hasListener } = require('../../util/ListenerUtil');
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Manages voice connections for the client
|
|
@@ -42,8 +43,7 @@ class ClientVoiceManager {
|
|
|
42
43
|
|
|
43
44
|
onVoiceServer(payload) {
|
|
44
45
|
const { guild_id, channel_id, token, endpoint } = payload;
|
|
45
|
-
this.
|
|
46
|
-
'debug',
|
|
46
|
+
this._debug(
|
|
47
47
|
`[VOICE] voiceServer ${channel_id ? 'channel' : 'guild'}: ${
|
|
48
48
|
channel_id || guild_id
|
|
49
49
|
} token: ${token} endpoint: ${endpoint}`,
|
|
@@ -68,7 +68,7 @@ class ClientVoiceManager {
|
|
|
68
68
|
}
|
|
69
69
|
// Main lib
|
|
70
70
|
const connection = this.connection;
|
|
71
|
-
this.
|
|
71
|
+
this._debug(`[VOICE] connection? ${!!connection}, ${guild_id} ${session_id} ${channel_id}`);
|
|
72
72
|
if (!connection) return;
|
|
73
73
|
if (!channel_id) {
|
|
74
74
|
connection._disconnect();
|
|
@@ -80,7 +80,7 @@ class ClientVoiceManager {
|
|
|
80
80
|
connection.channel = channel;
|
|
81
81
|
connection.setSessionId(session_id);
|
|
82
82
|
} else {
|
|
83
|
-
this.
|
|
83
|
+
this._debug(`[VOICE] disconnecting from guild ${guild_id} as channel ${channel_id} is uncached`);
|
|
84
84
|
connection.disconnect();
|
|
85
85
|
}
|
|
86
86
|
}
|
|
@@ -117,9 +117,14 @@ class ClientVoiceManager {
|
|
|
117
117
|
} else {
|
|
118
118
|
connection = new VoiceConnection(this, channel);
|
|
119
119
|
if (config?.videoCodec) connection.setVideoCodec(config.videoCodec);
|
|
120
|
-
|
|
121
|
-
this.client
|
|
122
|
-
|
|
120
|
+
const forwardDebug = msg => {
|
|
121
|
+
if (hasListener(this.client, Events.DEBUG)) {
|
|
122
|
+
this.client.emit(Events.DEBUG, `[VOICE (${channel.guild?.id || channel.id}:${connection.status})]: ${msg}`);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
forwardDebug.__voiceForwarder = true;
|
|
126
|
+
connection.on('debug', forwardDebug);
|
|
127
|
+
connection._voiceDebugForwarder = forwardDebug;
|
|
123
128
|
connection.authenticate({
|
|
124
129
|
self_mute: Boolean(config.selfMute),
|
|
125
130
|
self_deaf: Boolean(config.selfDeaf),
|
|
@@ -146,6 +151,12 @@ class ClientVoiceManager {
|
|
|
146
151
|
});
|
|
147
152
|
});
|
|
148
153
|
}
|
|
154
|
+
|
|
155
|
+
_debug(message) {
|
|
156
|
+
if (hasListener(this.client, Events.DEBUG)) {
|
|
157
|
+
this.client.emit(Events.DEBUG, message);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
149
160
|
}
|
|
150
161
|
|
|
151
162
|
module.exports = ClientVoiceManager;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { parseStreamKey } = require('./util/Function');
|
|
4
|
+
|
|
5
|
+
class StreamEventRouter {
|
|
6
|
+
constructor(connection) {
|
|
7
|
+
this.connection = connection;
|
|
8
|
+
this._onRaw = this._onRaw.bind(this);
|
|
9
|
+
this._attached = false;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
attach() {
|
|
13
|
+
if (this._attached) return;
|
|
14
|
+
this.connection.channel.client.on('raw', this._onRaw);
|
|
15
|
+
this._attached = true;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
detach() {
|
|
19
|
+
if (!this._attached) return;
|
|
20
|
+
this.connection.channel.client.removeListener('raw', this._onRaw);
|
|
21
|
+
this._attached = false;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
_onRaw(packet) {
|
|
25
|
+
if (typeof packet !== 'object' || !packet.t || !packet.d?.stream_key) return;
|
|
26
|
+
const { t: event, d: data } = packet;
|
|
27
|
+
const streamKey = parseStreamKey(data.stream_key);
|
|
28
|
+
if (this.connection.channel.id !== streamKey.channelId) return;
|
|
29
|
+
|
|
30
|
+
if (streamKey.userId === this.connection.channel.client.user.id && this.connection.streamConnection) {
|
|
31
|
+
this._applyEvent(this.connection.streamConnection, event, data);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const watched = this.connection.streamWatchConnection.get(streamKey.userId);
|
|
35
|
+
if (watched) {
|
|
36
|
+
this._applyEvent(watched, event, data, true);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
_applyEvent(connection, event, data, isWatcher = false) {
|
|
41
|
+
switch (event) {
|
|
42
|
+
case 'STREAM_CREATE':
|
|
43
|
+
connection.setSessionId(this.connection.authentication.sessionId);
|
|
44
|
+
connection.serverId = data.rtc_server_id;
|
|
45
|
+
break;
|
|
46
|
+
case 'STREAM_SERVER_UPDATE':
|
|
47
|
+
connection.setTokenAndEndpoint(data.token, data.endpoint);
|
|
48
|
+
break;
|
|
49
|
+
case 'STREAM_DELETE':
|
|
50
|
+
connection.disconnect();
|
|
51
|
+
if (isWatcher) connection.receiver.packets.destroyAllStream();
|
|
52
|
+
break;
|
|
53
|
+
case 'STREAM_UPDATE':
|
|
54
|
+
connection.update(data);
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
module.exports = StreamEventRouter;
|
|
@@ -4,15 +4,16 @@ const EventEmitter = require('events');
|
|
|
4
4
|
const { getCiphers } = require('node:crypto');
|
|
5
5
|
const { setTimeout } = require('node:timers');
|
|
6
6
|
const { Collection } = require('@discordjs/collection');
|
|
7
|
+
const StreamEventRouter = require('./StreamEventRouter');
|
|
7
8
|
const VoiceUDP = require('./networking/VoiceUDPClient');
|
|
8
9
|
const VoiceWebSocket = require('./networking/VoiceWebSocket');
|
|
9
10
|
const MediaPlayer = require('./player/MediaPlayer');
|
|
10
11
|
const VoiceReceiver = require('./receiver/Receiver');
|
|
11
|
-
const { parseStreamKey } = require('./util/Function');
|
|
12
12
|
const PlayInterface = require('./util/PlayInterface');
|
|
13
13
|
const Silence = require('./util/Silence');
|
|
14
14
|
const { Error } = require('../../errors');
|
|
15
15
|
const { Opcodes, VoiceOpcodes, VoiceStatus, Events } = require('../../util/Constants');
|
|
16
|
+
const { hasListener } = require('../../util/ListenerUtil');
|
|
16
17
|
const Speaking = require('../../util/Speaking');
|
|
17
18
|
const Util = require('../../util/Util');
|
|
18
19
|
|
|
@@ -85,6 +86,7 @@ class VoiceConnection extends EventEmitter {
|
|
|
85
86
|
* @private
|
|
86
87
|
*/
|
|
87
88
|
this.authentication = {};
|
|
89
|
+
this._voiceSequence = -1;
|
|
88
90
|
|
|
89
91
|
/**
|
|
90
92
|
* The audio player for this voice connection
|
|
@@ -98,7 +100,7 @@ class VoiceConnection extends EventEmitter {
|
|
|
98
100
|
* @event VoiceConnection#debug
|
|
99
101
|
* @param {string} message The debug message
|
|
100
102
|
*/
|
|
101
|
-
this.
|
|
103
|
+
this._debug(`media player - ${m}`);
|
|
102
104
|
});
|
|
103
105
|
|
|
104
106
|
this.player.on('error', e => {
|
|
@@ -166,6 +168,7 @@ class VoiceConnection extends EventEmitter {
|
|
|
166
168
|
* @type {Collection<Snowflake, StreamConnectionReadonly>}
|
|
167
169
|
*/
|
|
168
170
|
this.streamWatchConnection = new Collection();
|
|
171
|
+
this._streamEventRouter = new StreamEventRouter(this);
|
|
169
172
|
}
|
|
170
173
|
|
|
171
174
|
/**
|
|
@@ -195,6 +198,28 @@ class VoiceConnection extends EventEmitter {
|
|
|
195
198
|
return this.player.videoDispatcher;
|
|
196
199
|
}
|
|
197
200
|
|
|
201
|
+
hasDebugListeners() {
|
|
202
|
+
const forwardingListeners = this._voiceDebugForwarder ? 1 : 0;
|
|
203
|
+
const hasClientDebugListener = hasListener(this.client, Events.DEBUG);
|
|
204
|
+
return this.listenerCount('debug') > forwardingListeners || hasClientDebugListener;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
_debug(message) {
|
|
208
|
+
if (!this.hasDebugListeners()) return;
|
|
209
|
+
this.emit('debug', message);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
_debugLazy(factory) {
|
|
213
|
+
if (!this.hasDebugListeners()) return;
|
|
214
|
+
this.emit('debug', factory());
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
sendGatewayPacket(packet) {
|
|
218
|
+
const shard = this.channel?.shard ?? this.channel?.client?.ws?.shards?.first?.();
|
|
219
|
+
if (shard) return shard.send(packet);
|
|
220
|
+
return this.channel.client.ws.broadcast(packet);
|
|
221
|
+
}
|
|
222
|
+
|
|
198
223
|
/**
|
|
199
224
|
* Sets whether the voice connection should display as "speaking", "soundshare" or "none".
|
|
200
225
|
* @param {BitFieldResolvable} value The new speaking state
|
|
@@ -213,7 +238,7 @@ class VoiceConnection extends EventEmitter {
|
|
|
213
238
|
},
|
|
214
239
|
})
|
|
215
240
|
.catch(e => {
|
|
216
|
-
this.
|
|
241
|
+
this._debug(e);
|
|
217
242
|
});
|
|
218
243
|
}
|
|
219
244
|
|
|
@@ -239,7 +264,7 @@ class VoiceConnection extends EventEmitter {
|
|
|
239
264
|
if (!value) {
|
|
240
265
|
this.sockets.ws
|
|
241
266
|
.sendPacket({
|
|
242
|
-
op: VoiceOpcodes.
|
|
267
|
+
op: VoiceOpcodes.VIDEO,
|
|
243
268
|
d: {
|
|
244
269
|
audio_ssrc: this.authentication.ssrc,
|
|
245
270
|
video_ssrc: 0,
|
|
@@ -248,12 +273,12 @@ class VoiceConnection extends EventEmitter {
|
|
|
248
273
|
},
|
|
249
274
|
})
|
|
250
275
|
.catch(e => {
|
|
251
|
-
this.
|
|
276
|
+
this._debug(e);
|
|
252
277
|
});
|
|
253
278
|
} else {
|
|
254
279
|
this.sockets.ws
|
|
255
280
|
.sendPacket({
|
|
256
|
-
op: VoiceOpcodes.
|
|
281
|
+
op: VoiceOpcodes.VIDEO,
|
|
257
282
|
d: {
|
|
258
283
|
audio_ssrc: this.authentication.ssrc,
|
|
259
284
|
video_ssrc: this.authentication.ssrc + 1,
|
|
@@ -278,7 +303,7 @@ class VoiceConnection extends EventEmitter {
|
|
|
278
303
|
},
|
|
279
304
|
})
|
|
280
305
|
.catch(e => {
|
|
281
|
-
this.
|
|
306
|
+
this._debug(e);
|
|
282
307
|
});
|
|
283
308
|
}
|
|
284
309
|
}
|
|
@@ -310,9 +335,9 @@ class VoiceConnection extends EventEmitter {
|
|
|
310
335
|
options,
|
|
311
336
|
);
|
|
312
337
|
|
|
313
|
-
this.
|
|
338
|
+
this._debugLazy(() => `Sending voice state update: ${JSON.stringify(options)}`);
|
|
314
339
|
|
|
315
|
-
return this.
|
|
340
|
+
return this.sendGatewayPacket({
|
|
316
341
|
op: Opcodes.VOICE_STATE_UPDATE,
|
|
317
342
|
d: options,
|
|
318
343
|
});
|
|
@@ -326,7 +351,7 @@ class VoiceConnection extends EventEmitter {
|
|
|
326
351
|
* @private
|
|
327
352
|
*/
|
|
328
353
|
setTokenAndEndpoint(token, endpoint) {
|
|
329
|
-
this.
|
|
354
|
+
this._debug(`Token "${token}" and endpoint "${endpoint}"`);
|
|
330
355
|
if (!endpoint) {
|
|
331
356
|
// Signifies awaiting endpoint stage
|
|
332
357
|
return;
|
|
@@ -338,7 +363,7 @@ class VoiceConnection extends EventEmitter {
|
|
|
338
363
|
}
|
|
339
364
|
|
|
340
365
|
endpoint = endpoint.match(/([^:]*)/)[0];
|
|
341
|
-
this.
|
|
366
|
+
this._debug(`Endpoint resolved as ${endpoint}`);
|
|
342
367
|
|
|
343
368
|
if (!endpoint) {
|
|
344
369
|
this.authenticateFailed('VOICE_INVALID_ENDPOINT');
|
|
@@ -360,7 +385,7 @@ class VoiceConnection extends EventEmitter {
|
|
|
360
385
|
* @private
|
|
361
386
|
*/
|
|
362
387
|
setSessionId(sessionId) {
|
|
363
|
-
this.
|
|
388
|
+
this._debug(`Setting sessionId ${sessionId} (stored as "${this.authentication.sessionId}")`);
|
|
364
389
|
if (!sessionId) {
|
|
365
390
|
this.authenticateFailed('VOICE_SESSION_ABSENT');
|
|
366
391
|
return;
|
|
@@ -386,7 +411,7 @@ class VoiceConnection extends EventEmitter {
|
|
|
386
411
|
*/
|
|
387
412
|
checkAuthenticated() {
|
|
388
413
|
const { token, endpoint, sessionId } = this.authentication;
|
|
389
|
-
this.
|
|
414
|
+
this._debug(`Authenticated with sessionId ${sessionId}`);
|
|
390
415
|
if (token && endpoint && sessionId) {
|
|
391
416
|
this.status = VoiceStatus.CONNECTING;
|
|
392
417
|
/**
|
|
@@ -405,7 +430,7 @@ class VoiceConnection extends EventEmitter {
|
|
|
405
430
|
*/
|
|
406
431
|
authenticateFailed(reason) {
|
|
407
432
|
clearTimeout(this.connectTimeout);
|
|
408
|
-
this.
|
|
433
|
+
this._debug(`Authenticate failed - ${reason}`);
|
|
409
434
|
if (this.status === VoiceStatus.AUTHENTICATING) {
|
|
410
435
|
/**
|
|
411
436
|
* Emitted when we fail to initiate a voice connection.
|
|
@@ -455,7 +480,7 @@ class VoiceConnection extends EventEmitter {
|
|
|
455
480
|
this.authentication.endpoint = endpoint;
|
|
456
481
|
this.speaking = new Speaking().freeze();
|
|
457
482
|
this.status = VoiceStatus.RECONNECTING;
|
|
458
|
-
this.
|
|
483
|
+
this._debug(`Reconnecting to ${endpoint}`);
|
|
459
484
|
/**
|
|
460
485
|
* Emitted when the voice connection is reconnecting (typically after a region change).
|
|
461
486
|
* @event VoiceConnection#reconnecting
|
|
@@ -469,7 +494,7 @@ class VoiceConnection extends EventEmitter {
|
|
|
469
494
|
*/
|
|
470
495
|
disconnect() {
|
|
471
496
|
this.emit('closing');
|
|
472
|
-
this.
|
|
497
|
+
this._debug('disconnect() triggered');
|
|
473
498
|
clearTimeout(this.connectTimeout);
|
|
474
499
|
const conn = this.voiceManager.connection;
|
|
475
500
|
if (conn === this) this.voiceManager.connection = null;
|
|
@@ -502,7 +527,8 @@ class VoiceConnection extends EventEmitter {
|
|
|
502
527
|
this.speaking = new Speaking().freeze();
|
|
503
528
|
const { ws, udp } = this.sockets;
|
|
504
529
|
|
|
505
|
-
this.
|
|
530
|
+
this._debug('Connection clean up');
|
|
531
|
+
this._streamEventRouter.detach();
|
|
506
532
|
|
|
507
533
|
if (ws) {
|
|
508
534
|
ws.removeAllListeners('error');
|
|
@@ -523,7 +549,7 @@ class VoiceConnection extends EventEmitter {
|
|
|
523
549
|
* @private
|
|
524
550
|
*/
|
|
525
551
|
connect() {
|
|
526
|
-
this.
|
|
552
|
+
this._debug('Connect triggered');
|
|
527
553
|
if (this.status !== VoiceStatus.RECONNECTING) {
|
|
528
554
|
if (this.sockets.ws) throw new Error('WS_CONNECTION_EXISTS');
|
|
529
555
|
if (this.sockets.udp) throw new Error('UDP_CONNECTION_EXISTS');
|
|
@@ -537,11 +563,12 @@ class VoiceConnection extends EventEmitter {
|
|
|
537
563
|
|
|
538
564
|
const { ws, udp } = this.sockets;
|
|
539
565
|
|
|
540
|
-
ws.on('debug', msg => this.
|
|
541
|
-
udp.on('debug', msg => this.
|
|
566
|
+
ws.on('debug', msg => this._debug(msg));
|
|
567
|
+
udp.on('debug', msg => this._debug(msg));
|
|
542
568
|
ws.on('error', err => this.emit('error', err));
|
|
543
569
|
udp.on('error', err => this.emit('error', err));
|
|
544
570
|
ws.on('ready', this.onReady.bind(this));
|
|
571
|
+
ws.on('resumed', this.onResumed.bind(this));
|
|
545
572
|
ws.on('sessionDescription', this.onSessionDescription.bind(this));
|
|
546
573
|
ws.on('startSpeaking', this.onStartSpeaking.bind(this));
|
|
547
574
|
ws.on('startStreaming', this.onStartStreaming.bind(this));
|
|
@@ -559,7 +586,7 @@ class VoiceConnection extends EventEmitter {
|
|
|
559
586
|
for (let mode of data.modes) {
|
|
560
587
|
if (SUPPORTED_MODES.includes(mode)) {
|
|
561
588
|
this.authentication.mode = mode;
|
|
562
|
-
this.
|
|
589
|
+
this._debug(`Selecting the ${mode} mode`);
|
|
563
590
|
break;
|
|
564
591
|
}
|
|
565
592
|
}
|
|
@@ -576,7 +603,7 @@ class VoiceConnection extends EventEmitter {
|
|
|
576
603
|
this.status = VoiceStatus.CONNECTED;
|
|
577
604
|
const ready = () => {
|
|
578
605
|
clearTimeout(this.connectTimeout);
|
|
579
|
-
this.
|
|
606
|
+
this._debugLazy(() => `Ready with authentication details: ${JSON.stringify(this.authentication)}`);
|
|
580
607
|
/**
|
|
581
608
|
* Emitted once the connection is ready, when a promise to join a voice channel resolves,
|
|
582
609
|
* the connection will already be ready.
|
|
@@ -593,6 +620,13 @@ class VoiceConnection extends EventEmitter {
|
|
|
593
620
|
}
|
|
594
621
|
}
|
|
595
622
|
|
|
623
|
+
onResumed() {
|
|
624
|
+
this.status = VoiceStatus.CONNECTED;
|
|
625
|
+
clearTimeout(this.connectTimeout);
|
|
626
|
+
this._debug('[WS] Voice session resumed');
|
|
627
|
+
this.emit('resumed');
|
|
628
|
+
}
|
|
629
|
+
|
|
596
630
|
onStartSpeaking({ user_id, ssrc, speaking }) {
|
|
597
631
|
this.ssrcMap.set(+ssrc, {
|
|
598
632
|
...(this.ssrcMap.get(+ssrc) || {}),
|
|
@@ -680,77 +714,22 @@ class VoiceConnection extends EventEmitter {
|
|
|
680
714
|
} else {
|
|
681
715
|
const connection = (this.streamConnection = new StreamConnection(this.voiceManager, this.channel, this));
|
|
682
716
|
connection.setVideoCodec(this.videoCodec); // Sync :?
|
|
683
|
-
|
|
684
|
-
if (!this.eventHook) {
|
|
685
|
-
this.eventHook = true; // Dont listen this event two times :/
|
|
686
|
-
this.channel.client.on('raw', packet => {
|
|
687
|
-
if (typeof packet !== 'object' || !packet.t || !packet.d || !packet.d?.stream_key) {
|
|
688
|
-
return;
|
|
689
|
-
}
|
|
690
|
-
const { t: event, d: data } = packet;
|
|
691
|
-
const StreamKey = parseStreamKey(data.stream_key);
|
|
692
|
-
if (
|
|
693
|
-
StreamKey.userId === this.channel.client.user.id &&
|
|
694
|
-
this.channel.id == StreamKey.channelId &&
|
|
695
|
-
this.streamConnection
|
|
696
|
-
) {
|
|
697
|
-
// Current user stream
|
|
698
|
-
switch (event) {
|
|
699
|
-
case 'STREAM_CREATE': {
|
|
700
|
-
this.streamConnection.setSessionId(this.authentication.sessionId);
|
|
701
|
-
this.streamConnection.serverId = data.rtc_server_id;
|
|
702
|
-
break;
|
|
703
|
-
}
|
|
704
|
-
case 'STREAM_SERVER_UPDATE': {
|
|
705
|
-
this.streamConnection.setTokenAndEndpoint(data.token, data.endpoint);
|
|
706
|
-
break;
|
|
707
|
-
}
|
|
708
|
-
case 'STREAM_DELETE': {
|
|
709
|
-
this.streamConnection.disconnect();
|
|
710
|
-
break;
|
|
711
|
-
}
|
|
712
|
-
case 'STREAM_UPDATE': {
|
|
713
|
-
this.streamConnection.update(data);
|
|
714
|
-
break;
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
if (this.streamWatchConnection.has(StreamKey.userId) && this.channel.id == StreamKey.channelId) {
|
|
719
|
-
const streamConnection = this.streamWatchConnection.get(StreamKey.userId);
|
|
720
|
-
// Watch user stream
|
|
721
|
-
switch (event) {
|
|
722
|
-
case 'STREAM_CREATE': {
|
|
723
|
-
streamConnection.setSessionId(this.authentication.sessionId);
|
|
724
|
-
streamConnection.serverId = data.rtc_server_id;
|
|
725
|
-
break;
|
|
726
|
-
}
|
|
727
|
-
case 'STREAM_SERVER_UPDATE': {
|
|
728
|
-
streamConnection.setTokenAndEndpoint(data.token, data.endpoint);
|
|
729
|
-
break;
|
|
730
|
-
}
|
|
731
|
-
case 'STREAM_DELETE': {
|
|
732
|
-
streamConnection.disconnect();
|
|
733
|
-
streamConnection.receiver.packets.destroyAllStream();
|
|
734
|
-
break;
|
|
735
|
-
}
|
|
736
|
-
case 'STREAM_UPDATE': {
|
|
737
|
-
streamConnection.update(data);
|
|
738
|
-
break;
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
});
|
|
743
|
-
}
|
|
717
|
+
this._streamEventRouter.attach();
|
|
744
718
|
|
|
745
719
|
connection.sendSignalScreenshare();
|
|
746
720
|
connection.sendScreenshareState(true);
|
|
747
721
|
|
|
748
|
-
|
|
749
|
-
this.channel.client.
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
722
|
+
const forwardStreamDebug = msg => {
|
|
723
|
+
if (hasListener(this.channel.client, Events.DEBUG)) {
|
|
724
|
+
this.channel.client.emit(
|
|
725
|
+
Events.DEBUG,
|
|
726
|
+
`[VOICE STREAM (${this.channel.guild?.id || this.channel.id}:${connection.status})]: ${msg}`,
|
|
727
|
+
);
|
|
728
|
+
}
|
|
729
|
+
};
|
|
730
|
+
forwardStreamDebug.__voiceForwarder = true;
|
|
731
|
+
connection.on('debug', forwardStreamDebug);
|
|
732
|
+
connection._voiceDebugForwarder = forwardStreamDebug;
|
|
754
733
|
connection.once('failed', reason => {
|
|
755
734
|
this.streamConnection = null;
|
|
756
735
|
reject(reason);
|
|
@@ -794,78 +773,23 @@ class VoiceConnection extends EventEmitter {
|
|
|
794
773
|
const connection = new StreamConnectionReadonly(this.voiceManager, this.channel, this, userId);
|
|
795
774
|
this.streamWatchConnection.set(userId, connection);
|
|
796
775
|
connection.setVideoCodec(this.videoCodec);
|
|
797
|
-
|
|
798
|
-
if (!this.eventHook) {
|
|
799
|
-
this.eventHook = true; // Dont listen this event two times :/
|
|
800
|
-
this.channel.client.on('raw', packet => {
|
|
801
|
-
if (typeof packet !== 'object' || !packet.t || !packet.d || !packet.d?.stream_key) {
|
|
802
|
-
return;
|
|
803
|
-
}
|
|
804
|
-
const { t: event, d: data } = packet;
|
|
805
|
-
const StreamKey = parseStreamKey(data.stream_key);
|
|
806
|
-
if (
|
|
807
|
-
StreamKey.userId === this.channel.client.user.id &&
|
|
808
|
-
this.channel.id == StreamKey.channelId &&
|
|
809
|
-
this.streamConnection
|
|
810
|
-
) {
|
|
811
|
-
// Current user stream
|
|
812
|
-
switch (event) {
|
|
813
|
-
case 'STREAM_CREATE': {
|
|
814
|
-
this.streamConnection.setSessionId(this.authentication.sessionId);
|
|
815
|
-
this.streamConnection.serverId = data.rtc_server_id;
|
|
816
|
-
break;
|
|
817
|
-
}
|
|
818
|
-
case 'STREAM_SERVER_UPDATE': {
|
|
819
|
-
this.streamConnection.setTokenAndEndpoint(data.token, data.endpoint);
|
|
820
|
-
break;
|
|
821
|
-
}
|
|
822
|
-
case 'STREAM_DELETE': {
|
|
823
|
-
this.streamConnection.disconnect();
|
|
824
|
-
break;
|
|
825
|
-
}
|
|
826
|
-
case 'STREAM_UPDATE': {
|
|
827
|
-
this.streamConnection.update(data);
|
|
828
|
-
break;
|
|
829
|
-
}
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
if (this.streamWatchConnection.has(StreamKey.userId) && this.channel.id == StreamKey.channelId) {
|
|
833
|
-
const streamConnection = this.streamWatchConnection.get(StreamKey.userId);
|
|
834
|
-
// Watch user stream
|
|
835
|
-
switch (event) {
|
|
836
|
-
case 'STREAM_CREATE': {
|
|
837
|
-
streamConnection.setSessionId(this.authentication.sessionId);
|
|
838
|
-
streamConnection.serverId = data.rtc_server_id;
|
|
839
|
-
break;
|
|
840
|
-
}
|
|
841
|
-
case 'STREAM_SERVER_UPDATE': {
|
|
842
|
-
streamConnection.setTokenAndEndpoint(data.token, data.endpoint);
|
|
843
|
-
break;
|
|
844
|
-
}
|
|
845
|
-
case 'STREAM_DELETE': {
|
|
846
|
-
streamConnection.disconnect();
|
|
847
|
-
streamConnection.receiver.packets.destroyAllStream();
|
|
848
|
-
break;
|
|
849
|
-
}
|
|
850
|
-
case 'STREAM_UPDATE': {
|
|
851
|
-
streamConnection.update(data);
|
|
852
|
-
break;
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
});
|
|
857
|
-
}
|
|
776
|
+
this._streamEventRouter.attach();
|
|
858
777
|
|
|
859
778
|
connection.sendSignalScreenshare();
|
|
860
779
|
|
|
861
|
-
|
|
862
|
-
this.channel.client.
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
780
|
+
const forwardStreamWatchDebug = msg => {
|
|
781
|
+
if (hasListener(this.channel.client, Events.DEBUG)) {
|
|
782
|
+
this.channel.client.emit(
|
|
783
|
+
Events.DEBUG,
|
|
784
|
+
`[VOICE STREAM WATCH (${userId}>${this.channel.guild?.id || this.channel.id}:${
|
|
785
|
+
connection.status
|
|
786
|
+
})]: ${msg}`,
|
|
787
|
+
);
|
|
788
|
+
}
|
|
789
|
+
};
|
|
790
|
+
forwardStreamWatchDebug.__voiceForwarder = true;
|
|
791
|
+
connection.on('debug', forwardStreamWatchDebug);
|
|
792
|
+
connection._voiceDebugForwarder = forwardStreamWatchDebug;
|
|
869
793
|
connection.once('failed', reason => {
|
|
870
794
|
this.streamWatchConnection.delete(userId);
|
|
871
795
|
reject(reason);
|
|
@@ -986,7 +910,7 @@ class StreamConnection extends VoiceConnection {
|
|
|
986
910
|
disconnect() {
|
|
987
911
|
if (this.#requestDisconnect) return;
|
|
988
912
|
this.emit('closing');
|
|
989
|
-
this.
|
|
913
|
+
this._debug('Stream: disconnect() triggered');
|
|
990
914
|
clearTimeout(this.connectTimeout);
|
|
991
915
|
if (this.voiceConnection.streamConnection === this) this.voiceConnection.streamConnection = null;
|
|
992
916
|
this.sendStopScreenshare();
|
|
@@ -1004,8 +928,8 @@ class StreamConnection extends VoiceConnection {
|
|
|
1004
928
|
channel_id: this.channel.id,
|
|
1005
929
|
preferred_region: null,
|
|
1006
930
|
};
|
|
1007
|
-
this.
|
|
1008
|
-
return this.
|
|
931
|
+
this._debugLazy(() => `Signal Stream: ${JSON.stringify(data)}`);
|
|
932
|
+
return this.sendGatewayPacket({
|
|
1009
933
|
op: Opcodes.STREAM_CREATE,
|
|
1010
934
|
d: data,
|
|
1011
935
|
});
|
|
@@ -1032,7 +956,7 @@ class StreamConnection extends VoiceConnection {
|
|
|
1032
956
|
},
|
|
1033
957
|
);
|
|
1034
958
|
this.isPaused = isPaused;
|
|
1035
|
-
this.
|
|
959
|
+
this.sendGatewayPacket({
|
|
1036
960
|
op: Opcodes.STREAM_SET_PAUSED,
|
|
1037
961
|
d: {
|
|
1038
962
|
stream_key: this.streamKey,
|
|
@@ -1048,7 +972,7 @@ class StreamConnection extends VoiceConnection {
|
|
|
1048
972
|
*/
|
|
1049
973
|
sendStopScreenshare() {
|
|
1050
974
|
this.#requestDisconnect = true;
|
|
1051
|
-
this.
|
|
975
|
+
this.sendGatewayPacket({
|
|
1052
976
|
op: Opcodes.STREAM_DELETE,
|
|
1053
977
|
d: {
|
|
1054
978
|
stream_key: this.streamKey,
|
|
@@ -1177,7 +1101,7 @@ class StreamConnectionReadonly extends VoiceConnection {
|
|
|
1177
1101
|
disconnect() {
|
|
1178
1102
|
if (this.#requestDisconnect) return;
|
|
1179
1103
|
this.emit('closing');
|
|
1180
|
-
this.
|
|
1104
|
+
this._debug('Stream: disconnect() triggered');
|
|
1181
1105
|
clearTimeout(this.connectTimeout);
|
|
1182
1106
|
this.voiceConnection.streamWatchConnection.delete(this.userId);
|
|
1183
1107
|
this.sendStopScreenshare();
|
|
@@ -1189,8 +1113,8 @@ class StreamConnectionReadonly extends VoiceConnection {
|
|
|
1189
1113
|
* @returns {void}
|
|
1190
1114
|
*/
|
|
1191
1115
|
sendSignalScreenshare() {
|
|
1192
|
-
this.
|
|
1193
|
-
return this.
|
|
1116
|
+
this._debug(`Signal Stream Watch: ${this.streamKey}`);
|
|
1117
|
+
return this.sendGatewayPacket({
|
|
1194
1118
|
op: Opcodes.STREAM_WATCH,
|
|
1195
1119
|
d: {
|
|
1196
1120
|
stream_key: this.streamKey,
|
|
@@ -1205,7 +1129,7 @@ class StreamConnectionReadonly extends VoiceConnection {
|
|
|
1205
1129
|
*/
|
|
1206
1130
|
sendStopScreenshare() {
|
|
1207
1131
|
this.#requestDisconnect = true;
|
|
1208
|
-
this.
|
|
1132
|
+
this.sendGatewayPacket({
|
|
1209
1133
|
op: Opcodes.STREAM_DELETE,
|
|
1210
1134
|
d: {
|
|
1211
1135
|
stream_key: this.streamKey,
|