0
votes

I have been using the following two methods to get a user input from a discord embed. The first I use to get a text based message input and the second I use to get a reaction input (used to paginate the embed). What I would like to know is if I can merge these two to create a method to wait for either a reaction or a message input?

#message input

try:
                    answer = await self.bot.wait_for(
                        "message",
                        timeout=60,
                        check=lambda message: message.author.id == ctx.author.id
                        and isinstance(message.channel, discord.channel.DMChannel) 
                                            
                    )

#reaction input
try:
                    reaction, user = await self.bot.wait_for(
                        "reaction_add",
                        timeout=60,
                        check=lambda reaction, user: user.id == ctx.author.id
                        and reaction.emoji in buttons
                        #and isinstance(reaction.channel, discord.channel.DMChannel),
                    )

UPDATE: So I have tried to implement the method duckboycool linked to (Many thanks man!). The issue I am having now is that when I react to the paginated embed it works perfectly, the reaction is noted and the embed is updated accordingly. But if I input a message instead it get the following error:

"reaction, emoji = await task TypeError: cannot unpack non-iterable Message object"

here is my code:

finished =0
            
        while finished == 0:
            done_tasks = None   
            check1=lambda reaction, user: user.id == ctx.author.id and reaction.emoji in buttons
            check2=lambda message: message.author.id == ctx.author.id and isinstance(message.channel, discord.channel.DMChannel)

            pending_tasks = [self.bot.wait_for('reaction_add',check=check1),self.bot.wait_for('message',check=check2)]
            done_tasks, pending_tasks = await asyncio.wait(pending_tasks, return_when=asyncio.FIRST_COMPLETED)

            #print(done_tasks)
            for task in pending_tasks:
                task.cancel()
            for task in done_tasks: 
                reaction, emoji = await task
                message = await task
                if reaction:
                    print(reaction)
                    previous_page = current

                    if reaction.emoji == u"\u23EA":
                        current = 0
                    
                    elif reaction.emoji == u"\u25C0":
                        if current > 0:
                            current -= 1
                    
                    elif reaction.emoji == u"\u25B6":
                        if current < len(pages)-1:
                            current  += 1
                    elif reaction.emoji == u"\u23E9":
                        current = len(pages)-1
                    

                    if current != previous_page:
                        await msg.edit(embed = pages[current])
                else:
                    print(message.content)
1
Does this answer your question?duckboycool
@duckboycool Thank you for the link! I have tried to implement that solution... think I am doing something wrong. Would you mind taking a look? I have updated the original post.TranquilityEden

1 Answers

0
votes

In the updated code, you need to check what kind of awaitable the event is so that you can unpack with the correct number of values and complete the intended behavior. With your examples of message and reaction_add, this would probably look something like this.

for task in done_tasks:
    taskobj = await task
    
    if isinstance(taskobj, discord.Message):
        message = taskobj

        #Message logic
    
    else:
        reaction, user = taskobj
        
        #Reaction logic

You might have to do different things depending on which events you're using. (Here, it relies on a tuple being recognized as not an instance of discord.Message.)