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

如何解决Discord.py机器人因用户反应重复发送消息的问题?

问题分析与解决方案

你的机器人重复发送消息的核心原因是:每次收到用户消息时都会启动一个独立的wait_for('reaction_add')监听,而这些监听的判断条件没有限定对应消息。当用户对某条消息添加反应时,所有正在等待的wait_for都会触发,导致多次发送结果Embed。

另外代码里还有几个细节问题会引发异常或逻辑错误,一起修复:

修复步骤

  1. 限定反应对应的目标消息
    在check函数中添加判断,确保只响应刚才机器人添加反应的那条消息的反应,避免所有等待中的监听同时触发。

  2. 修正频道ID类型
    bot.get_channel()需要传入整数类型的频道ID,不能是字符串,否则会获取不到频道。

  3. 避免变量名冲突
    历史消息列表推导式里的变量名不要和on_message的参数message重名,否则会覆盖外部变量。

  4. 规范异步调用写法
    add_reaction是异步方法,需要正确await,不要直接把协程对象赋值后再await。

修复后的代码

import asyncio
import random
import discord

@bot.listen('on_message')
async def on_message(message):
    if message.author == bot.user:
        return 
    
    # 频道ID改为整数
    channel = bot.get_channel(CHANNEL_ID)  # 替换成你的数字ID
    if not channel:
        return  # 防止获取不到频道引发后续错误
    
    # 变量名改为msg,避免和外部message冲突
    messages = [msg async for msg in channel.history(limit=15)]
    if len(messages) < 1:
        return  # 确保有消息可选择
    
    await asyncio.sleep(random.randint(0, 3))
    
    # 随机选一条消息并添加反应
    target_msg = messages[random.randint(0, len(messages)-1)]
    await target_msg.add_reaction("\N{Snowman}")
    
    def check(reaction, user):
        # 限定反应的消息是刚才添加反应的那条,同时判断表情和用户
        return (str(reaction.emoji) == '\N{Snowman}' 
                and user != bot.user 
                and reaction.message == target_msg)
    
    try:
        reaction, user = await bot.wait_for('reaction_add', timeout=30, check=check)
        embed = discord.Embed(description=f'{user.mention} 抢到雪人啦!', color=discord.Color.random())
        await channel.send(embed=embed)
    except asyncio.TimeoutError:
        pass

额外说明

  • 新增了if not channel:和if len(messages) <1:的判断,避免因为频道不存在或频道无消息导致的运行时错误。
  • 随机选消息时用len(messages)-1代替固定的14,防止频道历史消息不足15条时引发索引越界异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 08:20:29