joeyagreco
joeyagreco

Reputation: 124

How to handle multiple reactions in Discord py (Bot)

Trying to make my bot handle multiple reactions to a message.

I can get a version of this to work if I only check for one reaction like:

reaction, user = await bot.wait_for('reaction_add', timeout=5, check=checkR)

but when I check for multiple reactions (like paper and scissors), the code simply will not work.

I've searched everywhere for help on this and cannot find anything that is post-Discord rewrite.

Any help appreciated!

# test rps
@bot.command()
async def test(ctx):

    eb = await getEmbed(ctx, "Rock, Paper, Scissors", "", {}, "", "Choose one:", discord.Colour.gold())

    msg = await ctx.message.channel.send(embed = eb)
    channel = msg.channel
    for emoji in ('🗿', '📄', "✂"):
        await msg.add_reaction(emoji)

    # now check for response
    def checkR(reaction, user):
        return user == ctx.message.author and str(reaction.emoji) == '🗿'
    def checkP(reaction, user):
        print("in paper")
        return user == ctx.message.author and str(reaction.emoji) == '📄'
    def checkS(reaction, user):
        return user == ctx.message.author and str(reaction.emoji) == '✂'

    try:
        reaction, user = await bot.wait_for('reaction_add', timeout=5, check=checkR)
        reaction, user = await bot.wait_for('reaction_add', timeout=5, check=checkP)
        reaction, user = await bot.wait_for('reaction_add', timeout=5, check=checkS)
    except asyncio.TimeoutError:
        await embed(ctx, "Game timed out.")
        return
    else:
        # we got a reaction
        await embed(ctx, "GOT A REACTION")
        await discord.Message.delete(msg)
        pass

Upvotes: 1

Views: 4860

Answers (2)

Spi Spi
Spi Spi

Reputation: 13

thanks i was looking for this for way to long here's what i came up with.

creates message and adds reactions:

    @commands.command()
async def pageturn(self, ctx):
    guildid = str(ctx.guild.id)
    userid = str(ctx.author.id)
    previuspage = '⬅️'
    nextpage = '➡️'
    page = 1
    msg = await ctx.send(f'page{page}')
    await msg.add_reaction(previuspage)
    await msg.add_reaction(nextpage)

    def checkforreaction(reaction, user):
        return str(user.id) == userid and str(reaction.emoji) in [previuspage,nextpage]

#loops untill reaction_add times out

    loopclose = 0
    while loopclose == 0:
        try:
            reaction, user = await self.client.wait_for('reaction_add', timeout=5,check = checkforreaction)
            if reaction.emoji == nextpage:
                page += 1
            elif reaction.emoji == previuspage:
                page-= 1
            await msg.edit(content=f'page{page}')

        except asyncio.TimeoutError:
           await ctx.send('timeout')
           loopclose = 1

Upvotes: 0

Tin Nguyen
Tin Nguyen

Reputation: 5330

reaction, user = await bot.wait_for('reaction_add', timeout=5, check=checkR)
reaction, user = await bot.wait_for('reaction_add', timeout=5, check=checkP)
reaction, user = await bot.wait_for('reaction_add', timeout=5, check=checkS)

This waits for someone to react Rock, Paper, Scissor in that order. It does not accept only Paper, or only Scissor. It wants all 3 reactions and in that order.

You need to write something like this:

def check(reaction, user):
  return user == ctx.message.author and str(reaction.emoji) in ['🗿', '📄', '✂']

reaction, user = await bot.wait_for('reaction_add', timeout=5, check=check)

This will look for one reaction that is either rock, paper or scissor.

Upvotes: 2

Related Questions