Search code examples
pythondiscordnextcord

Check for button interaction while awaiting for message (Nextcord)


I'm making a discord slash command that I need for another projext that once interacted with starts looking for images sent by the user in the chat and saves them. It all works fine, but when I interact with the button to stop looking for images the loop has already checked event.is_set() != True at 2 lines after #HELP HERE and is awaiting for a message, so even if the loop is closed I get one more iteration. Is there a way to stop this code:

check = lambda msg: interaction.user.id == msg.author.id
message = await bot.wait_for("message", check=check)

from running even if it has already started awaiting?

This is the full code without the @bot.slash_command() decorator:

async def auto(interaction:Interaction):
    await interaction.response.defer()
    event = asyncio.Event()
    embed = Embed(title="", color=0x2f3136)
    #Make a screenshot with Win+Shift+S and press Ctrl+V on the chat to send it.
    embed.add_field(name = "", value="Make a screenshot with `Win+Shift+S` and press `Ctrl+V` on the chat to send it.", inline= False)
    stop_button = Button(label="Stop", style = ButtonStyle.red)
    async def stopb_callback(interaction):
        event.set()
    stop_button.callback = stopb_callback
    view = View()
    view.add_item(stop_button)
    message_to_delete = await interaction.followup.send(embed=embed, view = view)

    #HELP HERE
    while event.is_set() != True:
        print("Event:",event.is_set())
        if event.is_set() != True:
            check = lambda msg: interaction.user.id == msg.author.id
            message = await bot.wait_for("message", check=check)
            
            if len(message.attachments) > 0:
                print(message.attachments[0].url)
                url = message.attachments[0].url
                #save image
                r = requests.get(url, stream=True)
                imageName = str(uuid.uuid4()) + '.png'
                with open(imageName, 'wb') as out_file:
                    shutil.copyfileobj(r.raw, out_file)
            
            else:
                embed1 = Embed(title="", color=0x2f3136)
                embed1.add_field(name = "", value="You have to send a screenshot to start.", inline= False)
                message1 = await interaction.followup.send(embed=embed1)
                all_messages.append(message1)

I also tried assigning a variable like stop = False before the loop and assigning it the value True in the stopb_callback function but it doesn't seem to work I'm not sure why that's why I used asyncio.Event().


Solution

  • Looks like I found a solution:

    message = await bot.wait_for("message", check=check)

    this wait_for function when running continuously check for 2 things:

    the event, in this case "message" and for the check, in this case:

    check = lambda msg: interaction.user.id == msg.author.id

    so, by adding to the add function an and statement that looks like this:

    check = lambda msg: interaction.user.id == msg.author.id and not stop

    the function while waiting for the message checks that the I pressed the stop button, and so the check is no more equal to True, but now it's equal to False, so stops searching for that message.