【问题标题】:Discord.py: Multiple multipage messagesDiscord.py:多个多页消息
【发布时间】:2021-04-14 14:29:23
【问题描述】:

编辑:

解决方案是在检查功能中添加一个附加条件,我已经在后续答案中发布了详细信息。

主要问题:

我是新的python,并决定通过创建一个不和谐的机器人来学习它。

根据用户命令,我能够让机器人发送一条消息,该消息可以按照这种设计更改页面:

I want to make a multi-page help command using discord.py

我可以很好地更改一条消息的页面,但是,如果用户多次调用该命令,对机器人发送的消息之一做出反应会更改所有未超时消息的页面。我可以在代码中进行哪些更改,以便对一条消息做出反应不会触发其他消息中的页面更改?

其他问题:

def check(reaction, user):
        return user == ctx.author and str(reaction.emoji) in ["◀️", "▶️"]
        # This makes sure nobody except the command sender can interact with the "menu"
  • 我知道wait_for会使用这个函数作为检查,但是检查参数是在哪里以及如何传入的呢?如果可能,如何添加更多参数?
reaction, user = await bot.wait_for("reaction_add", timeout=60, check=check)
  • 在文档中,我无法确定 wait_for 方法的返回值,看起来它在不同情况下会发生变化。
  • 我们没有将消息实例传递给 wait_for 方法,那么该方法如何知道要等待响应的消息?
  • 如果检查失败,程序流程会怎样?似乎只有当 check() 返回 true 时才会执行此行下的语句。但是当检查失败时会发生什么?

【问题讨论】:

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


    【解决方案1】:

    感谢 Łukasz Kwieciński 回答我的其他问题。因为我了解到 wait_for 等待对任何消息的任何反应,所以我在 check() 函数中添加了一个附加条件。现在每条消息都是相互独立的。

    message = await ctx.send(f"Page {cur_page}/{pages}:\n{contents[cur_page-1]}")
        # getting the message object for editing and reacting
    
    def check(reaction, user):
            if reaction.message != message:
                return false
                # SOLUTION: Checks if the message reacted on is the same as the one the bot sent
            
            return user == ctx.author and str(reaction.emoji) in ["◀️", "▶️"]
            # This makes sure nobody except the command sender can interact with the "menu"
    

    但是,此修复可能会导致性能问题。对于尚未超时的每条机器人消息,对服务器上的任何消息做出反应都会导致它多次运行 check()。

    【讨论】:

      【解决方案2】:

      比您提供的方法更好的替代方法是使用ext.menus(它处于测试阶段,所以它还没有任何文档,安装它python -m pip install -U git+https://github.com/Rapptz/discord-ext-menus

      例子

      from discord.ext import menus
      
      class MyMenu(menus.Menu):
          async def send_initial_message(self, ctx, channel):
              return await channel.send(f'Hello {ctx.author}')
      
          @menus.button('\N{THUMBS UP SIGN}')
          async def on_thumbs_up(self, payload):
              await self.message.edit(content=f'Thanks {self.ctx.author}!')
      
          @menus.button('\N{THUMBS DOWN SIGN}')
          async def on_thumbs_down(self, payload):
              await self.message.edit(content=f"That's not nice {self.ctx.author}...")
      
          @menus.button('\N{BLACK SQUARE FOR STOP}\ufe0f')
          async def on_stop(self, payload):
              self.stop()
      
      # later
      @bot.command()
      async def menu_example(ctx):
          m = MyMenu()
          await m.start(ctx)
      

      很抱歉,我无法回答您的第一个问题,我不知道为什么会这样,抱歉。

      回答您的其他问题:

      1. wait_for 采用与事件相同的参数,on_message 采用 message,因此检查将采用 message 作为单个参数(该方法也将仅返回 message)。添加更多参数,这与装饰器的基础非常相似,我们将检查包装在另一个外部函数中
      def check(func): # The ADDITIONAL arguments we want to pass, in this example another function
          def inner_check(reaction, user): # The actual check
              return user == ctx.author and func(reaction, user)
          return inner_check
      
      # To use it                                                     Note how I'm calling the check an additional argument
      reaction, user = await bot.wait_for('reaction_add', check=check(lambda r, u: return True), timeout=60.0)
      

      Python decorator basics

      1. 同第一个问题
      2. 机器人等待添加任何反应,如果检查函数返回True,它将返回值
      3. 如果检查返回的不是True,机器人将等待函数返回True或超时结束

      【讨论】:

      • 谢谢!了解 wait_for 如何引导我找到解决方案。我现在遇到了我后续帖子中描述的可能的性能问题(我说可能是因为我不知道这是否是正常问题)。关于替代方案,我想在未来的迭代中实现这种菜单方法!我没有足够的声望让我的支持可见,但根据我收到的通知,我认为它就在那里!
      • 另外,我的命令是在一个 cog 中,如果我们把它放在一个单独的文件和 cog 类中,你的菜单代码需要改变多少?
      • 它根本不会改变,但不要把菜单类放在齿轮里面
      猜你喜欢
      • 2020-10-27
      • 1970-01-01
      • 2020-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-21
      • 2021-01-01
      • 2019-04-14
      相关资源
      最近更新 更多