discord.py离线/重启后,如何监听历史消息的on_message_edit事件?
问题解答
核心结论
discord.py 默认不会对机器人加入服务器前或离线期间发送的消息编辑触发on_message_edit,因为该事件依赖本地缓存中存储的消息原始副本做对比,而历史消息默认不会被加载到缓存中,且fetch_message()确实不会自动将消息存入内部缓存。
解决方案
1. 手动将目标消息加入缓存
机器人启动时,主动拉取需要监控的历史消息并手动添加到缓存,让后续的on_message_edit能正常触发:
async def preload_target_messages(guild_id, channel_id, target_msg_ids): guild = client.get_guild(guild_id) channel = guild.get_channel(channel_id) for msg_id in target_msg_ids: try: msg = await channel.fetch_message(msg_id) # 将消息手动加入缓存(discord.py v2.x 写法) client.cache.messages.add(msg) except discord.NotFound: print(f"消息 {msg_id} 不存在或无法获取") # 在机器人就绪时执行缓存预加载 @client.event async def on_ready(): # 替换为你的服务器ID、频道ID和需要监控的消息ID列表 await preload_target_messages(123456789, 987654321, [111222333, 444555666])
- 注意:discord.py v1.x 的缓存写法为
client.messages.add(msg),请根据实际版本调整。
2. 使用不依赖缓存的原始事件监听
直接使用on_raw_message_edit事件,它会接收Discord推送的所有消息编辑原始载荷,完全不依赖本地缓存,适合处理历史消息的编辑:
@client.event async def on_raw_message_edit(payload): # 从载荷中获取基础信息 channel_id = payload.channel_id msg_id = payload.message_id channel = client.get_channel(channel_id) if not channel: return try: # 获取编辑后的完整消息 new_msg = await channel.fetch_message(msg_id) # 从载荷中提取编辑前的旧数据(仅保留最近一次编辑记录) old_embed_data = payload.data.get('embeds') # 处理Embed更新逻辑 if new_msg.embeds: current_embed = new_msg.embeds[0] print(f"消息 {msg_id} 的Embed已更新:{current_embed.title}") # 如果需要对比旧Embed内容 if old_embed_data: old_embed = discord.Embed.from_dict(old_embed_data[0]) print(f"编辑前的Embed标题:{old_embed.title}") except discord.NotFound: print(f"无法获取消息 {msg_id}")
- 优势:无需提前缓存消息,能监听所有消息的编辑事件,包括机器人离线期间发生的编辑。
- 限制:Discord API仅保留最近一次的编辑记录,无法获取更早的历史版本;若需要完整的编辑轨迹,需自行在首次获取消息时保存初始状态,后续对比自己存储的版本。
3. 针对特定Embed消息的优化
如果仅需监控固定的Embed消息,可将这些消息的ID存储在配置文件或数据库中:
- 机器人启动时批量拉取并保存初始Embed状态
- 结合
on_raw_message_edit监听后续编辑,对比本地保存的初始状态获取更新数据
内容的提问来源于stack exchange,提问作者user24442827
相关产品推荐
相关产品推荐

