Last active
August 13, 2023 19:04
-
-
Save mudkipdev/4b0ce96a2d9bd6205e16c52798546571 to your computer and use it in GitHub Desktop.
A discord.py embed pagination system using buttons.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from discord.ext import commands | |
import discord | |
import asyncio | |
__all__ = ("Paginator",) | |
class Paginator: | |
def __init__( | |
self, | |
embeds: list[discord.Embed], | |
*, | |
index: int = 0, | |
author: discord.User | None = None | |
) -> None: | |
self.embeds = embeds | |
self.index = index | |
self.author = author | |
self.paginated_view = PaginatedView(self.embeds, author=self.author) | |
async def start( | |
self, | |
messageable: discord.abc.Messageable | discord.Interaction, | |
*args, | |
**kwargs | |
) -> None: | |
kwargs["embed"] = self.embeds[self.index] | |
kwargs["view"] = self.paginated_view | |
if isinstance(messageable, discord.Interaction): | |
await messageable.response.send_message(*args, **kwargs) | |
elif isinstance(messageable, discord.abc.Messageable): | |
await messageable.send(*args, **kwargs) | |
self.paginated_view.set_index(self.index) | |
class PaginatedView(discord.ui.View): | |
def __init__( | |
self, embeds: list[discord.Embed], *, author: discord.User | None = None | |
) -> None: | |
super().__init__(timeout=None) | |
self.embeds = embeds | |
self.index = 0 | |
self.author = author | |
@discord.ui.button(custom_id="previous", emoji="◀") | |
async def previous( | |
self, interaction: discord.Interaction, button: discord.ui.Button | |
) -> None: | |
self.set_index(self.index - 1) | |
await self.update(interaction) | |
@discord.ui.button(custom_id="page", emoji="🔢") | |
async def page( | |
self, interaction: discord.Interaction, button: discord.ui.Button | |
) -> None: | |
if self.author and interaction.user != self.author: | |
await interaction.response.send_message( | |
embed=discord.Embed( | |
description="You do not have permission to interact with this menu.", | |
color=discord.Color.dark_embed(), | |
), | |
ephemeral=True, | |
) | |
return | |
await interaction.response.send_modal(PageModal(self)) | |
@discord.ui.button(custom_id="next", emoji="▶") | |
async def next( | |
self, interaction: discord.Interaction, button: discord.ui.Button | |
) -> None: | |
self.set_index(self.index + 1) | |
await self.update(interaction) | |
async def update(self, interaction: discord.Interaction) -> None: | |
if self.author and interaction.user != self.author: | |
await interaction.response.send_message( | |
embed=discord.Embed( | |
description="You do not have permission to interact with this menu.", | |
color=discord.Color.dark_embed(), | |
), | |
ephemeral=True, | |
) | |
return | |
await interaction.response.edit_message( | |
embed=self.embeds[self.index], view=self | |
) | |
def set_index(self, index: int) -> None: | |
if not 0 <= index < len(self.embeds): | |
return | |
self.previous.disabled = index == 0 | |
self.next.disabled = index == len(self.embeds) - 1 | |
self.index = index | |
class PageModal(discord.ui.Modal, title="Skip to Page"): | |
page = discord.ui.TextInput(label="Page", required=True) | |
def __init__(self, paginated_view: PaginatedView) -> None: | |
super().__init__() | |
self.paginated_view = paginated_view | |
async def on_submit(self, interaction: discord.Interaction) -> None: | |
if self.page.value.isdigit(): | |
self.paginated_view.set_index(int(self.page.value) - 1) | |
await self.paginated_view.update(interaction) | |
else: | |
await interaction.response.send_message( | |
embed=discord.Embed( | |
description="That page number is invalid.", | |
color=discord.Color.dark_embed(), | |
), | |
ephemeral=True, | |
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Slash Command Example (With Cogs) | |
@app_commands.command(description="Sends a paginated message.") | |
async def test(self, interaction: discord.Interaction) -> None: | |
paginator = Paginator(embeds=[discord.Embed( | |
description=f"{page + 1}", | |
color=discord.Color.random() | |
) for page in range(5)]) | |
await paginator.start(interaction) | |
# Slash Command Example (Without Cogs) | |
@bot.tree.command(description="Sends a paginated message.") | |
async def test(interaction: discord.Interaction) -> None: | |
paginator = Paginator(embeds=[discord.Embed( | |
description=f"{page + 1}", | |
color=discord.Color.random() | |
) for page in range(5)]) | |
await paginator.start(interaction) | |
# Message Command Example (With Cogs) | |
@commands.command(help="Sends a paginated message.") | |
async def test(self, ctx: commands.Context) -> None: | |
paginator = Paginator(embeds=[discord.Embed( | |
description=f"{page + 1}", | |
color=discord.Color.random() | |
) for page in range(5)]) | |
await paginator.start(ctx) | |
# Message Command Example (Without Cogs) | |
@bot.command(help="Sends a paginated message.") | |
async def test(ctx: commands.Context) -> None: | |
paginator = Paginator(embeds=[discord.Embed( | |
description=f"{page + 1}", | |
color=discord.Color.random() | |
) for page in range(5)]) | |
await paginator.start(ctx) | |
# Hybrid Command Example (With Cogs) | |
# (coming soon) | |
# Hybrid Command Example (Without Cogs) | |
# (coming soon) |
Looking great tbh, but there should be a toggle option too, weather the user want to flag other user if the view is not for him or not. But other codes are good! Also there should be handler when isdigit() returns False. And done basically, Oh forgot to mention, this paginator should raise a error if the list of embeds is not 2 or more.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
looks good mate 👍