Discord机器人第二次迭代后反应无响应问题求助
Discord机器人反应交互循环异常问题排查与修复
问题现象
执行/test命令后,机器人进入1到99的迭代循环,每次更新Embed标题并添加✅反应:
- 第二次迭代时点击反应,机器人停止工作;后续迭代点击反应完全无响应
- 预期点击反应时触发
check()函数并终止循环,但实际未正常执行,程序无报错输出
代码问题分析
- 重复添加反应:每次循环都调用
await sent_embed.add_reaction('✅'),导致消息上叠加多个相同反应,wait_for监听的新增反应无法与当前迭代正确绑定,点击后续反应时可能被之前的等待实例忽略。 - 未清理等待任务:每次循环创建新的
wait_for,但前一次的等待任务未被取消,点击反应时可能被旧任务捕获,导致逻辑混乱;且stop_loop变量仅在循环开始时检查,无法中断正在运行的wait_for。 - 冗余延迟逻辑:第一次迭代后的
await asyncio.sleep(2)和超时后的await asyncio.sleep(1)会打乱交互节奏,且无必要。
修复后的代码
import asyncio import discord from discord.commands import slash_command from discord.ext import commands class Test(commands.Cog): def __init__(self, bot): self.bot = bot self.stop_loop = False self.reaction_task = None @slash_command(name='test', description='测试反应交互循环') async def test(self, ctx): self.stop_loop = False self.reaction_task = None def check(reaction, user): self.stop_loop = True print("clicked") return user == ctx.author and str(reaction.emoji) == "✅" # 初始化消息和反应,只添加一次反应 embed = discord.Embed(title="1x") interaction: discord.Interaction = await ctx.respond(embed=embed) sent_embed = await interaction.original_response() await sent_embed.add_reaction('✅') for i in range(2, 100): if self.stop_loop: if self.reaction_task: self.reaction_task.cancel() return # 更新Embed标题 embed = discord.Embed(title=f"{i}x") await interaction.edit_original_response(embed=embed) # 创建新的反应等待任务 try: self.reaction_task = asyncio.create_task( self.bot.wait_for("reaction_add", check=check, timeout=2.0) ) reaction, user = await self.reaction_task print(reaction) embed = discord.Embed(title=f"You clicked on {i}") await interaction.edit_original_response(embed=embed) return except asyncio.exceptions.TimeoutError: # 超时后取消当前任务,进入下一次迭代 if self.reaction_task: self.reaction_task.cancel() continue finally: self.reaction_task = None def setup(bot): bot.add_cog(Test(bot))
关键修改说明
- 单次添加反应:仅在初始化时添加一次✅反应,避免消息上叠加多个相同反应,确保每次点击的都是同一个反应,
wait_for能正确捕获。 - 使用
asyncio.Task管理等待:每次迭代创建新的等待任务,超时或终止时主动取消任务,避免旧任务干扰后续逻辑。 - 优化循环逻辑:将第一次迭代从循环中分离,循环从2开始,简化流程;移除冗余的
sleep调用,让交互更流畅。 - 及时终止循环:点击反应触发
check()后设置stop_loop=True,循环开始时检查该变量并取消当前等待任务,立即终止流程。
内容的提问来源于stack exchange,提问作者syrok
相关产品推荐
相关产品推荐

