Discord.py: 多个多页消息

Discord.py: Multiple multipage messages

编辑:

解决方法是在check函数中添加一个条件,我已经在后续的回答中发布了详细信息。

主要问题:

我是新手 python 并决定通过创建一个 discord 机器人来学习它。

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

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

补充问题:

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"
reaction, user = await bot.wait_for("reaction_add", timeout=60, check=check)

比您提供的方法更好的替代方法是使用 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 作为单个参数(该方法也将仅 return 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. 机器人等待添加任何反应,如果检查函数 returns True 它将 return 值
  3. 如果检查 returns 而不是 True 机器人将等待直到函数 returns True 或超时结束

感谢 Ł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() 多次。