You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Discord机器人第二次迭代后反应无响应问题求助

Discord机器人反应交互循环异常问题排查与修复

问题现象

执行/test命令后,机器人进入1到99的迭代循环,每次更新Embed标题并添加✅反应:

  • 第二次迭代时点击反应,机器人停止工作;后续迭代点击反应完全无响应
  • 预期点击反应时触发check()函数并终止循环,但实际未正常执行,程序无报错输出

代码问题分析

  1. 重复添加反应:每次循环都调用await sent_embed.add_reaction('✅'),导致消息上叠加多个相同反应,wait_for监听的新增反应无法与当前迭代正确绑定,点击后续反应时可能被之前的等待实例忽略。
  2. 未清理等待任务:每次循环创建新的wait_for,但前一次的等待任务未被取消,点击反应时可能被旧任务捕获,导致逻辑混乱;且stop_loop变量仅在循环开始时检查,无法中断正在运行的wait_for。
  3. 冗余延迟逻辑:第一次迭代后的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 16:27:43