discord.py中如何实现移除表情反应时编辑消息的功能?
问题修复方案
核心问题原因
- 事件回调中未绑定目标
message对象:你当前代码里的message是全局未定义状态,两个事件触发时无法找到要编辑的目标消息,自然没有响应 on_reaction_remove默认缓存限制:discord.py的普通反应事件仅对客户端启动后收到的、位于内部消息缓存中的消息生效,超出缓存的消息移除反应不会触发该事件- 没有做反应与消息的对应校验:现在的逻辑只要有反应触发就会尝试编辑,会出现跨消息错误
修复步骤
第一步:启用必要的机器人意图
初始化机器人时开启反应和消息内容权限,避免事件被拦截。
第二步:改用原始反应事件
on_raw_reaction_add和on_raw_reaction_remove不受消息缓存限制,重启前发送的消息也能正常触发事件。
第三步:绑定目标消息ID
发送初始embed的命令中存储消息ID,确保事件仅处理对应的目标消息。
完整可运行代码示例
import discord from discord.ext import commands # 开启所需权限意图 intents = discord.Intents.default() intents.message_content = True intents.reactions = True client = commands.Bot(command_prefix="!", intents=intents) # 替换为你自己的表情,Unicode表情直接写符号,自定义表情填ID NG = "✅" EE = "⚠️" SD = "❌" DD = "🎉" # 存储目标消息ID,支持多条消息可改为字典结构 target_message_id = None # 替换为你自己的5个embed定义 embed0 = discord.Embed(title="初始页", description="这是初始embed") embed1 = discord.Embed(title="页1", description="对应NG表情") embed2 = discord.Embed(title="页2", description="对应EE表情") embed3 = discord.Embed(title="页3", description="对应SD表情") embed4 = discord.Embed(title="页4", description="对应DD表情") # 发送初始embed的命令 @client.command() async def show_pages(ctx): global target_message_id msg = await ctx.send(embed=embed0) # 提前添加预设反应 await msg.add_reaction(NG) await msg.add_reaction(EE) await msg.add_reaction(SD) await msg.add_reaction(DD) # 存储目标消息ID target_message_id = msg.id # 反应添加事件 @client.event async def on_raw_reaction_add(payload): # 过滤机器人自己的反应 if payload.user_id == client.user.id: return # 只处理目标消息的反应 if payload.message_id != target_message_id: return # 获取消息对象 channel = await client.fetch_channel(payload.channel_id) message = await channel.fetch_message(payload.message_id) # 按表情切换embed if payload.emoji.name == NG: await message.edit(embed=embed1) elif payload.emoji.name == EE: await message.edit(embed=embed2) elif payload.emoji.name == SD: await message.edit(embed=embed3) elif payload.emoji.name == DD: await message.edit(embed=embed4) # 反应移除事件 @client.event async def on_raw_reaction_remove(payload): # 过滤机器人自己的反应 if payload.user_id == client.user.id: return # 只处理目标消息的反应 if payload.message_id != target_message_id: return # 获取消息对象 channel = await client.fetch_channel(payload.channel_id) message = await channel.fetch_message(payload.message_id) # 切回初始embed await message.edit(embed=embed0) client.run("你的机器人Token")
补充注意事项
- 如果你使用的是自定义服务器表情,判断条件需要替换为
payload.emoji.id == 你的表情ID,不要用name判断 - 若需要支持多条独立的embed切换消息,可将
target_message_id替换为字典结构,存储每条消息的对应状态 - 如果需要处理多用户同时加反应的场景,可额外统计当前消息剩余的用户反应,判断是否需要切回初始embed,避免移除其中一个反应就直接跳转
内容的提问来源于stack exchange,提问作者Chinelo
相关产品推荐
相关产品推荐

