@@ -323,7 +323,7 @@ async def voice_server_update(self, data: VoiceServerUpdatePayload) -> None:
323
323
)
324
324
return
325
325
326
- self .endpoint , _ , _ = endpoint . rpartition ( ':' )
326
+ self .endpoint = endpoint
327
327
if self .endpoint .startswith ('wss://' ):
328
328
# Just in case, strip it off since we're going to add it later
329
329
self .endpoint = self .endpoint [6 :]
@@ -603,7 +603,10 @@ async def _voice_disconnect(self) -> None:
603
603
self ._disconnected .clear ()
604
604
605
605
async def _connect_websocket (self , resume : bool ) -> DiscordVoiceWebSocket :
606
- ws = await DiscordVoiceWebSocket .from_connection_state (self , resume = resume , hook = self .hook )
606
+ seq_ack = - 1
607
+ if self .ws is not MISSING :
608
+ seq_ack = self .ws .seq_ack
609
+ ws = await DiscordVoiceWebSocket .from_connection_state (self , resume = resume , hook = self .hook , seq_ack = seq_ack )
607
610
self .state = ConnectionFlowState .websocket_connected
608
611
return ws
609
612
@@ -632,18 +635,20 @@ async def _poll_voice_ws(self, reconnect: bool) -> None:
632
635
# The following close codes are undocumented so I will document them here.
633
636
# 1000 - normal closure (obviously)
634
637
# 4014 - we were externally disconnected (voice channel deleted, we were moved, etc)
635
- # 4015 - voice server has crashed
638
+ # 4015 - voice server has crashed, we should resume
639
+ # 4021 - rate limited, we should not reconnect
640
+ # 4022 - call terminated, similar to 4014
636
641
637
642
code = getattr (exc , 'code' , self .ws ._close_code )
638
643
639
- if code in ( 1000 , 4015 ) :
644
+ if code == 1000 :
640
645
# Don't call disconnect a second time if the websocket closed from a disconnect call
641
646
if not self ._expecting_disconnect :
642
647
_log .info ('Disconnecting from voice normally, close code %d.' , code )
643
648
await self .disconnect ()
644
649
break
645
650
646
- if code == 4014 :
651
+ if code in ( 4014 , 4022 ) :
647
652
# We were disconnected by discord
648
653
# This condition is a race between the main ws event and the voice ws closing
649
654
if self ._disconnected .is_set ():
@@ -663,6 +668,32 @@ async def _poll_voice_ws(self, reconnect: bool) -> None:
663
668
else :
664
669
continue
665
670
671
+ if code == 4021 :
672
+ _log .warning ('We are being rate limited while trying to connect to voice. Disconnecting...' )
673
+ if self .state is not ConnectionFlowState .disconnected :
674
+ await self .disconnect ()
675
+ break
676
+
677
+ if exc .code == 4015 :
678
+ _log .info ('Disconnected from voice, attempting a resume...' )
679
+ try :
680
+ await self ._connect (
681
+ reconnect = reconnect ,
682
+ timeout = self .timeout ,
683
+ self_deaf = (self .self_voice_state or self ).self_deaf ,
684
+ self_mute = (self .self_voice_state or self ).self_mute ,
685
+ self_video = (self .self_voice_state or self ).self_video ,
686
+ resume = True ,
687
+ )
688
+ except asyncio .TimeoutError :
689
+ _log .info ('Could not resume the voice connection. Disconnecting...' )
690
+ if self .state is not ConnectionFlowState .disconnected :
691
+ await self .disconnect ()
692
+ break
693
+ else :
694
+ _log .info ('Successfully resumed voice connection.' )
695
+ continue
696
+
666
697
_log .debug (
667
698
'Not handling voice socket close code %s (reason: %s).' ,
668
699
code ,
0 commit comments