如何让Discord机器人断开语音后向指定文本频道发消息并在play命令中检测离开?
解决Discord机器人离开语音频道后仅向指令发起频道发消息的问题
核心思路是记录每个服务器中发起play指令的文本频道,当机器人断开语音连接时,直接使用该频道发送通知,避免全局事件无法关联指令来源的问题。
修改后的完整代码
import asyncio import discord from discord.ext import commands class Commands(commands.Cog): def __init__(self, bot): self.bot = bot # 存储服务器ID与对应指令发起文本频道的映射 self.guild_text_channels = {} @commands.Cog.listener() async def on_voice_state_update(self, member, before, after): if not member.id == self.bot.user.id: return # 检测机器人是否从语音频道断开(之前在频道,之后不在) if before.channel is not None and after.channel is None: guild_id = before.channel.guild.id # 检查当前服务器是否有记录的指令频道 if guild_id in self.guild_text_channels: text_channel = self.guild_text_channels[guild_id] await text_channel.send("我已离开语音频道!") # 发送后删除记录,避免重复触发 del self.guild_text_channels[guild_id] return # 原自动断开超时逻辑 elif before.channel is None: voice = after.channel.guild.voice_client time = 0 while True: await asyncio.sleep(1) time += 1 if voice.is_playing() and not voice.is_paused(): time = 0 if time == 10: await voice.disconnect() # 修正原代码的语法错误:is_connected是方法,需要加括号 if not voice.is_connected(): break @commands.command(pass_context=True) async def play(self, ctx): if ctx.author.voice: channel = ctx.author.voice.channel await channel.connect() # 记录当前服务器对应的指令发起文本频道 self.guild_text_channels[ctx.guild.id] = ctx.channel
关键修改说明
- 新增
self.guild_text_channels字典,用服务器ID作为键,保存发起play指令的文本频道对象,实现指令来源与服务器的绑定。 - 在
on_voice_state_update事件中,新增机器人断开语音的状态检测逻辑:当before.channel存在且after.channel为空时,判定为断开连接,此时从字典中取出对应文本频道发送消息。 - 修正原代码的语法错误:
voice.is_connected是方法调用,必须添加括号voice.is_connected(),否则无法正确判断连接状态。
内容的提问来源于stack exchange,提问作者iflookscouldkill
相关产品推荐
相关产品推荐

