How to loop with a reaction embed menu

你说的曾经没有我的故事 提交于 2021-02-10 15:43:18

问题


What I'm trying to do: Learning to make a proper help menu for my discord.py bot by having the ctx.message.author react to the message with the reactions given. The bot checks if they've been reacted to, then edits the message. If the ctx.message.author un-reacts, it goes back to the first menu (menuu).

Problem(s): I'm not sure how to loop through this until the timeout runs out. I'm also not sure how to check if the user un-reacts to the message.

Error(s): No errors.

@client.command()
async def menuu(ctx):
    #what reaction goes where menuu
    menuu = discord.Embed(title="menuu", color=0x8d78d9)
    menuu.add_field(name="Topics: ", value="React with <:oneone:772681764321099827>", inline=False)
    menuu.add_field(name="Games: ", value="React with <:twotwo:772681764271423528>", inline=False)
    menuu.add_field(name="Misc: ", value="React with <:threethree:772681763939024897>", inline=False)
    menuu.set_footer(text=f"Ensure you drink some water today, you're doing so well {ctx.message.author}")
    #topics menuu
    topics = discord.Embed(title="Topics", color=0x8d78d9)
    topics.add_field(name="`bl!topic`: ", value="Friend makers and ice breakers", inline=False)
    topics.add_field(name="`bl!debate`: ", value="menuu not complete sorry haha")
    topics.set_footer(text="Never forget to believe in yourself, because I do!")
    #game menuu
    games = discord.Embed(title="Games", color=0x8d78d9)
    games.add_field(name="`nothing here`: ", value="Technically there is but still", inline=False)
    games.set_footer(text="Eat some food, take a nap, good luck on the journey ahead")
    #misc menuu
    misc = discord.Embed(title="Misc", color=0x8d78d9)
    misc.add_field(name="`miscmimscimc`: ", value="aeaeaeaeaeaeeae", inline=False)
    misc.set_footer(text="You look lovely today, you're rocking this look")
    msg = await ctx.send(embed=menuu)#send message
    #add reactions things
    await msg.add_reaction("<:oneone:772681764321099827>")
    await msg.add_reaction("<:twotwo:772681764271423528>")
    await msg.add_reaction("<:threethree:772681763939024897>")
    await msg.add_reaction("<:stop:773054889685024768>")

    try:
        def check(reaction, user):
            return user == ctx.message.author and str(reaction.emoji) in ["<:oneone:772681764321099827>","<:twotwo:772681764271423528>","<:threethree:772681763939024897>"]
        reaction, user = await client.wait_for("reaction_add", timeout=60, check=check)

        if str(reaction.emoji) == "<:oneone:772681764321099827>":
            await msg.edit(embed=topics)
            await msg.remove_reaction("<:oneone:772681764321099827>", ctx.message.author)

        if str(reaction.emoji) == "<:twotwo:772681764271423528>":
            await msg.edit(embed=games)
            await msg.remove_reaction("<:twotwo:772681764271423528>", ctx.message.author)

        if str(reaction.emoji) == "<:threethree:772681763939024897>":
            await msg.edit(embed=misc)
            await msg.remove_reaction("<:threethree:772681763939024897>", ctx.message.author)

        if str(reaction.emoji) == "<:stop:773054889685024768>":
            await msg.edit(embed=menuu)
            await msg.remove_reaction("<:stop:773054889685024768>", ctx.message.author)       
            
    except asyncio.TimeoutError:
        await ctx.send("Time has run out, message no work now")
    ```

回答1:


I've created an easy enough to use 'book-manager'. If you put all of your menuus into a list called pages you can use this function:

async def createbook(bot, ctx, title, pages, **kwargs):

        header = kwargs.get("header", "") # String
        results = kwargs.get("results", 0) # Int
        
        pagenum = 1

        def get_results():
            results_min = (pagenum - 1) * 8 + 1
            if pagenum == len(pages): results_max = results
            else: results_max = pagenum * 8
            return f"Showing {results_min} - {results_max} results out of {results}"

        pagemax = len(pages)
        if results:
            header = get_results()
            if len(pages) == 0: pagemax = 1

        embed = discord.Embed(title=title, description=f"{header}\n\n{pages[pagenum - 1]}", colour=0xF42F42)
        embed.set_footer(text=f"Page {pagenum}/{pagemax}", icon_url=fboturl)
        msg = await ctx.send(embed=embed)
        
        await msg.add_reaction("⬅️")
        await msg.add_reaction("➡")
        
        def check(reaction, user):
            return user == ctx.author and str(reaction.emoji) in ["⬅️", "➡"]
    
        while True:
            try:
                reaction, user = await bot.wait_for("reaction_add", timeout = 60, check=check)
                await msg.remove_reaction(reaction, user)
                
                if str(reaction.emoji) == "⬅️":
                    pagenum -= 1
                    if pagenum < 1: pagenum = len(pages)
                        
                elif str(reaction.emoji) == "➡":
                    pagenum += 1
                    if pagenum > len(pages): pagenum = 1

                header = get_results() if results else header
                if str(reaction.emoji) == "⬅️" or str(reaction.emoji) == "➡":
                    embed = discord.Embed(title=title, description=f"{header}\n\n{pages[pagenum - 1]}", colour=0xF42F42)
                    embed.set_footer(text=f"Page {pagenum}/{len(pages)}", icon_url=fboturl)
                    await msg.edit(embed=embed)
            except:
                header = get_results() if results else header
                embed = discord.Embed(title="FBot Server Status", description=f"{header}\n\n{pages[pagenum - 1]}", colour=0xF42F42)
                embed.set_footer(text=f"Request timed out", icon_url=fboturl)
                await msg.edit(embed=embed)
                break

(I avoid using numbers purely because books with more than 10 pages are annoying to manage)




回答2:


So after a really long time of trial and error, I have figured out my own method based off of Judev1's create-book thing. I incorporated the way the page number changes, as well as the wait_for and time out things.

@client.command(aliases=["help"])
async def menuu(ctx):
    #first just giving all the embeds a purpose and a place to exist
    user = ctx.author
    menuu = discord.Embed(title="Help Menuu", color=0x8d78d9)
    menuu.add_field(name="How to navigate : ", value="```Use the arrow reactions below to navigate this menuu```", inline=False)
    menuu.add_field(name="How to invite bot : ", value="```Use bl!invite to invite this bot and join our support server!```", inline=True)
    menuu.set_footer(text=f"Ensure you drink some water today, you're doing so well {ctx.message.author}")
    #topics menuu
    topics = discord.Embed(title="Topics", color=0x8d78d9)
    topics.add_field(name="bl!topic : ", value="```Friend makers and ice breakers```", inline=False)
    topics.add_field(name="bl!debate : ", value="```Sends a debate topic (Trigger Warning: Some topics may trigger certain individuals. Please tread with caution when using this command)```", inline=False)
    topics.add_field(name="bl!wyr : ", value="```Would you rather questions```", inline = False)
    topics.add_field(name="bl!place : ", value="```So many places in the world, so little time```", inline = True)
    topics.set_footer(text="Never forget to believe in yourself, because I do!")
    #game menuu
    games = discord.Embed(title="Games", color=0x8d78d9)
    games.add_field(name=f"bl!powpow `@blitz` : ", value="```Who will win? You, or that person you mentioned?```", inline=False)
    games.add_field(name=f"bl!battle `@blitz` : ", value="```Basically powpow but less work```", inline=True)
    games.set_footer(text="Eat some food, take a nap, good luck on the journey ahead")
    #pics menuu
    pics = discord.Embed(title="Picture Things:tm:", color=0x8d78d9)
    pics.add_field(name="bl!avatar `@blitz` : ", value="```Get the profile picture of the mentioned person```", inline=False)
    pics.add_field(name="bl!hug `@blitz` : ", value="```Hugs, many hug gifs :)```", inline= True)
    pics.add_field(name="bl!slap `@blitz` : ", value="```Slap whoever you want without the pain```", inline=False)
    pics.set_footer(text="You look lovely today, you're rocking this look")
    ##send message##
    msg = await ctx.send(embed=menuu)
    
    pages = 1 #page it's currently on
    left = "<a:totheleft:767541559440572427>" #left arrow reaction
    right = "<a:totheright:767541574287884309>" #right arrow reaction

    await msg.add_reaction(left) #add reaction to send menuu
    await msg.add_reaction(right) #and again

    def check(reaction, user): #checking if user is author and the reaction is either left or right (as defined earlier)
        return user == ctx.author and str(reaction.emoji) in [left, right]

    while True:
        try:
            reaction, user = await client.wait_for("reaction_add", timeout = 120, check=check)
            await msg.remove_reaction(reaction, user)

            if str(reaction.emoji) == left:
                pages = pages - 1
                if pages < 1:
                    pages = 4 #if pages is less than 1, go straight to 4

            if str(reaction.emoji) == right:
                pages = pages + 1
                if pages > 4:
                    pages = 1 #if pages is more than 4, go back to 1
                #if this is the page number, edit so it's this embed instead
            if pages == 1:
                await msg.edit(embed=menuu)

            elif pages == 2:
                await msg.edit(embed=topics)

            elif pages == 3:
                await msg.edit(embed=games)

            elif pages == 4:
                await msg.edit(embed=pics)

        except: #timeout error handling
            embed = discord.Embed(title="Run command again to use", description="Have a good day {ctx.author.display_name}! `bl!menuu`")
            await msg.edit(embed=embed)
            break


来源:https://stackoverflow.com/questions/64675404/how-to-loop-with-a-reaction-embed-menu

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!