@@ -321,7 +321,7 @@ async def voice_server_update(self, data: VoiceServerUpdatePayload) -> None:
321321 )
322322 return
323323
324- self .endpoint , _ , _ = endpoint . rpartition ( ':' )
324+ self .endpoint = endpoint
325325 if self .endpoint .startswith ('wss://' ):
326326 # Just in case, strip it off since we're going to add it later
327327 self .endpoint = self .endpoint [6 :]
@@ -574,7 +574,10 @@ async def _voice_disconnect(self) -> None:
574574 self ._disconnected .clear ()
575575
576576 async def _connect_websocket (self , resume : bool ) -> DiscordVoiceWebSocket :
577- ws = await DiscordVoiceWebSocket .from_connection_state (self , resume = resume , hook = self .hook )
577+ seq_ack = - 1
578+ if self .ws is not MISSING :
579+ seq_ack = self .ws .seq_ack
580+ ws = await DiscordVoiceWebSocket .from_connection_state (self , resume = resume , hook = self .hook , seq_ack = seq_ack )
578581 self .state = ConnectionFlowState .websocket_connected
579582 return ws
580583
@@ -603,15 +606,17 @@ async def _poll_voice_ws(self, reconnect: bool) -> None:
603606 # The following close codes are undocumented so I will document them here.
604607 # 1000 - normal closure (obviously)
605608 # 4014 - we were externally disconnected (voice channel deleted, we were moved, etc)
606- # 4015 - voice server has crashed
607- if exc .code in (1000 , 4015 ):
609+ # 4015 - voice server has crashed, we should resume
610+ # 4021 - rate limited, we should not reconnect
611+ # 4022 - call terminated, similar to 4014
612+ if exc .code == 1000 :
608613 # Don't call disconnect a second time if the websocket closed from a disconnect call
609614 if not self ._expecting_disconnect :
610615 _log .info ('Disconnecting from voice normally, close code %d.' , exc .code )
611616 await self .disconnect ()
612617 break
613618
614- if exc .code == 4014 :
619+ if exc .code in ( 4014 , 4022 ) :
615620 # We were disconnected by discord
616621 # This condition is a race between the main ws event and the voice ws closing
617622 if self ._disconnected .is_set ():
@@ -631,6 +636,31 @@ async def _poll_voice_ws(self, reconnect: bool) -> None:
631636 else :
632637 continue
633638
639+ if exc .code == 4021 :
640+ _log .warning ('We are being ratelimited while trying to connect to voice. Disconnecting...' )
641+ if self .state is not ConnectionFlowState .disconnected :
642+ await self .disconnect ()
643+ break
644+
645+ if exc .code == 4015 :
646+ _log .info ('Disconnected from voice, attempting a resume...' )
647+ try :
648+ await self ._connect (
649+ reconnect = reconnect ,
650+ timeout = self .timeout ,
651+ self_deaf = (self .self_voice_state or self ).self_deaf ,
652+ self_mute = (self .self_voice_state or self ).self_mute ,
653+ resume = True ,
654+ )
655+ except asyncio .TimeoutError :
656+ _log .info ('Could not resume the voice connection... Disconnecting...' )
657+ if self .state is not ConnectionFlowState .disconnected :
658+ await self .disconnect ()
659+ break
660+ else :
661+ _log .info ('Successfully resumed voice connection' )
662+ continue
663+
634664 _log .debug ('Not handling close code %s (%s)' , exc .code , exc .reason or 'no reason' )
635665
636666 if not reconnect :
0 commit comments