我希望我的排行榜根据用户数量分成多个页面。 例如,如果有 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)
答案 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
对象,然后将它们依次发送。