Discord.py实现基于用户反应修改消息及相关功能求助
问题解决:Discord机器人反应处理与消息编辑功能实现
需求回顾
我开发了一个Discord机器人,当检测到消息中的'ping'词汇时,会在指定频道发送'pong!'消息并添加三个自定义表情反应(blue、red、yellow)。现在需要实现以下功能:
- 用户添加反应后,机器人编辑消息,追加该用户的操作记录(如“{用户} said blue pong!”);
- 移除用户添加的反应,保留机器人的三个初始反应;
- 30分钟后自动移除所有反应。
但我无法完成on_raw_reaction_add事件的逻辑实现,现有代码如下:
blue = '<:blue:1033370324135333898>' red = '<:red:1033370379663704148>' yellow = '<:yellow:1033370423078952970>' @client.event async def on_message(message): if 'ping' in message.content.lower(): if message.channel.id == 1032275628470308895: channel = client.get_channel(1032275628470308895) react = await channel.send('pong!') await react.add_reaction(blue) await react.add_reaction(red) await react.add_reaction(yellow) @client.event async def on_raw_reaction_add(payload): # and then I don't know what to do, everything I've tried doesn't work # I wanted to modify the message to (for example "{user} said blue pong!" and remove the reaction the user just use, and just keep the 3 from the bot) # And then if another user use the yellow reaction, the bot modify his message to for example "{user] said yellow pong!" # That could be great if the message was edited but keeping what was said before (in that case "pong! \n{user} said blue pong! \n{user} said yellow pong!") # And last thing, if possible I want the bot to remove all reactions including his after 30mins
完整实现代码
import discord from discord.ext import commands import asyncio # 初始化客户端,必须开启对应权限 intents = discord.Intents.default() intents.message_content = True intents.reactions = True client = commands.Bot(command_prefix='!', intents=intents) # 自定义表情ID与名称映射,方便后续判断 EMOJI_MAP = { 1033370324135333898: 'blue', 1033370379663704148: 'red', 1033370423078952970: 'yellow' } # 指定目标频道ID TARGET_CHANNEL_ID = 1032275628470308895 @client.event async def on_ready(): print(f'已登录:{client.user}') @client.event async def on_message(message): # 忽略机器人自身发送的消息 if message.author == client.user: return # 只处理目标频道的ping消息 if 'ping' in message.content.lower() and message.channel.id == TARGET_CHANNEL_ID: pong_msg = await message.channel.send('pong!') # 批量添加预设反应 for emoji_id in EMOJI_MAP.keys(): emoji = client.get_emoji(emoji_id) if emoji: await pong_msg.add_reaction(emoji) # 启动30分钟后清除所有反应的异步任务 asyncio.create_task(clear_reactions_after_delay(pong_msg, 1800)) async def clear_reactions_after_delay(message, delay_sec): await asyncio.sleep(delay_sec) try: await message.clear_reactions() except discord.errors.NotFound: # 消息已被删除,直接跳过 pass @client.event async def on_raw_reaction_add(payload): # 过滤机器人自己的反应 if payload.user_id == client.user.id: return # 只处理目标频道的消息 if payload.channel_id != TARGET_CHANNEL_ID: return # 提取表情ID(自定义表情是整数,普通表情是字符串) emoji_id = payload.emoji.id if payload.emoji.id else payload.emoji.name # 只处理我们预设的三个表情 if emoji_id not in EMOJI_MAP: return try: # 获取消息和用户对象 channel = client.get_channel(payload.channel_id) message = await channel.fetch_message(payload.message_id) user = client.get_user(payload.user_id) or await client.fetch_user(payload.user_id) # 构建追加内容并编辑消息 emoji_name = EMOJI_MAP[emoji_id] new_content = f"{message.content}\n{user.display_name} said {emoji_name} pong!" await message.edit(content=new_content) # 移除用户添加的这个反应 await message.remove_reaction(payload.emoji, user) except discord.errors.NotFound: # 消息或用户不存在,忽略错误 pass except discord.errors.Forbidden: print("机器人没有编辑消息或移除反应的权限,请检查权限设置") # 替换成你的机器人Token client.run('YOUR_BOT_TOKEN')
关键逻辑说明
- 权限配置:必须开启
message_content和reactions权限,否则机器人无法读取消息内容和监听反应事件。 - 表情映射:用字典存储表情ID和对应名称,快速判断用户点击的目标表情。
- 自动清除反应:发送pong消息后启动异步任务,等待30分钟后清除所有反应,不阻塞其他操作。
- 反应事件处理:
- 先过滤机器人自身的反应和非目标频道的消息;
- 验证反应是否属于预设的三个表情;
- 编辑消息追加用户操作记录;
- 移除用户添加的反应,保留机器人初始的三个反应。
内容的提问来源于stack exchange,提问作者Sha_do
相关产品推荐
相关产品推荐

