如何在discord.py中通过wait_for监听reaction_remove事件获取触发用户?
问题原因
client.wait_for()的事件名参数不需要带on_前缀,你填写的on_reaction_remove是事件回调函数的命名规则,监听移除反应的正确事件名是reaction_remove。- 原有的串行监听逻辑只能捕获加反应事件,无法同时处理加、删两种反应触发场景。
实现方案
你可以用asyncio.wait同时监听两种反应事件,谁先触发就先处理谁,同时建议在校验规则中限定仅处理你刚发送的embed消息的反应,避免其他消息的同表情反应干扰逻辑。
完整示例代码如下:
import asyncio import discord from discord.ext import commands intents = discord.Intents.all() client = commands.Bot(command_prefix='!', intents=intents) @client.command() async def test(ctx): emoji_yes = "✅" reacted_users = [] # 构建并发送embed,保存消息对象 test_embed = discord.Embed(title="反应测试", description="已同意用户:无") msg = await ctx.send(embed=test_embed) # 给消息添加初始表情 await msg.add_reaction(emoji_yes) # 校验规则:仅匹配目标消息、指定表情、非bot自身的操作 def check(reaction, user): return ( reaction.message.id == msg.id and str(reaction.emoji) == emoji_yes and user != client.user ) while True: # 同时创建两个监听任务 add_task = asyncio.create_task(client.wait_for('reaction_add', check=check)) remove_task = asyncio.create_task(client.wait_for('reaction_remove', check=check)) # 等待任意一个任务触发 done, pending = await asyncio.wait( [add_task, remove_task], return_when=asyncio.FIRST_COMPLETED ) # 取消未触发的任务,避免内存泄漏 for task in pending: task.cancel() # 处理触发的事件 if add_task in done: reaction, user = add_task.result() if user not in reacted_users: reacted_users.append(user) else: reaction, user = remove_task.result() if user in reacted_users: reacted_users.remove(user) # 更新embed内容 user_list = "、".join([u.name for u in reacted_users]) if reacted_users else "无" new_embed = discord.Embed(title="反应测试", description=f"已同意用户:{user_list}") await msg.edit(embed=new_embed)
注意事项
- 你已经开启了
Intents.all(),所以反应事件的权限是足够的,如果后续调整权限配置,需要确保intents.reactions = True处于开启状态。 - 该场景下你是监听刚发送的消息,消息必然在bot的缓存中,不需要用到raw系列事件,普通反应事件即可正常触发。
内容的提问来源于stack exchange,提问作者DragonInTraining
相关产品推荐
相关产品推荐

