diff --git a/packages/voice/src/networking/Networking.ts b/packages/voice/src/networking/Networking.ts index a3922c4f6a96..64952c564478 100644 --- a/packages/voice/src/networking/Networking.ts +++ b/packages/voice/src/networking/Networking.ts @@ -298,9 +298,14 @@ export class Networking extends EventEmitter { * Creates a new WebSocket to a Discord Voice gateway. * * @param endpoint - The endpoint to connect to + * @param lastSequence - The last sequence to set for this WebSocket */ - private createWebSocket(endpoint: string) { - const ws = new VoiceWebSocket(`wss://${endpoint}?v=4`, Boolean(this.debug)); + private createWebSocket(endpoint: string, lastSequence?: number) { + const ws = new VoiceWebSocket(`wss://${endpoint}?v=8`, Boolean(this.debug)); + + if (lastSequence !== undefined) { + ws.sequence = lastSequence; + } ws.on('error', this.onChildError); ws.once('open', this.onWsOpen); @@ -347,6 +352,7 @@ export class Networking extends EventEmitter { server_id: this.state.connectionOptions.serverId, session_id: this.state.connectionOptions.sessionId, token: this.state.connectionOptions.token, + seq_ack: this.state.ws.sequence, }, }; this.state.ws.sendPacket(packet); @@ -363,10 +369,11 @@ export class Networking extends EventEmitter { private onWsClose({ code }: CloseEvent) { const canResume = code === 4_015 || code < 4_000; if (canResume && this.state.code === NetworkingStatusCode.Ready) { + const lastSequence = this.state.ws.sequence; this.state = { ...this.state, code: NetworkingStatusCode.Resuming, - ws: this.createWebSocket(this.state.connectionOptions.endpoint), + ws: this.createWebSocket(this.state.connectionOptions.endpoint, lastSequence), }; } else if (this.state.code !== NetworkingStatusCode.Closed) { this.destroy(); @@ -379,10 +386,11 @@ export class Networking extends EventEmitter { */ private onUdpClose() { if (this.state.code === NetworkingStatusCode.Ready) { + const lastSequence = this.state.ws.sequence; this.state = { ...this.state, code: NetworkingStatusCode.Resuming, - ws: this.createWebSocket(this.state.connectionOptions.endpoint), + ws: this.createWebSocket(this.state.connectionOptions.endpoint, lastSequence), }; } } diff --git a/packages/voice/src/networking/VoiceWebSocket.ts b/packages/voice/src/networking/VoiceWebSocket.ts index 86d69e17c34b..6a6c09205676 100644 --- a/packages/voice/src/networking/VoiceWebSocket.ts +++ b/packages/voice/src/networking/VoiceWebSocket.ts @@ -52,6 +52,11 @@ export class VoiceWebSocket extends EventEmitter { */ public ping?: number; + /** + * The last sequence number acknowledged from Discord. Will be `-1` if no sequence numbered messages have been received. + */ + public sequence = -1; + /** * The debug logger function, if debugging is enabled. */ @@ -115,6 +120,10 @@ export class VoiceWebSocket extends EventEmitter { return; } + if (packet.seq) { + this.sequence = packet.seq; + } + if (packet.op === VoiceOpcodes.HeartbeatAck) { this.lastHeartbeatAck = Date.now(); this.missedHeartbeats = 0; @@ -150,7 +159,11 @@ export class VoiceWebSocket extends EventEmitter { this.sendPacket({ op: VoiceOpcodes.Heartbeat, // eslint-disable-next-line id-length - d: nonce, + d: { + // eslint-disable-next-line id-length + t: nonce, + seq_ack: this.sequence, + }, }); }