From e1aa6cc264911985d21a6a598d72a087c4ba4b9e Mon Sep 17 00:00:00 2001 From: Imayhaveborkedit Date: Sun, 1 Oct 2023 17:45:55 -0400 Subject: [PATCH] Fix bad voice state when moving to a voice channel without permissions --- discord/voice_client.py | 3 +-- discord/voice_state.py | 22 +++++++++++++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/discord/voice_client.py b/discord/voice_client.py index d991f1476..3c5699acd 100644 --- a/discord/voice_client.py +++ b/discord/voice_client.py @@ -355,8 +355,7 @@ class VoiceClient(VoiceProtocol): asyncio.TimeoutError The move did not complete in time, but may still be ongoing. """ - await self._connection.move_to(channel) - await self._connection.wait_async(timeout) + await self._connection.move_to(channel, timeout) def is_connected(self) -> bool: """Indicates if the voice client is connected to voice.""" diff --git a/discord/voice_state.py b/discord/voice_state.py index 4ede821be..1dda1e5d9 100644 --- a/discord/voice_state.py +++ b/discord/voice_state.py @@ -459,13 +459,25 @@ class VoiceConnectionState: if self.socket: self.socket.close() - async def move_to(self, channel: Optional[abc.Snowflake]) -> None: + async def move_to(self, channel: Optional[abc.Snowflake], timeout: Optional[float]) -> None: if channel is None: await self.disconnect() return - await self.voice_client.channel.guild.change_voice_state(channel=channel) - self.state = ConnectionFlowState.set_guild_voice_state + previous_state = self.state + # this is only an outgoing ws request + # if it fails, nothing happens and nothing changes (besides self.state) + await self._move_to(channel) + + last_state = self.state + try: + await self.wait_async(timeout) + except asyncio.TimeoutError: + _log.warning('Timed out trying to move to channel %s in guild %s', channel.id, self.guild.id) + if self.state is last_state: + _log.debug('Reverting to previous state %s', previous_state.name) + + self.state = previous_state def wait(self, timeout: Optional[float] = None) -> bool: return self._connected.wait(timeout) @@ -594,3 +606,7 @@ class VoiceConnectionState: return False else: return True + + async def _move_to(self, channel: abc.Snowflake) -> None: + await self.voice_client.channel.guild.change_voice_state(channel=channel) + self.state = ConnectionFlowState.set_guild_voice_state