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

discord.py on_message_edit事件随机误触发问题排查

问题根因
  • 误触发核心来源:Discord的on_message_edit事件不是只有用户手动修改消息文本才会触发。消息附带的链接预览加载完成、消息系统标记(flag)更新、附件状态变更等不改动content字段的元数据更新,都会触发该事件。初始监听代码没有做内容一致性校验,事件触发就发提示,必然出现前后文本完全一致的误报。
  • 运行方式错误:将两个功能拆分到不同文件,同时启动两个独立进程、用同一个bot令牌连接Discord网关,会导致事件被重复广播、投递顺序混乱,进一步提升随机误触发概率,Discord官方不允许同一bot账号无意义建立多个网关连接。
  • 之前修复代码的具体错误:
    • 事件注册逻辑完全错误:把on_message_edit的装饰器注册写在on_message事件的判断分支内部,会导致事件被重复注册,触发次数随消息接收量持续递增,逻辑完全不可控。
    • 过滤规则无效:id = id是无意义的自赋值,且直接将message.author(用户/成员对象)和整数ID做等值比较属于类型不匹配,根本无法命中过滤规则;也没有做bot账号的通用过滤,bot自身发消息触发的事件也会被处理。
    • 指令逻辑失效:自定义on_message事件后没有调用await bot.process_commands(message),所有前缀指令都无法正常响应。
    • 存在未定义变量:修复代码中channel = bot.get_channel(channel)的传入参数channel从未被赋值,运行到该行会直接抛出名称错误。
    • 之前遇到的unresolved reference报错,本质是变量作用域错误,对应位置没有正确定义/引入author相关变量。
修复步骤
  1. 合并两个功能到同一个bot实例,禁止拆分多文件启动多个进程用同一令牌登录,从根源避免多连接导致的事件混乱。
  2. 在on_message_edit事件最前端增加两层强制过滤:
    • 消息发送者为bot(包括当前bot自身)时直接return,不处理任何bot账号触发的消息编辑事件
    • 编辑前后content字段完全一致时直接return,过滤所有非文本修改触发的无效事件,这是解决误报的核心逻辑
  3. 所有事件注册统一放在代码顶层,禁止嵌套在其他函数/事件逻辑内部。
  4. 若需要自定义on_message全局消息处理逻辑,必须在逻辑末尾添加await bot.process_commands(message),保证前缀指令能正常被识别执行。
修复后参考代码
import discord
from discord.ext import commands
from googlesearch import search # 对应你使用的谷歌搜索依赖库

# 两个功能共用同一个bot实例,注意提前在开发者后台开启相关权限意图
bot = commands.Bot(command_prefix='!', intents=discord.Intents.all())

@bot.event
async def on_message_edit(before, after):
    # 过滤bot账号的消息编辑事件
    if after.author.bot:
        return
    # 过滤内容无实际变化的编辑事件
    if before.content == after.content:
        return
    
    # 正常编辑提示逻辑
    embed = discord.Embed(
        timestamp=after.created_at,
        description = f"<@!{before.author.id}>**的消息在** <#{before.channel.id}>**被编辑**",
        colour = discord.Colour(0x00FF00)
    )
    embed.set_author(name=f'{before.author.name}#{before.author.discriminator}', icon_url=before.author.avatar.url)
    embed.set_footer(text=f"作者ID:{before.author.id} • 消息ID: {before.id}")
    embed.add_field(name='编辑前:', value=before.content + "\u200b", inline=False)
    embed.add_field(name="编辑后:", value=after.content + "\u200b", inline=False)
    # 直接用消息所在频道发送,不需要硬编码频道ID调用get_channel
    await before.channel.send(embed=embed)

@bot.command()
async def question(ctx,*, query):
    author = ctx.author.mention
    await ctx.send(f"这是和你的问题相关的链接 {author} !")
    async with ctx.typing():
        for j in search(query, tld="co.in", num=1, stop=1, pause=1):
            await ctx.send(f"\n {j}")

# 无特殊全局消息处理需求可以删掉整个on_message事件,bot默认会自动处理指令
@bot.event
async def on_message(message):
    # 在此处编写自定义全局消息处理逻辑
    await bot.process_commands(message) # 该行必须保留,否则指令无法响应

bot.run('替换为你的bot令牌')

前置配置提醒:需要提前在Discord开发者后台对应Bot的设置页,开启「Message Content Intent」开关,否则bot无法接收消息正文内容,编辑事件也拿不到content字段,功能会完全失效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 15:48:16