Skip to content

Commit 26a9420

Browse files
DA-344pre-commit-ci[bot]Lulalaby
authored andcommitted
fix: 4006 voice crashes and upgrade to voice v8 (Pycord-Development#2812)
Signed-off-by: Lala Sabathil <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Lala Sabathil <[email protected]> (cherry picked from commit 2ae01b7)
1 parent 9a5554f commit 26a9420

File tree

3 files changed

+43
-10
lines changed

3 files changed

+43
-10
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ These changes are available on the `master` branch, but have not yet been releas
119119
([#2781](https://github.com/Pycord-Development/pycord/pull/2781))
120120
- Fixed `VoiceClient` crashing randomly while receiving audio
121121
([#2800](https://github.com/Pycord-Development/pycord/pull/2800))
122+
- Fixed `VoiceClient.connect` failing to do initial connection.
123+
([#2812](https://github.com/Pycord-Development/pycord/pull/2812))
122124

123125
### Changed
124126

@@ -138,6 +140,8 @@ These changes are available on the `master` branch, but have not yet been releas
138140
([#2564](https://github.com/Pycord-Development/pycord/pull/2564))
139141
- Changed the default value of `ApplicationCommand.nsfw` to `False`.
140142
([#2797](https://github.com/Pycord-Development/pycord/pull/2797))
143+
- Upgraded voice websocket version to v8.
144+
([#2812](https://github.com/Pycord-Development/pycord/pull/2812))
141145

142146
### Deprecated
143147

discord/gateway.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import traceback
3636
import zlib
3737
from collections import deque, namedtuple
38+
from typing import TYPE_CHECKING
3839

3940
import aiohttp
4041

@@ -200,6 +201,9 @@ def ack(self):
200201

201202

202203
class VoiceKeepAliveHandler(KeepAliveHandler):
204+
if TYPE_CHECKING:
205+
ws: DiscordVoiceWebSocket
206+
203207
def __init__(self, *args, **kwargs):
204208
super().__init__(*args, **kwargs)
205209
self.recent_ack_latencies = deque(maxlen=20)
@@ -208,7 +212,10 @@ def __init__(self, *args, **kwargs):
208212
self.behind_msg = "High socket latency, shard ID %s heartbeat is %.1fs behind"
209213

210214
def get_payload(self):
211-
return {"op": self.ws.HEARTBEAT, "d": int(time.time() * 1000)}
215+
return {
216+
"op": self.ws.HEARTBEAT,
217+
"d": {"t": int(time.time() * 1000), "seq_ack": self.ws.seq_ack},
218+
}
212219

213220
def ack(self):
214221
ack_time = time.perf_counter()
@@ -766,6 +773,7 @@ def __init__(self, socket, loop, *, hook=None):
766773
self._close_code = None
767774
self.secret_key = None
768775
self.ssrc_map = {}
776+
self.seq_ack: int = -1
769777
if hook:
770778
self._hook = hook
771779

@@ -786,6 +794,9 @@ async def resume(self):
786794
"token": state.token,
787795
"server_id": str(state.server_id),
788796
"session_id": state.session_id,
797+
# this seq_ack will allow for us to do buffered resume, which is, receive the
798+
# lost voice packets while trying to resume the reconnection
799+
"seq_ack": self.seq_ack,
789800
},
790801
}
791802
await self.send_as_json(payload)
@@ -806,7 +817,7 @@ async def identify(self):
806817
@classmethod
807818
async def from_client(cls, client, *, resume=False, hook=None):
808819
"""Creates a voice websocket for the :class:`VoiceClient`."""
809-
gateway = f"wss://{client.endpoint}/?v=4"
820+
gateway = f"wss://{client.endpoint}/?v=8"
810821
http = client._state.http
811822
socket = await http.ws_connect(gateway, compress=15)
812823
ws = cls(socket, loop=client.loop, hook=hook)
@@ -842,14 +853,21 @@ async def client_connect(self):
842853
await self.send_as_json(payload)
843854

844855
async def speak(self, state=SpeakingState.voice):
845-
payload = {"op": self.SPEAKING, "d": {"speaking": int(state), "delay": 0}}
856+
payload = {
857+
"op": self.SPEAKING,
858+
"d": {
859+
"speaking": int(state),
860+
"delay": 0,
861+
},
862+
}
846863

847864
await self.send_as_json(payload)
848865

849866
async def received_message(self, msg):
850867
_log.debug("Voice websocket frame received: %s", msg)
851868
op = msg["op"]
852869
data = msg.get("d")
870+
self.seq_ack = data.get("seq", self.seq_ack)
853871

854872
if op == self.READY:
855873
await self.initial_connection(data)

discord/voice_client.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -325,11 +325,7 @@ async def on_voice_server_update(self, data: VoiceServerUpdatePayload) -> None:
325325
)
326326
return
327327

328-
self.endpoint, _, _ = endpoint.rpartition(":")
329-
if self.endpoint.startswith("wss://"):
330-
# Just in case, strip it off since we're going to add it later
331-
self.endpoint = self.endpoint[6:]
332-
328+
self.endpoint = endpoint.removeprefix("wss://")
333329
# This gets set later
334330
self.endpoint_ip = MISSING
335331

@@ -467,8 +463,8 @@ async def poll_voice_ws(self, reconnect: bool) -> None:
467463
# The following close codes are undocumented, so I will document them here.
468464
# 1000 - normal closure (obviously)
469465
# 4014 - voice channel has been deleted.
470-
# 4015 - voice server has crashed
471-
if exc.code in (1000, 4015):
466+
# 4015 - voice server has crashed, we should resume
467+
if exc.code == 1000:
472468
_log.info(
473469
"Disconnecting from voice normally, close code %d.",
474470
exc.code,
@@ -484,6 +480,21 @@ async def poll_voice_ws(self, reconnect: bool) -> None:
484480
_log.info("Reconnect was unsuccessful, disconnecting from voice normally...")
485481
await self.disconnect()
486482
break
483+
if exc.code == 4015:
484+
_log.info("Disconnected from voice, trying to resume...")
485+
486+
try:
487+
await self.ws.resume()
488+
except asyncio.TimeoutError:
489+
_log.info(
490+
"Could not resume the voice connection... Disconnection..."
491+
)
492+
if self._connected.is_set():
493+
await self.disconnect(force=True)
494+
else:
495+
_log.info("Successfully resumed voice connection")
496+
continue
497+
487498
if not reconnect:
488499
await self.disconnect()
489500
raise

0 commit comments

Comments
 (0)