Reaction pagination button forward and back python

2020-03-07 23:41发布

问题:

I'm trying to make a button / reaction to go back and forth between 3 different images, but the button is not coming back in the previous image, just advancing to the next one, could anyone help me?

    if message.content.startswith('!image'):

        msg1 = await Bot.send_file(message.channel, 'image1.png')

        toReact = ('⏩')
        for reaction in toReact:
            await Bot.add_reaction(msg1, reaction)
        def checkReaction(reaction, user):
            e = str(reaction.emoji)
            return e.startswith('⏩')
        res = await Bot.wait_for_reaction(message=msg1, user=message.author, timeout=30, check=checkReaction)

        if res is None:
            await Bot.delete_message(msg1)

        elif '⏩' in str(res.reaction.emoji):
            await Bot.delete_message(msg1)
            msg2 = await Bot.send_file(message.channel, 'image2.png')

            toReact = ['⏪', '⏩']
            for reaction in toReact:
                await Bot.add_reaction(msg2, reaction)
            def checkReaction2(reaction, user):
                e = str(reaction.emoji)
                return e.startswith('⏪','⏩')
            res2 = await Bot.wait_for_reaction(message=msg2, user=message.author, timeout=30, check=checkReaction2)

            if res2 is None:
                await Bot.delete_message(msg2)

            elif '⏩' in str(res.reaction.emoji):
                await Bot.delete_message(mensagem2)
                await Bot.send_file(message.channel, 'image3.png')

回答1:

Here's what I came up with.

Basically, we have a loop that checks every reaction against the ones we want, and then delete the old message and send the new one if we see one of the reactions we're looking for.

from discord.ext import commands

bot = commands.Bot(command_prefix='!')

left = '⏪'
right = '⏩'

messages = ("1", "2", "3")

def predicate(message, l, r):
    def check(reaction, user):
        if reaction.message.id != message.id or user == bot.user:
            return False
        if l and reaction.emoji == left:
            return True
        if r and reaction.emoji == right:
            return True
        return False

    return check


@bot.command(pass_context=True)
async def series(ctx):
    index = 0
    while True:
        msg = await bot.say(messages[index])
        l = index != 0
        r = index != len(messages) - 1
        if l:
            await bot.add_reaction(msg, left) 
        if r:
            await bot.add_reaction(msg, right)
        # bot.wait_for_reaction
        react, user = await bot.wait_for_reaction(check=predicate(msg, l, r))
        if react.emoji == left:
            index -= 1
        elif react.emoji == right:
            index += 1
        await bot.delete_message(msg)

bot.run("TOKEN")

Someone asked for a version that edits the message instead of sending a new one, I've also updated it to the latest version:

@bot.command(pass_context=True)
async def series(ctx):
    index = 0
    msg = None
    action = ctx.send
    while True:
        res = await action(content=messages[index])
        if res is not None:
            msg = res
        l = index != 0
        r = index != len(messages) - 1
        if l:
            await msg.add_reaction(left) 
        if r:
            await msg.add_reaction(right)
        react, user = await bot.wait_for('reaction_add', check=predicate(msg, l, r))
        if react.emoji == left:
            index -= 1
        elif react.emoji == right:
            index += 1
        action = msg.edit