Bot.wait_for() 在我等待 "reaction_remove" 时无法正常工作
Bot.wait_for() doesn't work very properly when I wait it for "reaction_remove"
预期输出和我的代码是什么:
我的 bot 应该发送一条消息,然后检查是否有人对该消息做出了 :tada: 反应,如果有人反应了,它应该给该用户一个特定的角色,那部分工作正常,但是我还希望它检查用户是否 删除了 他们的反应,如果是,则删除该角色。
我把 role remover 和 role adder 放到它们自己的 async
协程函数中,
# Listening for reactions
await participation_message.add_reaction("")
reaction_check = lambda reaction, user: str(reaction.emoji) == "" and reaction.message.id == participation_message.id # In case you might be wondering, participation_message is a discord.Message that I send before this code block
async def remove_participants_loop():
while True:
try:
reaction, user = await self.client.wait_for('reaction_remove', timeout=60, check=reaction_check)
try:
await user.remove_roles(participant_role)
except Exception as e:
console_log("Error in removing participant role from user: {}".format(e), "white", "on_red")
except TimeoutError:
break
async def add_participants_loop(timeout=delete_after*60):
while True:
try:
reaction, user = await self.client.wait_for('reaction_add', timeout=60, check=reaction_check)
try:
await user.add_roles(participant_role)
except Exception as e:
console_log("Error in adding participant role to user: {}".format(e), "white", "on_red")
except TimeoutError:
break
我将它们放入自己的协程中,因为我需要它们都异步 运行,为此我现在做
asyncio.create_task(add_participants_loop())
asyncio.create_task(remove_participants_loop())
问题:
这适用于 add_participants_loop()
但不适用于 remove_participants_loop()
,我尝试使用断点对其进行调试,发现 remove_participants_loop
确实 运行 正确,但是当它等待 "reaction_remove"
时,当我删除我的反应时它没有检测到它,并继续等待并最终引发 asyncio.TimoutError
.
我试过:
- 阅读文档,函数
wait_for()
的 documentation 指出,“事件 (str) – 事件名称,类似于事件引用,但没有 on_ 前缀,以等待。”,并且事件参考显示正确的术语确实是“reaction_remove”而不是其他任何东西
- 正在检查拼写错误
- 确保 Bot.Intent.reactions == True
- 确保我有最新版本的 discord.py 模块
- 断点调试如上。
- 考虑到我的理智,在所有这一切之后,这个问题最终只是我错过的一些愚蠢的拼写错误。
- 确保我的机器人拥有其在 discord 中角色所需的所有权限
我认为wait_for
只能处理“消息”和“reaction_add”,不能处理“reaction_remove”。
在 issue on the discord.py Github Repository 中表示:
this requires the message cache and for the message to be there. It also requires member cache since discord does not provide this event with member data.
它还指出
If you want to get event without this limitation then use the on_raw_reaction_remove
event.
因此,reaction_remove
事件因缺少缓存而无法运行。因此,这里应该使用 raw_reaction_remove
,因为它不受此限制的约束,并且它 returns 是一个有效负载 discord.RawReactionActionEvent 对象,而不是标准的用户和反应,然后可以是用于获取用户和反应。
因此,现在的 lambda 检查类似于:
lambda payload: str(payload.emoji) == "" and payload.message_id == participation_message.id
将其放入 wait_for 协程中,
payload = await self.client.wait_for('raw_reaction_remove', timeout=timeout, check=lambda payload: str(payload.emoji) == "" and payload.message_id == participation_message.id)
# And then the User/Member who removed the Reaction can
# Be obtained by the user_id in the returned payload
user = self.client.get_guild(payload.guild_id).get_member(payload.user_id)
总结:
预期输出和我的代码是什么:
我的 bot 应该发送一条消息,然后检查是否有人对该消息做出了 :tada: 反应,如果有人反应了,它应该给该用户一个特定的角色,那部分工作正常,但是我还希望它检查用户是否 删除了 他们的反应,如果是,则删除该角色。
我把 role remover 和 role adder 放到它们自己的 async
协程函数中,
# Listening for reactions
await participation_message.add_reaction("")
reaction_check = lambda reaction, user: str(reaction.emoji) == "" and reaction.message.id == participation_message.id # In case you might be wondering, participation_message is a discord.Message that I send before this code block
async def remove_participants_loop():
while True:
try:
reaction, user = await self.client.wait_for('reaction_remove', timeout=60, check=reaction_check)
try:
await user.remove_roles(participant_role)
except Exception as e:
console_log("Error in removing participant role from user: {}".format(e), "white", "on_red")
except TimeoutError:
break
async def add_participants_loop(timeout=delete_after*60):
while True:
try:
reaction, user = await self.client.wait_for('reaction_add', timeout=60, check=reaction_check)
try:
await user.add_roles(participant_role)
except Exception as e:
console_log("Error in adding participant role to user: {}".format(e), "white", "on_red")
except TimeoutError:
break
我将它们放入自己的协程中,因为我需要它们都异步 运行,为此我现在做
asyncio.create_task(add_participants_loop())
asyncio.create_task(remove_participants_loop())
问题:
这适用于 add_participants_loop()
但不适用于 remove_participants_loop()
,我尝试使用断点对其进行调试,发现 remove_participants_loop
确实 运行 正确,但是当它等待 "reaction_remove"
时,当我删除我的反应时它没有检测到它,并继续等待并最终引发 asyncio.TimoutError
.
我试过:
- 阅读文档,函数
wait_for()
的 documentation 指出,“事件 (str) – 事件名称,类似于事件引用,但没有 on_ 前缀,以等待。”,并且事件参考显示正确的术语确实是“reaction_remove”而不是其他任何东西 - 正在检查拼写错误
- 确保 Bot.Intent.reactions == True
- 确保我有最新版本的 discord.py 模块
- 断点调试如上。
- 考虑到我的理智,在所有这一切之后,这个问题最终只是我错过的一些愚蠢的拼写错误。
- 确保我的机器人拥有其在 discord 中角色所需的所有权限
我认为wait_for
只能处理“消息”和“reaction_add”,不能处理“reaction_remove”。
在 issue on the discord.py Github Repository 中表示:
this requires the message cache and for the message to be there. It also requires member cache since discord does not provide this event with member data.
它还指出
If you want to get event without this limitation then use the
on_raw_reaction_remove
event.
因此,reaction_remove
事件因缺少缓存而无法运行。因此,这里应该使用 raw_reaction_remove
,因为它不受此限制的约束,并且它 returns 是一个有效负载 discord.RawReactionActionEvent 对象,而不是标准的用户和反应,然后可以是用于获取用户和反应。
因此,现在的 lambda 检查类似于:
lambda payload: str(payload.emoji) == "" and payload.message_id == participation_message.id
将其放入 wait_for 协程中,
payload = await self.client.wait_for('raw_reaction_remove', timeout=timeout, check=lambda payload: str(payload.emoji) == "" and payload.message_id == participation_message.id)
# And then the User/Member who removed the Reaction can
# Be obtained by the user_id in the returned payload
user = self.client.get_guild(payload.guild_id).get_member(payload.user_id)