0
votes

I've been trying to solve this for a couple days with no solution. I want my discord bot to be able to buy digital items, and to buy them I have made a confirmation message and a system where you react to confirm with a 60 seconds timeout with a code I found online.

The problem with that code is it doesnt take into account the message the user reacted, so for example if the user sends two messages and confirms one, they both get executed, also, I can't add another icon like a cancel one. It is pretty important since this is an important function for the bot to work.

Also, making a on_reaction_add function is not viable since I would like my bot to run in various servers and channels at the same time with diferent users sending commands.

@client.event
async def on_message(message):
        channel = message.channel
        embedVar2 = discord.Embed(title="Item buying", description="<@"+ str(message.author.id) +">  Are you sure you want to buy " + str(conditions[1])  + " quantity of " + str(conditions[0]), color = 0x9A9B9D)
        embedVar2.add_field(name="\u200b", value= "It will cost $" + str(price) + " you will have $" + str(endbal) + " remaining \nReact with ✅ to confirm", inline=False)
        await confirm_message.add_reaction("✅") #add a reaction for the user to understand he has to react
        def check(reaction, user):  #checks if user has reacted
            return user == message.author and str(reaction.emoji) == '✅'
        try: #waits if it doest get timeout error
            reaction, user = await client.wait_for('reaction_add', timeout=60.0, check=check) #calls for function check defined prev
        except asyncio.TimeoutError: #if timeout throws error:
            embedVar5 = discord.Embed(title="Money transfer", description="<@"+ str(message.author.id) +">  Are you sure you want to buy " + str(conditions[1])  + " quantity of " + str(conditions[0]), color = 0xFF0A26)
            embedVar5.add_field(name="\u200b", value= "It would have cost $" + str(price) + " you would have had $" + str(endbal) + " remaining \nTransaction canceled", inline=False)
            await confirm_message.edit(embed = embedVar5) #message edit to canceled
            return
        else: #if user reacted before timeout
            embedVar4 = discord.Embed(title="Money transfer", description="<@"+ str(message.author.id) +">  Are you sure you want to buy " + str(conditions[1])  + " quantity of " + str(conditions[0]), color = 0x77FF87)
            embedVar4.add_field(name="\u200b", value= "It will cost $" + str(price) + " you now have $" + str(endbal) + " remaining \nTransaction confirmed", inline=False)
            await confirm_message.edit(embed = embedVar4)   #message edit to confirmed

Thanks in advance, Noel.

1

1 Answers

2
votes

To make this message specific, simply add and reaction.message == message in check:

def check(reaction, user):  #checks if user has reacted
    return user == message.author and str(reaction.emoji) == '✅' and reaction.message == message

If you also want to have a cancel reaction, you should modify check to also allow cancel reactions:

def check(reaction, user):  #checks if user has reacted
    return user == message.author and str(reaction.emoji) in ['✅','Your cancel reaction here'] and reaction.message == confirm_message

and then check with which reaction the user reacted and do stuff depending on which reaction was used:

        try:
            reaction, user = await client.wait_for('reaction_add', timeout=60.0, check=check) #calls for function check defined prev
        except asyncio.TimeoutError:
            embedVar5 = discord.Embed(title="Money transfer", description="<@"+ str(message.author.id) +">  Are you sure you want to buy " + str(conditions[1])  + " quantity of " + str(conditions[0]), color = 0xFF0A26)
            embedVar5.add_field(name="\u200b", value= "It would have cost $" + str(price) + " you would have had $" + str(endbal) + " remaining \nTransaction canceled", inline=False)
            await confirm_message.edit(embed = embedVar5) 
            return
        else:
        if str(reaction.emoji) == '✅':
            embedVar4 = discord.Embed(title="Money transfer", description="<@"+ str(message.author.id) +">  Are you sure you want to buy " + str(conditions[1])  + " quantity of " + str(conditions[0]), color = 0x77FF87)
            embedVar4.add_field(name="\u200b", value= "It will cost $" + str(price) + " you now have $" + str(endbal) + " remaining \nTransaction confirmed", inline=False)
            await confirm_message.edit(embed = embedVar4) 
        elif str(reaction.emoji) == 'Your cancel emoji here':
            await confirm_message.edit(embed = embedVar5) #execute the same code you executed on TimeoutError
            return

References: