【问题标题】:Bot.wait_for() doesn't work very properly when I wait it for "reaction_remove"当我等待“reaction_remove”时,Bot.wait_for() 不能正常工作
【发布时间】:2021-03-17 23:18:30
【问题描述】:

预期的输出和我的代码是什么:

我的机器人应该发送一条消息,然后检查是否有人用 :tada: 对该消息作出反应,如果有人这样做了,它应该给那个用户一个特定的角色,这部分工作正常,但我也希望它检查用户是否删除他们的反应,如果是,则删除该角色。 我把角色移除器和角色添加器放到自己的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 声明,“event (str) – 事件名称,类似于事件引用,但没有 on_ 前缀,等待。”,和事件参考表明正确的术语确实是“reaction_remove”而不是其他任何东西
  • 检查拼写错误
  • 确保 Bot.Intent.reactions == True
  • 确保我拥有最新版本的 discord.py 模块
  • 如上所述使用断点进行调试。
  • 考虑到我的理智,毕竟这个问题只是我错过的一些愚蠢的错字。
  • 确保我的机器人在不和谐中拥有其角色所需的所有权限

【问题讨论】:

  • 我能想到的唯一问题是支票。你调试过str(reaction.emoji) == "????" 吗?

标签: python discord python-asyncio discord.py-rewrite


【解决方案1】:

我认为wait_for 只能处理“message”和“reaction_add”,不能处理“reaction_remove”。

【讨论】:

    【解决方案2】:

    discord.py Github Repository 上的issue 中声明:

    这需要消息缓存并且消息存在。它还需要成员缓存,因为 discord 不向此事件提供成员数据。

    它还指出

    如果您想获得不受此限制的事件,请使用on_raw_reaction_remove 事件。

    因此,reaction_remove 事件由于缺少缓存而不起作用。因此这里应该使用raw_reaction_remove,因为它不受此限制的约束,它返回一个有效负载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.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-07
      相关资源
      最近更新 更多