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

Discord.py开发删除消息日志BOT时获取删除执行人问题求解

问题原因分析

  • 代码逻辑存在多处错误:
    1. 变量deletionLog初始化位置错误,放在循环内部会导致每次遍历审计日志条目时都重置为None,只有最后一条匹配的条目才会被保留,大概率匹配不到有效记录
    2. 时间戳对比逻辑完全错误:你用消息的创建时间和审计日志的删除操作时间做对比,自然会出现几百上千秒的差值,应该对比的是删除操作发生时间和on_message_delete事件触发的近似时间
    3. 仅匹配entry.target.id == message.author.id逻辑太粗糙,同一时间如果有多个该用户的消息被删除,会匹配到错误的记录

可行解决方案

  1. 先确认Bot已经被授予查看审计日志的服务器权限,没有这个权限拉取的审计日志内容会缺失
  2. 拉取审计日志时按最新时间排序,先初始化deletionLog为None再进入循环
  3. 时间对比改为用审计日志条目的创建时间和事件触发的当前时间做差值,同时利用审计日志extra字段的频道信息做二次匹配,提高准确率
  4. 增加2-3秒的延迟再拉取审计日志,避免Discord侧审计日志还未同步的问题,延迟要加在拉取审计日志之前才会生效

优化后代码示例

import discord
import os
from datetime import datetime
import asyncio

intents = discord.Intents.all()
client = discord.Client(intents=intents)

# 原有create_embed实现逻辑可保留不变,这里做示例补充
def create_embed(discord, message, executor):
    embed = discord.Embed(title="消息被删除", color=discord.Color.red())
    embed.add_field(name="消息作者", value=message.author.mention, inline=False)
    embed.add_field(name="消息内容", value=message.content if message.content else "无文本内容", inline=False)
    if executor:
        embed.add_field(name="删除执行人", value=executor.mention, inline=False)
    else:
        embed.add_field(name="删除执行人", value="消息作者本人", inline=False)
    embed.timestamp = datetime.utcnow()
    return embed

@client.event
async def on_message_delete(message):
    if not message or not message.guild:
        return
    # 加2秒延迟等待Discord审计日志同步
    await asyncio.sleep(2)
    deletion_log = None
    # 拉取最近5条消息删除的审计日志,按时间倒序(最新的在前)
    async for entry in message.guild.audit_logs(limit=5, action=discord.AuditLogAction.message_delete, oldest_first=False):
        # 匹配条件:1. 操作目标是消息作者 2. 操作时间距当前事件触发不超过20秒 3. 删除操作的频道和消息所在频道一致
        if (entry.target.id == message.author.id 
            and abs((datetime.utcnow() - entry.created_at).total_seconds()) < 20
            and entry.extra.get("channel", {}).id == message.channel.id):
            deletion_log = entry
            # 匹配到就跳出循环,不需要继续遍历
            break

    executor = deletion_log.user if deletion_log else None
    embed = create_embed(discord, message, executor)
    await message.channel.send(embed=embed)

client.run(os.environ['TOKEN'])

额外优化建议

  • 不要将删除日志发送到原消息所在频道,建议配置专门的日志频道发送,避免干扰正常聊天
  • 可以增加消息附件、贴纸、回复信息的记录逻辑,完善日志内容
  • 如果是高频删除的服务器,可以适当提高拉取审计日志的limit数值,避免漏匹配

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 01:57:04