discord_radio: don't count the bot's own voice state toward a full channel; timeout text points at the handshake
Permissions are pre-checked now, so a connect timeout is the voice handshake (pre-2.7 discord.py: DAVE close 4017 retried to the 30s timeout) or UDP egress, not permissions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
786e06a7a3
commit
2065446393
@@ -100,7 +100,11 @@ def _join_refusal(guild, channel) -> Optional[tuple[str, str]]:
|
|||||||
f"The radio bot lacks {', '.join(missing)} on that voice channel — "
|
f"The radio bot lacks {', '.join(missing)} on that voice channel — "
|
||||||
"allow it in the channel's permission settings in Discord.")
|
"allow it in the channel's permission settings in Discord.")
|
||||||
limit = getattr(channel, "user_limit", 0) or 0
|
limit = getattr(channel, "user_limit", 0) or 0
|
||||||
members = getattr(channel, "members", None) or []
|
# The bot's own lingering voice state (a dropped connection) is not a
|
||||||
|
# slot it needs; counting it would block the rejoin of a full channel.
|
||||||
|
me_id = getattr(me, "id", None)
|
||||||
|
members = [m for m in (getattr(channel, "members", None) or [])
|
||||||
|
if me_id is None or getattr(m, "id", None) != me_id]
|
||||||
if limit and len(members) >= limit and not getattr(perms, "move_members", False):
|
if limit and len(members) >= limit and not getattr(perms, "move_members", False):
|
||||||
return ("channel_full", f"That voice channel is full ({len(members)}/{limit}) — "
|
return ("channel_full", f"That voice channel is full ({len(members)}/{limit}) — "
|
||||||
"raise its user limit or free a slot.")
|
"raise its user limit or free a slot.")
|
||||||
@@ -334,8 +338,11 @@ class RadioManager:
|
|||||||
# "(TimeoutError: )" — useless on the admin page.
|
# "(TimeoutError: )" — useless on the admin page.
|
||||||
v.vc = None
|
v.vc = None
|
||||||
v.state, v.code = "error", "connect_timeout"
|
v.state, v.code = "error", "connect_timeout"
|
||||||
v.error = ("Discord never completed the voice join (timed out). Check the channel's "
|
# Permissions were checked above, so this is usually the voice
|
||||||
"permission overrides for the radio bot and that Discord voice is healthy.")
|
# handshake itself (e.g. a pre-2.7 discord.py refused with 4017 for
|
||||||
|
# lacking DAVE E2EE, then retried until the 30s timeout) or UDP egress.
|
||||||
|
v.error = ("Discord never completed the voice join (timed out). Permissions look fine, so "
|
||||||
|
"check the node's discord.py voice log (DAVE close 4017, UDP blocked).")
|
||||||
logger.error(f"Stream {v.stream_id}: voice connect timed out")
|
logger.error(f"Stream {v.stream_id}: voice connect timed out")
|
||||||
return
|
return
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -296,6 +296,17 @@ async def test_full_channel_is_reported(env):
|
|||||||
assert st["code"] == "channel_full" and "2/2" in st["error"]
|
assert st["code"] == "channel_full" and "2/2" in st["error"]
|
||||||
|
|
||||||
|
|
||||||
|
async def test_bots_own_lingering_voice_state_does_not_fill_the_channel(env):
|
||||||
|
"""A dropped connection can leave the bot listed in the channel; that is
|
||||||
|
not a slot it needs to rejoin."""
|
||||||
|
guild = env.guilds[1]
|
||||||
|
guild.me = type("Me", (), {"id": 999})()
|
||||||
|
ch = guild.channels[11]
|
||||||
|
ch.user_limit, ch.members = 2, [object(), guild.me]
|
||||||
|
await env.mgr.apply_desired(_desired(1, (1, 11, "t1")))
|
||||||
|
assert env.published[-1]["streams"]["1:11"]["state"] == "connected"
|
||||||
|
|
||||||
|
|
||||||
async def test_connect_timeout_has_a_readable_error(env):
|
async def test_connect_timeout_has_a_readable_error(env):
|
||||||
env.guilds[1].channels[11].connect_error = asyncio.TimeoutError()
|
env.guilds[1].channels[11].connect_error = asyncio.TimeoutError()
|
||||||
await env.mgr.apply_desired(_desired(1, (1, 11, "t1")))
|
await env.mgr.apply_desired(_desired(1, (1, 11, "t1")))
|
||||||
|
|||||||
Reference in New Issue
Block a user