diff options
Diffstat (limited to 'cogs/voice.py')
| -rw-r--r-- | cogs/voice.py | 54 |
1 files changed, 43 insertions, 11 deletions
diff --git a/cogs/voice.py b/cogs/voice.py index f079c6a..a224336 100644 --- a/cogs/voice.py +++ b/cogs/voice.py | |||
| @@ -80,17 +80,29 @@ class VoiceManager: | |||
| 80 | logger.info(f"Already connected to {channel}") | 80 | logger.info(f"Already connected to {channel}") |
| 81 | return vc | 81 | return vc |
| 82 | logger.warning(f"Stale connection to {channel}, reconnecting") | 82 | logger.warning(f"Stale connection to {channel}, reconnecting") |
| 83 | # Disconnect resets the state machine to 'disconnected' | ||
| 84 | # but keeps the VoiceClient alive. Reusing it avoids a | ||
| 85 | # race where Discord sends VOICE_SERVER_UPDATE between | ||
| 86 | # the destroy and the fresh-connect below, causing the | ||
| 87 | # new client to timeout waiting for the event (since the | ||
| 88 | # old one already consumed it). | ||
| 83 | try: | 89 | try: |
| 84 | await vc.disconnect() | 90 | await vc.disconnect() |
| 85 | except Exception: | 91 | except Exception: |
| 86 | pass | 92 | pass |
| 87 | # Forcefully clear stale internal state so the fresh | ||
| 88 | # connect doesn't hang for 30s waiting for Discord. | ||
| 89 | try: | 93 | try: |
| 90 | channel._state._remove_voice_client(guild.id) | 94 | await vc.connect( |
| 91 | except Exception: | 95 | reconnect=False, timeout=10.0, self_deaf=False, self_mute=False |
| 92 | pass | 96 | ) |
| 93 | vc = None | 97 | logger.info(f"Reconnected to voice channel: {channel}") |
| 98 | return vc | ||
| 99 | except Exception as e: | ||
| 100 | logger.error(f"Failed to reconnect stale voice client: {e}") | ||
| 101 | try: | ||
| 102 | channel._state._remove_voice_client(guild.id) | ||
| 103 | except Exception: | ||
| 104 | pass | ||
| 105 | vc = None | ||
| 94 | else: | 106 | else: |
| 95 | try: | 107 | try: |
| 96 | await vc.move_to(channel) | 108 | await vc.move_to(channel) |
| @@ -102,18 +114,38 @@ class VoiceManager: | |||
| 102 | await vc.disconnect() | 114 | await vc.disconnect() |
| 103 | except Exception: | 115 | except Exception: |
| 104 | pass | 116 | pass |
| 117 | try: | ||
| 118 | await vc.connect( | ||
| 119 | reconnect=False, timeout=10.0, self_deaf=False, self_mute=False | ||
| 120 | ) | ||
| 121 | logger.info(f"Reconnected after failed move: {channel}") | ||
| 122 | return vc | ||
| 123 | except Exception: | ||
| 124 | pass | ||
| 125 | try: | ||
| 126 | channel._state._remove_voice_client(guild.id) | ||
| 127 | except Exception: | ||
| 128 | pass | ||
| 105 | vc = None | 129 | vc = None |
| 106 | else: | 130 | else: |
| 107 | logger.info("Voice client exists but disconnected, cleaning up stale entry") | 131 | logger.info("Voice client exists but disconnected, reconnecting") |
| 108 | try: | 132 | try: |
| 109 | await vc.disconnect() | 133 | await vc.disconnect() |
| 110 | except Exception: | 134 | except Exception: |
| 111 | pass | 135 | pass |
| 112 | try: | 136 | try: |
| 113 | channel._state._remove_voice_client(guild.id) | 137 | await vc.connect( |
| 114 | except Exception: | 138 | reconnect=False, timeout=10.0, self_deaf=False, self_mute=False |
| 115 | pass | 139 | ) |
| 116 | vc = None | 140 | logger.info(f"Reconnected disconnected client: {channel}") |
| 141 | return vc | ||
| 142 | except Exception as e: | ||
| 143 | logger.error(f"Failed to reconnect disconnected client: {e}") | ||
| 144 | try: | ||
| 145 | channel._state._remove_voice_client(guild.id) | ||
| 146 | except Exception: | ||
| 147 | pass | ||
| 148 | vc = None | ||
| 117 | 149 | ||
| 118 | # --- create fresh connection -------------------------------------- | 150 | # --- create fresh connection -------------------------------------- |
| 119 | self._connecting.add(guild_id) | 151 | self._connecting.add(guild_id) |
