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

Discord投票机器人on_reaction_add事件访问async函数变量报错如何解决

问题原因
  • 你代码里的new_poll是被@bot.command装饰器包装后的Discord命令对象,而非普通函数,你在new_poll函数内部定义的tv_embed、message都属于函数运行时的局部变量,函数执行完毕后就会被回收,本身也不属于Command对象的属性,所以直接访问new_poll.tv_embed必然会触发AttributeError。
  • 除此之外你原来的new_poll里计算总票数的逻辑只会在创建投票时执行一次,本身就没有和后续的用户反应事件做联动。
修复方案
  1. 首先定义一个全局缓存字典,用来存储所有有效投票消息的关联数据:
# 全局缓存,key为投票消息的id,value存储对应需要的参数
poll_cache = {}
  1. 修改new_poll命令,创建投票后把消息ID和对应参数存入缓存:
@bot.command(name="newpoll")
async def new_poll(ctx, question, *options):
    if len(options) > 12:
        await ctx.send("You can have a maximum of 12 choices in your poll")
    else:
        embed = discord.Embed(title = "Poll",
                              description = question,
                              colour = discord.Colour.red())
        fields = [("Options", "\n".join([f"{emotes[idx]} {option}" for idx, option in enumerate(options)]), False),
                  ("Instructions", "Please react in order to vote!", False)]
        for name, value, inline in fields:
            embed.add_field(name = name, value = value, inline = inline)
        embed.add_field(name = "Total votes", value = 0, inline = False)
        message = await ctx.send(embed = embed)
        for emoji in emotes[:len(options)]:
            await message.add_reaction(emoji)
        # 把投票消息id和选项数量存入缓存,方便后续事件里调用
        poll_cache[message.id] = {
            "option_count": len(options)
        }
  1. 修改on_reaction_add事件,先判断是否是投票消息,再更新票数:
@bot.event
async def on_reaction_add(reaction, user):
    # 忽略机器人自己的反应
    if user.bot:
        return
    # 检查触发反应的消息是不是已创建的投票消息
    if reaction.message.id not in poll_cache:
        return
    # 获取当前投票的选项数量
    option_count = poll_cache[reaction.message.id]["option_count"]
    # 计算总票数:所有反应数之和减去机器人自己加的初始反应数
    total_votes = sum(r.count for r in reaction.message.reactions) - option_count
    # 更新embed的总票数字段
    new_embed = reaction.message.embeds[0]
    new_embed.set_field_at(2, name="Total votes", value=total_votes, inline=False)
    await reaction.message.edit(embed=new_embed)
补充说明
  • 如果机器人重启,缓存里的投票数据会丢失,如果你需要持久化支持,可以把缓存数据存在数据库或者本地文件里。
  • 建议同步处理on_reaction_remove事件,用户取消投票时也同步更新总票数。

内容的提问来源于stack exchange,提问作者iktefish

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 12:00:06