
本文详解如何使用 discord.py 实现消息删除和编辑的完整日志功能,包括自动捕获被删消息内容、编辑前后的文本对比,并统一发送至指定日志频道,适用于服务器管理类 bot 开发。
本文详解如何使用 discord.py 实现消息删除和编辑的完整日志功能,包括自动捕获被删消息内容、编辑前后的文本对比,并统一发送至指定日志频道,适用于服务器管理类 bot 开发。
要构建一个专业级的 Discord 服务器日志系统,仅记录消息删除是不够的——编辑行为同样关键,尤其是当用户试图掩盖不当内容时。on_message_delete 已能稳定捕获原始消息,而 on_message_edit 则需特别注意其函数签名:它接收两个参数——before(编辑前的 Message 对象)和 after(编辑后的 Message 对象),二者均包含 .content、.author、.channel 等关键属性,但仅当内容实际发生变化时才会触发该事件(例如纯格式调整如嵌入更新或附件增减不会触发,除非 .content 改变)。
以下是完整的日志实现代码(兼容 Cog 结构):
@commands.Cog.listener()
async def on_message_delete(self, message: discord.Message):
# 跳过机器人自身消息及空内容(可选)
if not message.content or message.author.bot:
return
embed = discord.Embed(
title="?️ Message Deleted",
color=0xe74c3c,
timestamp=message.created_at
)
embed.add_field(name="Author", value=f"{message.author.mention} (`{message.author}`)", inline=False)
embed.add_field(name="Channel", value=message.channel.mention, inline=False)
embed.add_field(name="Content", value=message.content[:1024] or "(empty)", inline=False)
if len(message.content) > 1024:
embed.add_field(name="Content (continued)", value=message.content[1024:2048], inline=False)
log_channel = discord.utils.get(message.guild.channels, name="logging")
if log_channel:
await log_channel.send(embed=embed)
@commands.Cog.listener()
async def on_message_edit(self, before: discord.Message, after: discord.Message):
# 忽略编辑前后内容一致的情况(防冗余触发)
if before.content == after.content:
return
# 跳过机器人消息和系统消息(如慢模式提示)
if before.author.bot or not before.content.strip():
return
embed = discord.Embed(
title="✏️ Message Edited",
color=0xf39c12,
timestamp=after.edited_at or after.created_at
)
embed.add_field(name="Author", value=f"{before.author.mention} (`{before.author}`)", inline=False)
embed.add_field(name="Channel", value=before.channel.mention, inline=False)
embed.add_field(name="Before Edit", value=before.content[:1024] or "(empty)", inline=False)
if len(before.content) > 1024:
embed.add_field(name="Before (continued)", value=before.content[1024:2048], inline=False)
embed.add_field(name="After Edit", value=after.content[:1024] or "(empty)", inline=False)
if len(after.content) > 1024:
embed.add_field(name="After (continued)", value=after.content[1024:2048], inline=False)
log_channel = discord.utils.get(before.guild.channels, name="logging")
if log_channel:
await log_channel.send(embed=embed)
✅ 关键注意事项:
- 日志频道名 "logging" 需确保在目标服务器中存在且 Bot 拥有读写权限;建议通过配置文件或数据库动态读取频道 ID,避免硬编码;
- 使用 before.content == after.content 过滤可防止因时间戳更新等非内容变更导致的误触发;
- Discord 对 embed 字段长度有限制(单字段 ≤ 1024 字符),因此对长消息做了分段处理;
- edited_at 可能为 None(未编辑过),故回退至 created_at 保证时间戳始终有效;
- 若需记录附件、嵌入(Embed)或提及变化,需额外扩展逻辑(如比对 before.attachments / after.attachments)。
通过以上实现,管理员可在日志频道中清晰追溯每一条被删/被改消息的上下文,显著提升服务器内容治理能力与审计可靠性。











