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

Discord机器人重复发送消息与日志问题排查及修复请求

Discord机器人重复发送私信与重复记录反应日志的问题修复

问题原因

1. 重复发送私信

  • 未启用Discord.py核心意图:v2.x版本后,必须显式开启成员意图(Members Intent)和消息内容意图(Message Content Intent),才能正常获取服务器成员列表、解析命令文本。缺少这些意图会导致ctx.guild.members返回的成员列表异常(如重复加载同一成员),进而在循环中重复发送私信。
  • 无发送记录去重机制:未记录已发送的成员ID,极端情况下可能因缓存重复触发重复发送。

2. 重复记录反应日志

  • 事件重复触发无过滤:Discord偶尔会重复发送同一反应事件,原代码未对反应做唯一标识去重,导致重复记录。
  • 变量覆盖逻辑冗余:原代码中先获取用户对象判断是否为机器人,随后又重新赋值成员变量,虽不影响核心逻辑,但增加了不必要的资源消耗。

修复后的完整代码

import discord
from discord.ext import commands
from collections import defaultdict

# 配置Discord机器人核心意图
intents = discord.Intents.default()
intents.members = True  # 启用成员意图,用于获取服务器成员列表
intents.message_content = True  # 启用消息内容意图,用于处理命令文本

bot = commands.Bot(command_prefix="!", intents=intents)

allowed_role_id = 1234567890  # 替换为你有权限执行命令的角色ID
sent_member_ids = set()  # 记录已发送私信的成员ID,避免重复发送
processed_reactions = defaultdict(set)  # 记录已处理的反应,格式:(用户ID, 表情名称)

@bot.event
async def on_ready():
    print(f'已登录为 {bot.user} (ID: {bot.user.id})')
    sent_member_ids.clear()
    processed_reactions.clear()

@bot.command(name='sendmessage')
@commands.has_role(allowed_role_id)
async def send_message(ctx, *, message: str):
    sent_member_ids.clear()  # 每次执行命令时重置发送记录
    for member in ctx.guild.members:
        # 跳过机器人和已发送过消息的成员
        if member.bot or member.id in sent_member_ids:
            continue
        
        try:
            dm_channel = await member.create_dm()
            sent_msg = await dm_channel.send(message)
            # 添加反应
            await sent_msg.add_reaction("✅")
            await sent_msg.add_reaction("❌")
            await sent_msg.add_reaction("🟡")
            sent_member_ids.add(member.id)  # 标记为已发送
        except discord.Forbidden:
            print(f"无法给 {member.name} ({member.id}) 发私信:用户关闭了私信权限")
        except Exception as e:
            print(f"给 {member.name} 发私信时出错:{str(e)}")

@bot.event
async def on_raw_reaction_add(payload):
    # 过滤机器人自己的反应
    if payload.user_id == bot.user.id:
        return
    
    # 生成唯一反应标识,避免重复处理
    reaction_key = (payload.user_id, payload.emoji.name)
    if reaction_key in processed_reactions[payload.message_id]:
        return
    processed_reactions[payload.message_id].add(reaction_key)

    # 获取目标服务器和成员信息
    target_guild = bot.get_guild(1077548297037819985)
    if not target_guild:
        print("无法获取目标服务器")
        return
    member = target_guild.get_member(payload.user_id)
    if not member:
        print(f"无法获取成员 {payload.user_id} 的信息")
        return

    # 验证消息是否为机器人发送的私信
    try:
        channel = bot.get_channel(payload.channel_id)
        if not channel:
            print(f"无法获取频道 {payload.channel_id}")
            return
        msg = await channel.fetch_message(payload.message_id)
        if msg.author != bot.user:
            return
    except Exception as e:
        print(f"获取消息时出错:{str(e)}")
        return

    # 发送反应日志
    log_channel = bot.get_channel(1095793300184764477)
    if not log_channel:
        print("无法找到日志频道")
        return

    embed = discord.Embed(title="反应日志", color=0x00ff00)
    embed.add_field(name="用户", value=f"{member.mention} ({member.id})", inline=True)
    embed.add_field(name="反应", value=payload.emoji.name, inline=True)
    embed.add_field(name="角色", value=" ".join([r.mention for r in member.roles]) if member.roles else "无角色", inline=False)
    embed.add_field(name="昵称", value=member.nick if member.nick else member.name, inline=True)
    embed.add_field(name="加入时间", value=member.joined_at.strftime("%Y-%m-%d %H:%M:%S") if member.joined_at else "未知", inline=True)
    await log_channel.send(embed=embed)

# 替换为你的机器人Token
bot.run("YOUR_BOT_TOKEN")

关键修复点

  1. 意图配置:添加members和message_content意图,确保机器人能正常获取成员列表、解析命令,从根源解决成员重复加载的问题。
  2. 私信去重:用sent_member_ids集合记录已发送的成员ID,循环时跳过已发送对象,避免重复私信。同时增加异常捕获,处理无法发送私信的场景。
  3. 反应日志去重:用processed_reactions字典记录已处理的反应,以消息ID+用户ID+表情为唯一标识,重复事件直接跳过。
  4. 逻辑优化:简化机器人反应判断逻辑,增加空值检查和异常处理,提升代码稳定性和容错性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 17:24:54