211 lines
5.6 KiB
Python
211 lines
5.6 KiB
Python
import discord
|
|
from discord.ext import commands
|
|
from discord import ButtonStyle, Embed, Interaction
|
|
from discord.ui import Button, View
|
|
|
|
|
|
class Bot(commands.Bot):
|
|
def __init__(self):
|
|
super().__init__(
|
|
command_prefix=commands.when_mentioned_or("$"), intents=discord.Intents(guilds=True, messages=True)
|
|
)
|
|
|
|
async def on_ready(self):
|
|
print(f"Logged in as {self.user} (ID: {self.user.id})")
|
|
print("------")
|
|
|
|
|
|
# Define 3 View subclasses that we will switch between depending on if we are viewing the first page, a page in the middle, or the last page.
|
|
# The first page has the "left" button disabled, because there is no left page to go to
|
|
class FirstPageComps(View):
|
|
def __init__(
|
|
self,
|
|
author_id: int,
|
|
):
|
|
super().__init__()
|
|
self.value = None
|
|
self.author_id = author_id
|
|
|
|
async def interaction_check(
|
|
self,
|
|
interaction: Interaction,
|
|
):
|
|
return interaction.user.id == self.author_id
|
|
|
|
@discord.ui.button(
|
|
style=ButtonStyle.primary,
|
|
disabled=True,
|
|
label="Left",
|
|
)
|
|
async def left(
|
|
self,
|
|
button: discord.ui.Button,
|
|
interaction: Interaction,
|
|
):
|
|
self.value = "left"
|
|
self.stop()
|
|
|
|
@discord.ui.button(
|
|
style=ButtonStyle.primary,
|
|
label="Right",
|
|
)
|
|
async def right(
|
|
self,
|
|
button: discord.ui.Button,
|
|
interaction: Interaction,
|
|
):
|
|
self.value = "right"
|
|
self.stop()
|
|
|
|
|
|
# The middle pages have both left and right buttons available
|
|
class MiddlePageComps(View):
|
|
def __init__(
|
|
self,
|
|
author_id: int,
|
|
):
|
|
super().__init__()
|
|
self.value = None
|
|
self.author_id = author_id
|
|
|
|
async def interaction_check(
|
|
self,
|
|
interaction: Interaction,
|
|
):
|
|
return interaction.user.id == self.author_id
|
|
|
|
@discord.ui.button(
|
|
style=ButtonStyle.primary,
|
|
label="Left",
|
|
)
|
|
async def left(
|
|
self,
|
|
button: discord.ui.Button,
|
|
interaction: Interaction,
|
|
):
|
|
self.value = "left"
|
|
self.stop()
|
|
|
|
@discord.ui.button(
|
|
style=ButtonStyle.primary,
|
|
label="Right",
|
|
)
|
|
async def right(
|
|
self,
|
|
button: discord.ui.Button,
|
|
interaction: Interaction,
|
|
):
|
|
self.value = "right"
|
|
self.stop()
|
|
|
|
|
|
# The last page has the right button disabled, because there's no right page to go to
|
|
class LastPageComps(View):
|
|
def __init__(
|
|
self,
|
|
author_id: int,
|
|
):
|
|
super().__init__()
|
|
self.value = None
|
|
self.author_id = author_id
|
|
|
|
async def interaction_check(
|
|
self,
|
|
interaction: Interaction,
|
|
):
|
|
return interaction.user.id == self.author_id
|
|
|
|
@discord.ui.button(
|
|
style=ButtonStyle.primary,
|
|
label="Left",
|
|
)
|
|
async def left(
|
|
self,
|
|
button: discord.ui.Button,
|
|
interaction: Interaction,
|
|
):
|
|
self.value = "left"
|
|
self.stop()
|
|
|
|
@discord.ui.button(
|
|
style=ButtonStyle.primary,
|
|
label="Right",
|
|
disabled=True,
|
|
)
|
|
async def right(
|
|
self,
|
|
button: discord.ui.Button,
|
|
interaction: Interaction,
|
|
):
|
|
self.value = "right"
|
|
self.stop()
|
|
|
|
|
|
# Now we define the function that will take care of the pagination for us. It will take a list of Embeds and allow the user to cycle between them using left/right buttons
|
|
# There is also an optional title parameter in case you want to give your paginator a title, it will display in the embed title, for example if the title is Book
|
|
# then the title will look like "Book | Page 1/2". This is very optional and can be removed
|
|
async def paginate(
|
|
ctx,
|
|
pages: list,
|
|
title: str = None,
|
|
):
|
|
|
|
total_pages = len(pages)
|
|
first_page = pages[0]
|
|
last_page = pages[-1]
|
|
current_page = first_page
|
|
index = 0
|
|
|
|
embed = first_page
|
|
if title:
|
|
embed.title = f"{title} | Page {index+1}/{total_pages}"
|
|
|
|
view = FirstPageComps(ctx.author.id)
|
|
# Here we send the message with the view of the first page and the FirstPageComps buttons
|
|
msg = await ctx.send(
|
|
embed=embed,
|
|
view=view,
|
|
)
|
|
|
|
# The default timeout for Views is 3 minutes, but if a user selects to scroll between pages the timer will be reset.
|
|
# If the timer reaches 0, though, the loop will just silently stop.
|
|
while True:
|
|
wait = await view.wait()
|
|
if wait:
|
|
return
|
|
|
|
if view.value == "right":
|
|
index += 1
|
|
current_page = pages[index]
|
|
view = MiddlePageComps(ctx.author.id) if current_page != last_page else LastPageComps(ctx.author.id)
|
|
embed = current_page
|
|
if title:
|
|
embed.title = f"{title} | Page {index+1}/{total_pages}"
|
|
|
|
elif view.value == "left":
|
|
index -= 1
|
|
current_page = pages[index]
|
|
view = MiddlePageComps(ctx.author.id) if current_page != first_page else FirstPageComps(ctx.author.id)
|
|
embed = current_page
|
|
if title:
|
|
embed.title = f"{title} | Page {index+1}/{total_pages}"
|
|
|
|
await msg.edit(
|
|
embed=embed,
|
|
view=view,
|
|
)
|
|
|
|
|
|
bot = Bot()
|
|
|
|
# To test our new function, let's create a list of a couple Embeds and let our paginator deal with the sending and buttons
|
|
@bot.command()
|
|
async def sendpages(ctx):
|
|
page1 = Embed(description="This is page 1")
|
|
page2 = Embed(description="This is page 2")
|
|
page3 = Embed(description="This is page 3")
|
|
await paginate(ctx, [page1, page2, page3])
|
|
|
|
|
|
bot.run("token")
|