如何在discord.py中创建分页嵌入菜单?

huangapple go评论71阅读模式
英文:

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:

Screenshot of what I wanted.

Extra Info:

  1. I am using client instead of Commands.Bot()
  2. I am using tree for Slash commands.
  3. discord_slash is not compatible with my discord.py version.
  4. Slash command is necessary for me.
  5. 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:

Screenshot of what I wanted.

Extra Info:

  1. I am using client instead of Commands.Bot()
  2. I am using tree for Slash commands.
  3. discord_slash is not compatible with my discord.py version.
  4. Slash command is necessary for me.
  5. 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. 如何在discord.py中创建分页嵌入菜单?

英文:

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) -&gt; bool:
        if interaction.user == self.interaction.user:
            return True
        else:
            emb = discord.Embed(
                description=f&quot;Only the author of the command can perform this action.&quot;,
                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 &gt; 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 &gt; self.total_pages // 2:
            self.children[2].emoji = &quot;⏮️&quot;
        else:
            self.children[2].emoji = &quot;⏭️&quot;
        self.children[0].disabled = self.index == 1
        self.children[1].disabled = self.index == self.total_pages

    @discord.ui.button(emoji=&quot;◀️&quot;, 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=&quot;▶️&quot;, 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=&quot;⏭️&quot;, style=discord.ButtonStyle.blurple)
    async def end(self, interaction: discord.Interaction, button: discord.Button):
        if self.index &lt;= 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) -&gt; 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&quot;User {i}&quot; for i in range(1, 10000)]
# This is a long list of results
# I&#39;m going to use pagination to display the data
L = 10    # elements per page


@tree.command(name=&quot;show&quot;)
async def show(interaction: discord.Interaction):
    async def get_page(page: int):
        emb = discord.Embed(title=&quot;The Users&quot;, description=&quot;&quot;)
        offset = (page-1) * L
        for user in users[offset:offset+L]:
            emb.description += f&quot;{user}\n&quot;
        emb.set_author(name=f&quot;Requested by {interaction.user}&quot;)
        n = Pagination.compute_total_pages(len(users), L)
        emb.set_footer(text=f&quot;Page {page} from {n}&quot;)
        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.
如何在discord.py中创建分页嵌入菜单?

huangapple
  • 本文由 发表于 2023年5月14日 21:49:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76247812.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定