Discord.py语音频道进出自动角色 静音操作时异常移除角色求助
故障原因
异常触发的核心是现有代码对on_voice_state_update事件的触发边界判断错误,且错误使用阻塞式监听,具体问题点:
on_voice_state_update并非仅在成员进出语音频道时触发,成员执行静音/取消静音、开关摄像头、被服务端禁言/静音等所有语音状态变更操作,都会触发该事件。现有代码没有过滤非频道切换类的状态变更,事件触发后会直接进入业务逻辑。- 代码中
wait_for的校验逻辑存在全局匹配漏洞:check函数仅判断before.channel != after.channel,没有限定触发事件的成员为当前被授予角色的成员,只要服务器内任意成员切换语音频道,阻塞的wait_for就会返回并执行移除角色操作,和当前成员的实际状态无关。 - 循环逻辑存在冗余:遍历5个频道时只要匹配到成员在任一目标频道,都会重复执行加角色、注册wait_for监听的操作,多个并发监听同时运行时,任意一个监听被触发都会执行角色移除,直接导致随机掉角色的问题。
- 缺少边界状态处理:没有兼容成员初始就在频道、成员从频道直接退出语音连接等场景,会出现角色漏加、漏删的问题。
修正方案
移除不稳定的wait_for阻塞监听逻辑,直接在事件回调中判断频道变更状态,非频道切换类操作直接跳过,完整实现代码如下:
@bot.event async def on_voice_state_update(member, before, after): # 配置项:绑定角色的目标语音频道列表、对应自动授予的角色 TARGET_CHANNELS = bot.fleets[0] AUTO_ROLE = bot.fleet1 # 兼容频道为空的边界场景,提取前后状态的频道ID before_ch_id = before.channel.id if before.channel else None after_ch_id = after.channel.id if after.channel else None # 频道未发生变化(即静音、开关摄像头等操作),直接终止逻辑 if before_ch_id == after_ch_id: return # 成员进入目标频道,授予对应角色 if after_ch_id in TARGET_CHANNELS: await member.add_roles(AUTO_ROLE) # 成员离开目标频道,移除对应角色 if before_ch_id in TARGET_CHANNELS: await member.remove_roles(AUTO_ROLE)
该实现从根源过滤了静音等非频道切换操作的触发,不存在全局监听串扰问题,同时覆盖了成员进出频道、直接断开语音连接等所有边界场景,不会出现随机移除角色的异常。
内容的提问来源于stack exchange,提问作者Goldman511
相关产品推荐
相关产品推荐

