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只能处理“消息”和“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)

总结:

As documented 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 raw_reaction_remove event.