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

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

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:

  1. import os
  2. import discord
  3. from discord import app_commands
  4. import asyncio
  5. TOKEN='YOUR TOKEN HERE'
  6. GUILD='GUILD NAME HERE'
  7. intents = discord.Intents.default()
  8. intents.message_content = True
  9. client = discord.Client(intents=intents) #I am using client, instead of commands.Bot()
  10. tree = app_commands.CommandTree(client) #This is for the slash command, I am using tree.
  11. @client.event
  12. async def on_ready():
  13. for guild in client.guilds:
  14. if guild.name == GUILD:
  15. break
  16. print(
  17. f'{client.user} has successfully connected to the following guild(s):\n'
  18. f'{guild.name}(id: {guild.id})'
  19. )
  20. await client.change_presence(activity=discord.Activity(name='anything', type=discord.ActivityType.playing))
  21. @tree.command(name='EMBED', description='Description here', guild=discord.Object(id=000000000000000000)) #guild id here
  22. ''' 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:

  1. import os
  2. import discord
  3. from discord import app_commands
  4. import asyncio
  5. TOKEN='YOUR TOKEN HERE'
  6. GUILD='GUILD NAME HERE'
  7. intents = discord.Intents.default()
  8. intents.message_content = True
  9. client = discord.Client(intents=intents) #I am using client, instead of commands.Bot()
  10. tree = app_commands.CommandTree(client) #This is for the slash command, I am using tree.
  11. @client.event
  12. async def on_ready():
  13. for guild in client.guilds:
  14. if guild.name == GUILD:
  15. break
  16. print(
  17. f'{client.user} has successfully connected to the following guild(s):\n'
  18. f'{guild.name}(id: {guild.id})'
  19. )
  20. await client.change_presence(activity=discord.Activity(name='anything', type=discord.ActivityType.playing))
  21. @tree.command(name='EMBED', description='Description here', guild=discord.Object(id=000000000000000000)) #guild id here
  22. ''' 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:

  1. import discord
  2. from typing import Callable, Optional
  3. class Pagination(discord.ui.View):
  4. def __init__(self, interaction: discord.Interaction, get_page: Callable):
  5. self.interaction = interaction
  6. self.get_page = get_page
  7. self.total_pages: Optional[int] = None
  8. self.index = 1
  9. super().__init__(timeout=100)
  10. async def interaction_check(self, interaction: discord.Interaction) -> bool:
  11. if interaction.user == self.interaction.user:
  12. return True
  13. else:
  14. emb = discord.Embed(
  15. description=f"只有命令的作者可以执行此操作。",
  16. color=16711680
  17. )
  18. await interaction.response.send_message(embed=emb, ephemeral=True)
  19. return False
  20. async def navegate(self):
  21. emb, self.total_pages = await self.get_page(self.index)
  22. if self.total_pages == 1:
  23. await self.interaction.response.send_message(embed=emb)
  24. elif self.total_pages > 1:
  25. self.update_buttons()
  26. await self.interaction.response.send_message(embed=emb, view=self)
  27. async def edit_page(self, interaction: discord.Interaction):
  28. emb, self.total_pages = await self.get_page(self.index)
  29. self.update_buttons()
  30. await interaction.response.edit_message(embed=emb, view=self)
  31. def update_buttons(self):
  32. if self.index > self.total_pages // 2:
  33. self.children[2].emoji = "⏮️"
  34. else:
  35. self.children[2].emoji = "⏭️"
  36. self.children[0].disabled = self.index == 1
  37. self.children[1].disabled = self.index == self.total_pages
  38. @discord.ui.button(emoji="◀️", style=discord.ButtonStyle.blurple)
  39. async def previous(self, interaction: discord.Interaction, button: discord.Button):
  40. self.index -= 1
  41. await self.edit_page(interaction)
  42. @discord.ui.button(emoji="▶️", style=discord.ButtonStyle.blurple)
  43. async def next(self, interaction: discord.Interaction, button: discord.Button):
  44. self.index += 1
  45. await self.edit_page(interaction)
  46. @discord.ui.button(emoji="⏭️", style=discord.ButtonStyle.blurple)
  47. async def end(self, interaction: discord.Interaction, button: discord.Button):
  48. if self.index <= self.total_pages//2:
  49. self.index = self.total_pages
  50. else:
  51. self.index = 1
  52. await self.edit_page(interaction)
  53. async def on_timeout(self):
  54. # remove buttons on timeout
  55. message = await self.interaction.original_response()
  56. await message.edit(view=None)
  57. @staticmethod
  58. def compute_total_pages(total_results: int, results_per_page: int) -> int:
  59. 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:

  1. import discord
  2. from pagination import Pagination
  3. users = [f"User {i}" for i in range(1, 10000)]
  4. # This is a long list of results
  5. # I'm going to use pagination to display the data
  6. L = 10 # elements per page
  7. @tree.command(name="show")
  8. async def show(interaction: discord.Interaction):
  9. async def get_page(page: int):
  10. emb = discord.Embed(title="The Users", description="")
  11. offset = (page-1) * L
  12. for user in users[offset:offset+L]:
  13. emb.description += f"{user}\n"
  14. emb.set_author(name=f"Requested by {interaction.user}")
  15. n = Pagination.compute_total_pages(len(users), L)
  16. emb.set_footer(text=f"Page {page} from {n}")
  17. return emb, n
  18. 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:

  1. import discord
  2. from typing import Callable, Optional
  3. class Pagination(discord.ui.View):
  4. def __init__(self, interaction: discord.Interaction, get_page: Callable):
  5. self.interaction = interaction
  6. self.get_page = get_page
  7. self.total_pages: Optional[int] = None
  8. self.index = 1
  9. super().__init__(timeout=100)
  10. async def interaction_check(self, interaction: discord.Interaction) -&gt; bool:
  11. if interaction.user == self.interaction.user:
  12. return True
  13. else:
  14. emb = discord.Embed(
  15. description=f&quot;Only the author of the command can perform this action.&quot;,
  16. color=16711680
  17. )
  18. await interaction.response.send_message(embed=emb, ephemeral=True)
  19. return False
  20. async def navegate(self):
  21. emb, self.total_pages = await self.get_page(self.index)
  22. if self.total_pages == 1:
  23. await self.interaction.response.send_message(embed=emb)
  24. elif self.total_pages &gt; 1:
  25. self.update_buttons()
  26. await self.interaction.response.send_message(embed=emb, view=self)
  27. async def edit_page(self, interaction: discord.Interaction):
  28. emb, self.total_pages = await self.get_page(self.index)
  29. self.update_buttons()
  30. await interaction.response.edit_message(embed=emb, view=self)
  31. def update_buttons(self):
  32. if self.index &gt; self.total_pages // 2:
  33. self.children[2].emoji = &quot;⏮️&quot;
  34. else:
  35. self.children[2].emoji = &quot;⏭️&quot;
  36. self.children[0].disabled = self.index == 1
  37. self.children[1].disabled = self.index == self.total_pages
  38. @discord.ui.button(emoji=&quot;◀️&quot;, style=discord.ButtonStyle.blurple)
  39. async def previous(self, interaction: discord.Interaction, button: discord.Button):
  40. self.index -= 1
  41. await self.edit_page(interaction)
  42. @discord.ui.button(emoji=&quot;▶️&quot;, style=discord.ButtonStyle.blurple)
  43. async def next(self, interaction: discord.Interaction, button: discord.Button):
  44. self.index += 1
  45. await self.edit_page(interaction)
  46. @discord.ui.button(emoji=&quot;⏭️&quot;, style=discord.ButtonStyle.blurple)
  47. async def end(self, interaction: discord.Interaction, button: discord.Button):
  48. if self.index &lt;= self.total_pages//2:
  49. self.index = self.total_pages
  50. else:
  51. self.index = 1
  52. await self.edit_page(interaction)
  53. async def on_timeout(self):
  54. # remove buttons on timeout
  55. message = await self.interaction.original_response()
  56. await message.edit(view=None)
  57. @staticmethod
  58. def compute_total_pages(total_results: int, results_per_page: int) -&gt; int:
  59. 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:

  1. import discord
  2. from pagination import Pagination
  3. users = [f&quot;User {i}&quot; for i in range(1, 10000)]
  4. # This is a long list of results
  5. # I&#39;m going to use pagination to display the data
  6. L = 10 # elements per page
  7. @tree.command(name=&quot;show&quot;)
  8. async def show(interaction: discord.Interaction):
  9. async def get_page(page: int):
  10. emb = discord.Embed(title=&quot;The Users&quot;, description=&quot;&quot;)
  11. offset = (page-1) * L
  12. for user in users[offset:offset+L]:
  13. emb.description += f&quot;{user}\n&quot;
  14. emb.set_author(name=f&quot;Requested by {interaction.user}&quot;)
  15. n = Pagination.compute_total_pages(len(users), L)
  16. emb.set_footer(text=f&quot;Page {page} from {n}&quot;)
  17. return emb, n
  18. 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:

确定