将排行榜分页 discord.py

时间:2021-01-16 22:16:55

标签: discord.py

我希望我的排行榜根据用户数量分成多个页面。 例如,如果有 5 个用户,则只剩下一个页面,如果有 23 个用户,则将它们分成 3 个页面,其中前 2 个显示 10 个用户,而最后一个显示最后 3 个用户。 我已经尝试了很多方法,但我已经到了我真的不知道该怎么做的地步。你能解决吗? 只要有效,任何方法都可以接受。

@client.command()
async def leaderboard(ctx):
    cursor = levelsystem_db.cursor()
    cursor.execute("SELECT users.user_level, users.user_xp, users.client_id\nFROM users\nORDER BY users.user_level DESC , users.user_xp DESC")
    leaderboard = cursor.fetchall()
    embed = discord.Embed(
        title=f"Leaderboard del {ctx.guild.name}",
        colour=0x003399
    )
    for i, pos in enumerate(leaderboard, start=1):
        lvl, xp, member_id = pos
        cursor.execute(f"SELECT xp_level FROM levels WHERE level = {lvl+1}")
        xp_level = cursor.fetchall()
        xp_level = xp_level[0][0]
        member = await client.fetch_user(member_id)
        sorted_users = ## get all the members and sort them...
        pages = grouper(sorted_users, 10)
        print(pages)
        embed.add_field(
            name=f"{i}. {member.display_name}",
            value=f"Livello attuale: {lvl}\n\t\tXP: {xp}/{xp_level}\n",
            inline=False
        )
    await ctx.send(embed=embed)

def grouper(iterable, n, fillvalue=None):
    args = [iter(iterable)] * n
    return zip_longest(*args, fillvalue=fillvalue)

3 个答案:

答案 0 :(得分:1)

您可以使用反应对嵌入进行分页:

import asyncio

@client.command()
async def leaderboard(ctx):
    cursor = levelsystem_db.cursor()
    cursor.execute("SELECT user_level, user_xp, client_id FROM users ORDER BY user_level DESC, user_xp DESC")
    users = cursor.fetchall()
    pages = []
    page_count = -(-len(users)//10)) #will return 3 if users' length is 23
    for i in range(page_count):
        embed = discord.Embed(
            title = f"Leaderboard del {ctx.guild.name}",
            colour = 0x003399
        )
        embed.set_footer(
            text = f"Page {i + 1}/{page_count}"
        )
        for rank, data in enumerate(users[i * 10:i * 10 + 10], start=i * 10 + 1):
            level = data[0]
            xp = data[1]
            user = await client.fetch_user(data[2])
    
            embed.add_field(
                name = f"#{rank} {user}",
                value = f"Level: {level}\nExperience: {xp}"
                inline = False
            )
        pages.append(embed)

    index = 0
    message = await ctx.send(embed=pages[0])
    emojis = ["◀️", "⏹", "▶️"]
    for emoji in emojis:
        await message.add_reaction(emoji)
    while not client.is_closed():
        try:
            react, user = await client.wait_for(
                "reaction_add",
                timeout = 60.0,
                check = lambda r, u: r.emoji in emojis and u.id == ctx.author.id and r.message.id == message.id
            )
            if react.emoji == emojis[0] and index > 0:
                index -= 1
            elif react.emoji == emojis[1]:
                await message.delete()
                break
            elif react.emoji == emojis[2] and index < len(pages) - 1:
                index += 1

            await message.edit(embed=pages[index])
        except asyncio.TimeoutError:
            await message.delete()
            break

答案 1 :(得分:0)

根据 Discord 关于嵌入限制的文档,发现 here,您最多可以有 25 个字段对象,并且嵌入的字符最多不应超过 6000 个。

考虑到这些信息,您可以创建一个函数来跟踪字符数和字段数。一旦超过这些限制之一,就应该创建一个单独的“页面”,以保持嵌入在这些限制之下。

您需要存储消息的当前状态并拥有一个 reaction_add event listener。在您的 react_add 事件侦听器中,您需要再次检查消息并检查它位于哪个页面以及 edit the message 以进行新的嵌入。

我希望这会有所帮助。如果你卡住了,我会检查评论并帮助你!

答案 2 :(得分:0)

Idk 如果这就是你的意思,但试试这个:

import math


@client.command()
async def test(ctx):
    users = [
        "user1",
        "user2",
        "user3",
        "user4",
        "user5",
        "user6",
        "user7",
        "user8",
        "user9",
        "user10",
        "user11",
        "user12",
        "user13",
        "user14",
        "user15",
        "user16",
        "user17",
        "user18",
        "user19",
        "user20",
        "user21",
        "user22",
        "user23",
    ]
    pages = {}
    numOfPages = math.ceil(len(users) / 10)
    j = 0
    for i in range(numOfPages):
        pages[f"page{i}"] = discord.Embed(title=f"Page {i+1}")
        displayUsers = ""
        while j < 10 + i * 10:
            try:
                displayUsers += users[j] + "\n"
            except:
                break
            j += 1
        pages[f"page{i}"].add_field(name="Users:", value=displayUsers)
        await ctx.send(embed=pages[f"page{i}"])

它使用 for 循环根据用户计数创建 discord.Embed 对象,然后将它们依次发送。