英文:
How to create pagination embed menu in discord.py?
问题
I need a 'SLASH COMMAND' that can displays an embed with 10 elements per page and buttons below for navigation (not reactions, those clickable buttons recently introduced).
I am using Discord.py version 2.2.3
Here is the code snippet of my bot:
import os
import discord
from discord import app_commands
import asyncio
TOKEN='YOUR TOKEN HERE'
GUILD='GUILD NAME HERE'
intents = discord.Intents.default()
intents.message_content = True
client = discord.Client(intents=intents) #I am using client, instead of commands.Bot()
tree = app_commands.CommandTree(client) #This is for the slash command, I am using tree.
@client.event
async def on_ready():
for guild in client.guilds:
if guild.name == GUILD:
break
print(
f'{client.user} has successfully connected to the following guild(s):\n'
f'{guild.name}(id: {guild.id})'
)
await client.change_presence(activity=discord.Activity(name='anything', type=discord.ActivityType.playing))
@tree.command(name='EMBED', description='Description here', guild=discord.Object(id=000000000000000000)) #guild id here
''' Cannot proceed further '''
I tried different modules such as discord_slash (for slash command), interactions etc. and still unable to create a paginator.
I was expecting to create a slash command that displays 10 elements per page out of any number of elements, in the form of an embed with buttons like this:
Extra Info:
- I am using client instead of Commands.Bot()
- I am using tree for Slash commands.
- discord_slash is not compatible with my discord.py version.
- Slash command is necessary for me.
- I am using Python 3.11 IDLE.
英文:
I need a 'SLASH COMMAND' that can displays an embed with 10 elements per page and buttons below for navigation (not reactions, those clickable buttons recently introduced).
I am using Discord.py version 2.2.3
Here is the code snippet of my bot:
import os
import discord
from discord import app_commands
import asyncio
TOKEN='YOUR TOKEN HERE'
GUILD='GUILD NAME HERE'
intents = discord.Intents.default()
intents.message_content = True
client = discord.Client(intents=intents) #I am using client, instead of commands.Bot()
tree = app_commands.CommandTree(client) #This is for the slash command, I am using tree.
@client.event
async def on_ready():
for guild in client.guilds:
if guild.name == GUILD:
break
print(
f'{client.user} has successfully connected to the following guild(s):\n'
f'{guild.name}(id: {guild.id})'
)
await client.change_presence(activity=discord.Activity(name='anything', type=discord.ActivityType.playing))
@tree.command(name='EMBED', description='Description here', guild=discord.Object(id=000000000000000000)) #guild id here
''' Cannot proceed further '''
I tried different modules such as discord_slash (for slash command), interactions etc. and still unable to create a paginator.
I was expecting to create a slash command that displays 10 elements per page out of any number of elements, in the form of an embed with buttons like this:
Extra Info:
- I am using client instead of Commands.Bot()
- I am using tree for Slash commands.
- discord_slash is not compatible with my discord.py version.
- Slash command is necessary for me.
- I am using Python 3.11 IDLE.
答案1
得分: 2
I have a pagination view already prepared that I use in my bots:
import discord
from typing import Callable, Optional
class Pagination(discord.ui.View):
def __init__(self, interaction: discord.Interaction, get_page: Callable):
self.interaction = interaction
self.get_page = get_page
self.total_pages: Optional[int] = None
self.index = 1
super().__init__(timeout=100)
async def interaction_check(self, interaction: discord.Interaction) -> bool:
if interaction.user == self.interaction.user:
return True
else:
emb = discord.Embed(
description=f"只有命令的作者可以执行此操作。",
color=16711680
)
await interaction.response.send_message(embed=emb, ephemeral=True)
return False
async def navegate(self):
emb, self.total_pages = await self.get_page(self.index)
if self.total_pages == 1:
await self.interaction.response.send_message(embed=emb)
elif self.total_pages > 1:
self.update_buttons()
await self.interaction.response.send_message(embed=emb, view=self)
async def edit_page(self, interaction: discord.Interaction):
emb, self.total_pages = await self.get_page(self.index)
self.update_buttons()
await interaction.response.edit_message(embed=emb, view=self)
def update_buttons(self):
if self.index > self.total_pages // 2:
self.children[2].emoji = "⏮️"
else:
self.children[2].emoji = "⏭️"
self.children[0].disabled = self.index == 1
self.children[1].disabled = self.index == self.total_pages
@discord.ui.button(emoji="◀️", style=discord.ButtonStyle.blurple)
async def previous(self, interaction: discord.Interaction, button: discord.Button):
self.index -= 1
await self.edit_page(interaction)
@discord.ui.button(emoji="▶️", style=discord.ButtonStyle.blurple)
async def next(self, interaction: discord.Interaction, button: discord.Button):
self.index += 1
await self.edit_page(interaction)
@discord.ui.button(emoji="⏭️", style=discord.ButtonStyle.blurple)
async def end(self, interaction: discord.Interaction, button: discord.Button):
if self.index <= self.total_pages//2:
self.index = self.total_pages
else:
self.index = 1
await self.edit_page(interaction)
async def on_timeout(self):
# remove buttons on timeout
message = await self.interaction.original_response()
await message.edit(view=None)
@staticmethod
def compute_total_pages(total_results: int, results_per_page: int) -> int:
return ((total_results - 1) // results_per_page) + 1
You can save it in a pagination.py
file.
Its use is very simple. You just need to pass a function that will generate your pages. This function will receive the index and should return the Embed corresponding to the page and also the total number of pages.
I'll show you an example of use:
import discord
from pagination import Pagination
users = [f"User {i}" for i in range(1, 10000)]
# This is a long list of results
# I'm going to use pagination to display the data
L = 10 # elements per page
@tree.command(name="show")
async def show(interaction: discord.Interaction):
async def get_page(page: int):
emb = discord.Embed(title="The Users", description="")
offset = (page-1) * L
for user in users[offset:offset+L]:
emb.description += f"{user}\n"
emb.set_author(name=f"Requested by {interaction.user}")
n = Pagination.compute_total_pages(len(users), L)
emb.set_footer(text=f"Page {page} from {n}")
return emb, n
await Pagination(interaction, get_page).navegate()
My pagination model has 3 buttons. The first two have the function of going to the previous page and going to the next page. These buttons will be disabled when they cannot be used. The third button has a double function: if you are halfway through the pages, it will allow you to advance to the last one. If you are past half the pages, it will allow you to rewind the first one.
英文:
I have a pagination view already prepared that I use in my bots:
import discord
from typing import Callable, Optional
class Pagination(discord.ui.View):
def __init__(self, interaction: discord.Interaction, get_page: Callable):
self.interaction = interaction
self.get_page = get_page
self.total_pages: Optional[int] = None
self.index = 1
super().__init__(timeout=100)
async def interaction_check(self, interaction: discord.Interaction) -> bool:
if interaction.user == self.interaction.user:
return True
else:
emb = discord.Embed(
description=f"Only the author of the command can perform this action.",
color=16711680
)
await interaction.response.send_message(embed=emb, ephemeral=True)
return False
async def navegate(self):
emb, self.total_pages = await self.get_page(self.index)
if self.total_pages == 1:
await self.interaction.response.send_message(embed=emb)
elif self.total_pages > 1:
self.update_buttons()
await self.interaction.response.send_message(embed=emb, view=self)
async def edit_page(self, interaction: discord.Interaction):
emb, self.total_pages = await self.get_page(self.index)
self.update_buttons()
await interaction.response.edit_message(embed=emb, view=self)
def update_buttons(self):
if self.index > self.total_pages // 2:
self.children[2].emoji = "⏮️"
else:
self.children[2].emoji = "⏭️"
self.children[0].disabled = self.index == 1
self.children[1].disabled = self.index == self.total_pages
@discord.ui.button(emoji="◀️", style=discord.ButtonStyle.blurple)
async def previous(self, interaction: discord.Interaction, button: discord.Button):
self.index -= 1
await self.edit_page(interaction)
@discord.ui.button(emoji="▶️", style=discord.ButtonStyle.blurple)
async def next(self, interaction: discord.Interaction, button: discord.Button):
self.index += 1
await self.edit_page(interaction)
@discord.ui.button(emoji="⏭️", style=discord.ButtonStyle.blurple)
async def end(self, interaction: discord.Interaction, button: discord.Button):
if self.index <= self.total_pages//2:
self.index = self.total_pages
else:
self.index = 1
await self.edit_page(interaction)
async def on_timeout(self):
# remove buttons on timeout
message = await self.interaction.original_response()
await message.edit(view=None)
@staticmethod
def compute_total_pages(total_results: int, results_per_page: int) -> int:
return ((total_results - 1) // results_per_page) + 1
You can save it in a pagination.py
file.
Its use is very simple. You just need to pass a function that will generate your pages. This function will receive the index and should return the Embed corresponding to the page and also the total number of pages.
I'll show you an example of use:
import discord
from pagination import Pagination
users = [f"User {i}" for i in range(1, 10000)]
# This is a long list of results
# I'm going to use pagination to display the data
L = 10 # elements per page
@tree.command(name="show")
async def show(interaction: discord.Interaction):
async def get_page(page: int):
emb = discord.Embed(title="The Users", description="")
offset = (page-1) * L
for user in users[offset:offset+L]:
emb.description += f"{user}\n"
emb.set_author(name=f"Requested by {interaction.user}")
n = Pagination.compute_total_pages(len(users), L)
emb.set_footer(text=f"Page {page} from {n}")
return emb, n
await Pagination(interaction, get_page).navegate()
My pagination model has 3 buttons. The first two have the function of going to the previous page and going to the next page. These buttons will be disabled when they cannot be used. The third button has a double function: if you are halfway through the pages, it will allow you to advance to the last one. If you are past half the pages, it will allow you to rewind the first one.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论