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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 15:54:05