您可以通过以下操作安装库的最新PYPI版本:
$ pip install reactionmenu
或开发版本:
$ pip install git+https://github.com/Defxult/reactionmenu
最低意图
bot = commands . Bot (..., intents = discord . Intents ( messages = True , guilds = True , reactions = True , members = True )) class reactionmenu.ReactionMenu(method: Union[Context, discord.Interaction], /, *, menu_type: MenuType, **kwargs)
ReactionMenu是使用表情符号的菜单,它是自定义行会表情符号或普通表情符号来控制分页过程的菜单。如果您不在寻找任何精美的功能,而只是想要简单的东西,那么这就是要使用的功能。
from reactionmenu import ReactionMenu , ReactionButton该库带有几种方法和选项,以使Discord Reaction菜单变得简单。一旦导入适当的类,您将像这样初始化构造函数:
menu = ReactionMenu ( method , menu_type = ReactionMenu . TypeEmbed )method ( Union[discord.ext.commands.Context, discord.Interaction] )上下文或交互对象menu_type ( MenuType )菜单的配置ReactionMenu.TypeEmbed ,正常的嵌入分页菜单ReactionMenu.TypeEmbedDynamic ,一个带有动态数据的嵌入分页菜单ReactionMenu.TypeText ,仅文本分页菜单| 姓名 | 类型 | 默认值 | 用于 | 信息 |
|---|---|---|---|---|
wrap_in_codeblock | str | None | ReactionMenu.TypeEmbedDynamic | 将您的数据包装在包装中的Discord CodeBlock语言标识符。示例: ReactionMenu(ctx, ..., wrap_in_codeblock='py') |
custom_embed | discord.Embed | None | ReactionMenu.TypeEmbedDynamic | 嵌入对象在添加ReactionMenu.add_row()的数据时使用。用于造型目的 |
delete_on_timeout | bool | False | All menu types | 删除菜单时 |
clear_reactions_after | bool | True | All menu types | 菜单时删除所有反应 |
navigation_speed | str | ReactionMenu.NORMAL | All menu types | 设置如果用户需要等待在“转动”页面之前通过机器人删除反应。设置速度到ReactionMenu.FAST使它无需等待(在每次压力上都不会删除反应),并且可以更快地导航longy菜单 |
only_roles | List[discord.Role] | None | All menu types | 如果设置,则仅允许具有任何给定角色的成员控制菜单。菜单所有者总是可以控制菜单 |
timeout | Union[int, float, None] | 60.0 | All menu types | 菜单时的计时器。可以None超时 |
show_page_director | bool | True | All menu types | 显示在每个嵌入页面的底部。 “第1/20页” |
name | str | None | All menu types | 您可以为菜单设置的名称 |
style | str | "Page $/&" | All menu types | 您可以选择的自定义页面导演样式。 “ $”代表当前页面,”&”表示页面的总量。示例: ReactionMenu(ctx, ..., style='On $ out of &') |
all_can_click | bool | False | All menu types | 设置如果允许每个人在单击按钮时“转动”页面时控制页面 |
delete_interactions | bool | True | All menu types | 当被问及使用ReactionButton.Type.GO_TO_PAGE时,用户通过机器人和响应消息删除提示消息和响应消息 |
rows_requested | int | None | ReactionMenu.TypeEmbedDynamic | 您希望将每个嵌入页面应用于每个ReactionMenu.add_row()的信息量 |
remove_extra_emojis | bool | False | All menu types | 如果为True ,则将所有最初添加到菜单的表情符号(反应)添加到菜单消息中 |
根据menu_type files content页面可以是str , discord.Embed 。
menu_type是ReactionMenu.TypeEmbed ,请使用嵌入menu_type是ReactionMenu.TypeText (仅文本菜单)或ReactionMenu.TypeEmbedDynamic (仅嵌入菜单),请使用字符串。ReactionMenu.add_page(embed: discord.Embed=MISSING, content: Optional[str]=None, files: Optional[Sequence[discord.File]]=None)ReactionMenu.add_pages(pages: Sequence[Union[discord.Embed, str]])ReactionMenu.add_row(data: str)ReactionMenu.remove_all_pages()ReactionMenu.clear_all_row_data()ReactionMenu.remove_page(page_number: int)ReactionMenu.set_main_pages(*embeds: Embed)ReactionMenu.set_last_pages(*embeds: Embed) # ReactionMenu.TypeEmbed
menu = ReactionMenu ( method , menu_type = ReactionMenu . TypeEmbed )
menu . add_page ( summer_embed )
menu . add_page ( winter_embed )
# ReactionMenu.TypeText
menu = ReactionMenu ( method , menu_type = ReactionMenu . TypeText )
menu . add_page ( content = 'Its so hot!' )
menu . add_page ( content = 'Its so cold!' ) TypeText菜单是基于文本的分页菜单。分页过程中不涉及嵌入,只使用纯文本。
使用v3.1.0+ ,您可以使用不仅仅是嵌入或文本的词。您可以组合文本,嵌入以及文件。但是根据menu_type不同,可以限制组合。这是一个菜单的示例,其中包含菜单的menu_type TypeEmbed 。
# You can use regular commands as well
@ bot . tree . command ( description = "These are stacked pages" , guild = discord . Object ( id = ...))
async def stacked ( interaction : discord . Interaction ):
menu = ReactionMenu ( interaction , menu_type = ReactionMenu . TypeEmbed )
menu . add_page ( discord . Embed ( title = "My Embed" ), content = "This content is stacked on top of a file" , files = [ discord . File ( "stacked.py" )])
menu . add_page ( discord . Embed ( title = "Hey Wumpos, can you say hi to the person reading this? ?" ))
menu . add_page ( discord . Embed ( title = "Hi, I'm Wumpos!" ), files = [ discord . File ( "wumpos.gif" )])
menu . add_button ( ReactionButton . back ())
menu . add_button ( ReactionButton . next ())
await menu . start ()由于menu_type type已TypeEmbed ,因此每个页面上总是必须嵌入一个。如果menu_type是TypeText ,则不允许嵌入,您将仅限于使用files参数。
当您不知道将向菜单应用多少信息时,请使用动态菜单。例如,如果您要从数据库请求信息,则该信息始终可以更改。您可以查询一些内容,然后您可能会获得1,500个结果,而接下来只有800个。一个动态菜单为您添加了所有这些信息,并将其添加到嵌入页面中,然后通过大量数据添加。 ReactionMenu.add_row()最好在某种觉得可以循环遍历的某种Iterable中,但仅将您想要的数据添加到菜单页面中。
注意:在动态菜单中,所有添加的数据都放在嵌入的描述部分中。如果您选择使用
custom_embed,则描述中的所有文本都将用您添加的数据覆盖
ReactionMenu.add_row(data: str)ReactionMenu.clear_all_row_data()ReactionMenu.set_main_pages(*embeds: Embed)ReactionMenu.set_last_pages(*embeds: Embed)rows_requested制作新页面之前,每个嵌入页面上想要的行量ReactionMenu(..., rows_requested=5)custom_embed您创建的嵌入式用作嵌入页面。用于您的菜单美学ReactionMenu(..., custom_embed=red_embed)wrap_in_codeblock将数据包裹在不和谐代码块中时的语言标识符。ReactionMenu(..., wrap_in_codeblock='py') menu = ReactionMenu ( ctx , menu_type = ReactionMenu . TypeEmbedDynamic , rows_requested = 5 )
for data in database . request ( 'SELECT * FROM customers' ):
menu . add_row ( data )您可以使用menu.clear_all_row_data()
使用动态菜单时,您看到的唯一嵌入页面是从您添加的数据中。但是,如果您想显示更多的页面,则可以使用方法ReactionMenu.set_main_pages()和ReactionMenu.set_last_pages() 。设置主页,设置的嵌入将是菜单启动时显示的第一个嵌入。设置最后一页是显示的最后一个嵌入
menu . set_main_pages ( welcome_embed , announcement_embed )
for data in get_information ():
menu . add_row ( data )
menu . set_last_pages ( additional_info_embed )
# NOTE: setting main/last pages can be set in any order当您想向执行某个功能的菜单添加反应时,使用按钮/按钮类型。按钮和按钮类型共同使用所需的动作。
class reactionmenu.ReactionButton(*, emoji: str, linked_to: ButtonType, **kwargs)
emoji ( str )您想用作反应的表情符号linked_to ( ReactionButton.Type )按下反应时,这就是决定其要做什么的原因| 姓名 | 类型 | 默认值 | 用于 |
|---|---|---|---|
embed | discord.Embed | None | 按下反应时,转到指定的嵌入 |
name | str | None | 按钮的名称 |
details | 下面的信息 | None | 分配函数,当用ReactionButton.Type.CALLER ReactionButton被按下时,要调用该函数 |
event | ReactionButton.Event | None | 根据按下多少次,确定何时应删除按钮 |
skip | ReactionButton.Skip | None | 使用ReactionButton.Type.SKIP的linked_to时,设置动作和跳过的页面。例如,使用此按钮类型,将操作设置为“+”和金额3。 |
| 财产 | 返回类型 | 信息 |
|---|---|---|
clicked_by | Set[discord.Member] | 单击按钮的成员 |
total_clicks | int | 按钮的点击量 |
last_clicked | Optional[datetime.datetime] | UTC的时间上一次点击按钮的时间 |
menu | Optional[ReactionMenu] | 按钮附加到菜单 |
ReactionMenu.add_button(button: ReactionButton)ReactionMenu.remove_all_buttons()ReactionMenu.remove_button(button: ReactionButton)ReactionMenu.get_button(identity: Union[str, int], *, search_by='name')ReactionButton.set_caller_details(func: Callable[..., None], *args, **kwargs)| 类型 | 信息 |
|---|---|
ReactionButton.Type.NEXT_PAGE | 转到菜单会话中的下一页 |
ReactionButton.Type.PREVIOUS_PAGE | 转到菜单会话中的上一页 |
ReactionButton.Type.GO_TO_FIRST_PAGE | 转到菜单会话中的第一页 |
ReactionButton.Type.GO_TO_LAST_PAGE | 转到菜单会话中的最后一页 |
ReactionButton.Type.GO_TO_PAGE | 提示您要输入您想转到的页面 |
ReactionButton.Type.END_SESSION | 停止会话并删除菜单消息 |
ReactionButton.Type.CUSTOM_EMBED | 与导航按钮分开使用。按下后,转到指定的嵌入 |
ReactionButton.Type.CALLER | 指定要调用的函数时使用的是按钮按钮时的参数 |
ReactionButton.Type.SKIP | 用于通过单个按钮中的多个页面划分 |
您可以使用ReactionButton将按钮(反应)添加到菜单中。以下是如何使用每个ButtonType的示例。
注意:与
ReactionButton.Type.CALLER的ReactionButtons有些不同,因此有一个专用部分解释它们的工作方式以及如何进一步实施它们
menu = ReactionMenu (...)
# first and last pages
fpb = ReactionButton ( emoji = '⏪' , linked_to = ReactionButton . Type . GO_TO_FIRST_PAGE )
lpb = ReactionButton ( emoji = '⏩' , linked_to = ReactionButton . Type . GO_TO_LAST_PAGE )
# go to page
gtpb = ReactionButton ( emoji = '?' , linked_to = ReactionButton . Type . GO_TO_PAGE )
# end session
esb = ReactionButton ( emoji = '⏹️' , linked_to = ReactionButton . Type . END_SESSION )
# custom embed
ceb = ReactionButton ( emoji = '?' , linked_to = ReactionButton . Type . CUSTOM_EMBED , embed = discord . Embed ( title = 'Hello' ))
# skip button
sb = ReactionButton ( emoji = '5️⃣' , linked_to = ReactionButton . Type . SKIP , skip = ReactionButton . Skip ( action = '+' , amount = 5 ))
menu . add_button ( fpb )
...用menu.remove_all_buttons() 。您还可以使用其名称删除单独的按钮,如果您设置了该按钮,或使用menu.remove_button()
ReactionButton.Type.CALLER按钮用于在菜单中实现自己的功能。也许您想添加一个创建文本通道,发送消息或在数据库中添加的按钮,无论它可能是什么。为了与ReactionButton.Type.CALLER一起使用,请使用下面的类方法。
ReactionButton.set_caller_details(func: Callable[..., None], *args, **kwargs)此类方法用于设置一个函数,并且在按下按钮时将调用该函数。 ReactionButton构造函数具有Kwarg的details ,这就是您将使用.set_caller_details()来分配所需值。下面有一些示例有关如何正确实现ReactionButton.Type.CALLER
@ bot . command ()
async def user ( ctx , name , * , message ):
await ctx . send ( f"Hi { name } ! { message } . We're glad you're here!" )
def car ( year , make , model ):
print ( f"I have a { year } { make } { model } " )
ub = ReactionButton ( emoji = '' , linked_to = ReactionButton . Type . CALLER , details = ReactionButton . set_caller_details ( user , ctx , 'Defxult' , message = 'Welcome to the server' ))
cb = ReactionButton ( emoji = '?' , linked_to = ReactionButton . Type . CALLER , details = ReactionButton . set_caller_details ( car , 2021 , 'Ford' , 'Mustang' ))注意:您传递的功能不应返回任何内容。使用
ReactionButton.Type.CALLER调用功能不存储或处理该功能返回的任何内容
ReactionButton类带有设定的工厂方法(类方法),该方法将根据其linked_to设置的参数返回ReactionButton 。
ReactionButton.back()emoji :”linked_to : ReactionButton.Type.PREVIOUS_PAGEReactionButton.next()emoji :”linked_to : ReactionButton.Type.NEXT_PAGEReactionButton.go_to_first_page()emoji :“⏪”linked_to : ReactionButton.Type.GO_TO_FIRST_PAGEReactionButton.go_to_last_page()emoji :“⏩”linked_to : ReactionButton.Type.GO_TO_LAST_PAGEReactionButton.go_to_page()emoji :“?”linked_to : ReactionButton.Type.GO_TO_PAGEReactionButton.end_session()emoji :“⏹️”linked_to : ReactionButton.Type.END_SESSIONReactionButton.all()ReactionButton list.go_to_first_page() .back() .next() .go_to_last_page() .go_to_page() .end_session()ReactionButton.generate_skip(emoji: str, action: str, amount: int)emoji : <emoji>linked_to : ReactionButton.Type.SKIPskip : ReactionButton.Skip(<action>, <amount>)如果您愿意,可以限制每个“行会”,“成员”或“渠道”的反应菜单量
ReactionMenu.set_sessions_limit(limit: int, per='guild', message='Too many active menus. Wait for other menus to be finished.')ReactionMenu.remove_limit()例子:
@ bot . command ()
async def limit ( ctx ):
ReactionMenu . set_sessions_limit ( 3 , per = 'member' , message = 'Sessions are limited to 3 per member' )在上面的示例中,每个成员只能一次活跃3个菜单,如果他们尝试在另一个菜单完成之前创建更多菜单,他们将收到一条错误消息,说“会话限制为每个成员3个”。
您可以设置一个ReactionButton ,以便将其按下一定次
class ReactionButton.Event(event_type: str, value: int)
event_type ( str )要采取的动作。唯一可用的选项是“删除”value ( int )指定事件的设置。必须为> = 1。如果值是<= 0,则隐式设置为1例子:
menu = ReactionMenu ( ctx , ...)
# remove a button after 10 clicks
button = ReactionButton (..., event = ReactionButton . Event ( 'remove' , 10 ))
menu . add_button ( button )注意:对具有
linked_to按钮不理想,ReactionButton.Type.END_SESSION
菜单继电器是函数,随时可以按下菜单中的按钮。它被认为是与ReactionButton.Type.CALLER linked_to的ReactionButton的扩展。与呼叫者按钮不同,该按钮没有提供有关菜单上交互的详细信息,继电器可以。
ReactionMenu.set_relay(func: Callable[[NamedTuple], None], *, only: Optional[List[ReactionButton]]=None)ReactionMenu.remove_relay()为继电器创建函数时,该功能必须包含一个位置参数。按下按钮时, RelayPayload对象(命名元组)将传递给该功能。 RelayPayload的属性是:
member ( discord.Member )按下按钮的人button ( ReactionButton )按下按钮例子:
async def enter_giveaway ( payload ):
member = payload . member
channel = payload . button . menu . message . channel
await channel . send ( f" { member . mention } , you've entered the giveaway!" )
menu = ReactionMenu ( ctx , ...)
menu . set_relay ( enter_giveaway ) set_relay方法带有only参数。如果该参数None ,则所有按下的按钮都将中继。您可以提供该参数的按钮list ,因此只有从指定按钮的按钮按下将中继的按钮。
def example ( payload ):
...
menu = ReactionMenu ( ctx , ...)
back_button = ReactionButton . back ()
next_button = ReactionButton . next ()
menu . set_relay ( example , only = [ back_button ])await ReactionMenu.start(*, send_to=None, reply=False)await ReactionMenu.stop(*, delete_menu_message=False, clear_reactions=False)启动菜单时,您可以选择将菜单发送到某个频道。参数send_to是您要将菜单发送到的频道。您可以将send_to设置为频道名称( str ),通道ID( int )或通道对象( discord.TextChannel / discord.Thread )。例子:
menu = ReactionMenu (...)
# channel name
await menu . start ( send_to = 'bot-commands' )
# channel ID
await menu . start ( send_to = 1234567890123456 )
# channel object
channel = guild . get_channel ( 1234567890123456 )
await menu . start ( send_to = channel )
# there's no need to specify send_to unless you want the menu to be sent to a different channel
# from the one you're sending the initial message/using the command in. the menu can be started
# in the current channel by omitting the send_to parameter
await menu . start ()注意:如果DM的菜单启动了菜单,则
send_to无效
这是ReactionMenu的基本实现,您可以复制和粘贴以进行快速演示。
import asyncio
import discord
from discord . ext import commands
from reactionmenu import ReactionMenu , ReactionButton
bot = commands . Bot ( command_prefix = '!' , intents = discord . Intents . all ())
async def start_bot ():
async with bot :
await bot . start ( '...' )
@ bot . command ()
async def example ( ctx ):
menu = ReactionMenu ( ctx , menu_type = ReactionMenu . TypeEmbed )
for member in ctx . guild . members :
if member . avatar :
embed = discord . Embed ( description = f'Joined { member . joined_at . strftime ( "%b. %d, %Y" ) } ' )
embed . set_author ( name = member . name , icon_url = member . avatar . url )
menu . add_page ( embed )
menu . add_button ( ReactionButton . back ())
menu . add_button ( ReactionButton . next ())
menu . add_button ( ReactionButton . end_session ())
await menu . start ()
asyncio . run ( start_bot ()) class reactionmenu.ViewMenu(method: Union[Context, discord.Interaction], /, *, menu_type: MenuType, **kwargs)
ViewMenu是使用Discords按钮功能的菜单。使用按钮,您可以启用和禁用它们,用表情符号为它们设置某些颜色,具有发送隐藏消息的按钮并添加超链接。该库提供了更广泛的功能,例如谁按下了按钮,按下了多少次以及更多的次数。它使用视图( discord.ui.View )来实现按钮功能,但是使用其一些自己的方法来简单地使按钮分页菜单。
from reactionmenu import ViewMenu , ViewButtonmethod ( Union[discord.ext.commands.Context, discord.Interaction] )上下文或交互对象menu_type ( MenuType )菜单的配置ViewMenu.TypeEmbed ,一个普通的嵌入分页菜单ViewMenu.TypeEmbedDynamic ,带有动态数据的嵌入分页菜单ViewMenu.TypeText ,仅文本分页菜单| 姓名 | 类型 | 默认值 | 用于 | 信息 |
|---|---|---|---|---|
wrap_in_codeblock | str | None | ViewMenu.TypeEmbedDynamic | 将您的数据包装在中的Discord CodeBlock语言标识符。示例: ViewMenu(ctx, ..., wrap_in_codeblock='py') |
custom_embed | discord.Embed | None | ViewMenu.TypeEmbedDynamic | 嵌入对象使用ViewMenu.add_row()添加数据时使用的对象。用于造型目的 |
delete_on_timeout | bool | False | All menu types | 删除菜单时 |
disable_items_on_timeout | bool | True | All menu types | 菜单限制菜单上的项目 |
remove_items_on_timeout | bool | False | All menu types | 菜单时间删除菜单上的项目 |
only_roles | List[discord.Role] | None | All menu types | 如果设置,则仅允许具有任何给定角色的成员控制菜单。菜单所有者总是可以控制菜单 |
timeout | Union[int, float, None] | 60.0 | All menu types | 菜单时的计时器。可以None超时 |
show_page_director | bool | True | All menu types | 显示在每个嵌入页面的底部。 “第1/20页” |
name | str | None | All menu types | 您可以为菜单设置的名称 |
style | str | "Page $/&" | All menu types | 您可以选择的自定义页面导演样式。 “ $”代表当前页面,”&”表示页面的总量。示例: ViewMenu(ctx, ..., style='On $ out of &') |
all_can_click | bool | False | All menu types | 设置如果允许每个人在单击按钮时“转动”页面时控制页面 |
delete_interactions | bool | True | All menu types | 当询问使用ViewButton.ID_GO_TO_PAGE时,用户通过机器人和响应消息删除提示消息和响应消息 |
rows_requested | int | None | ViewMenu.TypeEmbedDynamic | 您要应用于每个嵌入页面的每个ViewMenu.add_row() |
根据menu_type不同,页面可以是str , discord.Embed ,或content或files组合(下面的示例)
menu_type是ViewMenu.TypeEmbed ,请使用嵌入menu_type是ViewMenu.TypeText (仅文本菜单)或ViewMenu.TypeEmbedDynamic (仅嵌入菜单),请使用字符串。ViewMenu.add_page(embed: discord.Embed=MISSING, content: Optional[str]=None, files: Optional[Sequence[discord.File]]=None)ViewMenu.add_pages(pages: Sequence[Union[discord.Embed, str]])ViewMenu.add_row(data: str)ViewMenu.remove_all_pages()ViewMenu.clear_all_row_data()ViewMenu.remove_page(page_number: int)ViewMenu.set_main_pages(*embeds: Embed)ViewMenu.set_last_pages(*embeds: Embed) # ViewMenu.TypeEmbed
menu = ViewMenu ( method , menu_type = ViewMenu . TypeEmbed )
menu . add_page ( summer_embed )
menu . add_page ( winter_embed )
# ViewMenu.TypeText
menu = ViewMenu ( method , menu_type = ViewMenu . TypeText )
menu . add_page ( content = 'Its so hot!' )
menu . add_page ( content = 'Its so cold!' ) TypeText菜单是基于文本的分页菜单。分页过程中不涉及嵌入,只使用纯文本。
使用v3.1.0+ ,您可以使用不仅仅是嵌入或文本的词。您可以组合文本,嵌入以及文件。但是根据menu_type不同,可以限制组合。这是一个菜单的示例,其中包含菜单的menu_type TypeEmbed 。
# You can use regular commands as well
@ bot . tree . command ( description = "These are stacked pages" , guild = discord . Object ( id = ...))
async def stacked ( interaction : discord . Interaction ):
menu = ViewMenu ( interaction , menu_type = ViewMenu . TypeEmbed )
menu . add_page ( discord . Embed ( title = "My Embed" ), content = "This content is stacked on top of a file" , files = [ discord . File ( "stacked.py" )])
menu . add_page ( discord . Embed ( title = "Hey Wumpos, can you say hi to the person reading this? ?" ))
menu . add_page ( discord . Embed ( title = "Hi, I'm Wumpos!" ), files = [ discord . File ( "wumpos.gif" )])
menu . add_button ( ViewButton . back ())
menu . add_button ( ViewButton . next ())
await menu . start ()由于menu_type type已TypeEmbed ,因此每个页面上总是必须嵌入一个。如果menu_type是TypeText ,则不允许嵌入,您将仅限于使用files参数。
当您不知道将向菜单应用多少信息时,请使用动态菜单。例如,如果您要从数据库请求信息,则该信息始终可以更改。您可以查询一些内容,然后您可能会获得1,500个结果,而接下来只有800个。一个动态菜单为您添加了所有这些信息,并将其添加到嵌入页面中,然后通过大量数据添加。 ViewMenu.add_row()最适合在某种Iterable使用,其中所有内容都可以通过,但仅将您想要的数据添加到菜单页面中。
注意:在动态菜单中,所有添加的数据都放在嵌入的描述部分中。如果您选择使用
custom_embed,则描述中的所有文本都将用您添加的数据覆盖
ViewMenu.add_row(data: str)ViewMenu.clear_all_row_data()ViewMenu.set_main_pages(*embeds: Embed)ViewMenu.set_last_pages(*embeds: Embed)rows_requested制作新页面之前,每个嵌入页面上想要的行量ViewMenu(..., rows_requested=5)custom_embed您创建的嵌入式用作嵌入页面。用于您的菜单美学ViewMenu(..., custom_embed=red_embed)wrap_in_codeblock将数据包裹在不和谐代码块中时的语言标识符。ViewMenu(..., wrap_in_codeblock='py') menu = ViewMenu ( ctx , menu_type = ViewMenu . TypeEmbedDynamic , rows_requested = 5 )
for data in database . request ( 'SELECT * FROM customers' ):
menu . add_row ( data )您可以使用menu.clear_all_row_data()
使用动态菜单时,您看到的唯一嵌入页面是从您添加的数据中。但是,如果您想显示更多的页面,则可以使用方法ViewMenu.set_main_pages()和ViewMenu.set_last_pages() 。设置主页,设置的嵌入将是菜单启动时显示的第一个嵌入。设置最后一页是显示的最后一个嵌入
menu . set_main_pages ( welcome_embed , announcement_embed )
for data in get_information ():
menu . add_row ( data )
menu . set_last_pages ( additional_info_embed )
# NOTE: setting main/last pages can be set in any order按钮是您与菜单进行交互的内容。与反应不同,它们看起来更清洁,提供较小的速率限制问题,并在互动方面提供更多。启用和禁用按钮,在消息中使用Markdown超链接,甚至发送隐藏的消息。
ViewMenu.add_button(button: ViewButton)ViewMenu.disable_all_buttons()ViewMenu.disable_button(button: ViewButton)ViewMenu.enable_all_buttons()ViewMenu.enable_button(button: ViewButton)ViewMenu.get_button(identity: str, *, search_by='label')ViewMenu.remove_all_buttons()ViewMenu.remove_button(button: ViewButton)await ViewMenu.refresh_menu_items() class reactionmenu.ViewButton(*, style=discord.ButtonStyle.secondary, label=None, disabled=False, custom_id=None, url=None, emoji=None, followup=None, event=None, **kwargs)
ViewButton是代表Discord按钮的类。它是discord.ui.Button的子类。
以下是按钮设置的规则:
custom_id ,并且不能有urlurl ,并且不能具有custom_idstyle ( discord.ButtonStyle )按钮样式label ( str )按钮上的文本custom_id ( str )一个ID来确定该按钮应采取的操作。可用ID:ViewButton.ID_NEXT_PAGEViewButton.ID_PREVIOUS_PAGEViewButton.ID_GO_TO_FIRST_PAGEViewButton.ID_GO_TO_LAST_PAGEViewButton.ID_GO_TO_PAGEViewButton.ID_END_SESSIONViewButton.ID_CALLERViewButton.ID_SEND_MESSAGEViewButton.ID_CUSTOM_EMBEDViewButton.ID_SKIPemoji ( Union[str, discord.PartialEmoji] )表情符号用于按钮ViewButton(..., emoji='?')ViewButton(..., emoji='<:miscTwitter:705423192818450453>')ViewButton(..., emoji='U000027a1')ViewButton(..., emoji='N{winking face}')url ( str )url for fins style discord.ButtonStyle.linkdisabled ( bool )如果应禁用该按钮followup ( ViewButton.Followup )按下按钮后发送的消息。仅适用于具有ViewButton.ID_CALLER或ViewButton.ID_SEND_MESSAGE的custom_id 。 ViewButton.Followup是一个类似于discord.abc.Messageable.send()的参数的类,用于控制消息是否是短暂的,包含文件,嵌入,tts等...event ( ViewButton.Event )设置一个按下要禁用或删除的按钮,请按一定的次数| 姓名 | 类型 | 默认值 | 用于 |
|---|---|---|---|
name | str | None | 按钮的名称 |
skip | ViewButton.Skip | None | 使用ViewButton.ID_SKIP的custom_id时,设置操作和跳过的页面。例如,将操作设置为“+”和金额3。 |
persist | bool | False | 防止链接按钮在菜单时间出门或停止时被禁用/删除 |
| 财产 | 返回类型 | 信息 |
|---|---|---|
clicked_by | Set[discord.Member] | 单击按钮的成员 |
total_clicks | int | 按钮的点击量 |
last_clicked | Optional[datetime.datetime] | UTC的时间上一次点击按钮的时间 |
menu | Optional[ViewMenu] | 按钮附加到菜单 |
from reactionmenu import ViewMenu , ViewButton
menu = ViewMenu ( ctx , menu_type = ViewMenu . TypeEmbed )
# Link button
link_button = ViewButton ( style = discord . ButtonStyle . link , emoji = '?' , label = 'Link to Google' , url = 'https://google.com' )
menu . add_button ( link_button )
# Skip button
skip = ViewButton ( style = discord . ButtonStyle . primary , label = '+5' , custom_id = ViewButton . ID_SKIP , skip = ViewButton . Skip ( action = '+' , amount = 5 ))
menu . add_button ( skip )
# ViewButton.ID_PREVIOUS_PAGE
back_button = ViewButton ( style = discord . ButtonStyle . primary , label = 'Back' , custom_id = ViewButton . ID_PREVIOUS_PAGE )
menu . add_button ( back_button )
# ViewButton.ID_NEXT_PAGE
next_button = ViewButton ( style = discord . ButtonStyle . secondary , label = 'Next' , custom_id = ViewButton . ID_NEXT_PAGE )
menu . add_button ( next_button )
# All other ViewButton are created the same way as the last 2 EXCEPT
# 1 - ViewButton.ID_CALLER
# 2 - ViewButton.ID_SEND_MESSAGE
# 3 - ViewButton.ID_CUSTOM_EMBED
# ViewButton.ID_CALLER
def say_hello ( name : str ):
print ( 'Hello' , name )
call_followup = ViewButton . Followup ( details = ViewButton . Followup . set_caller_details ( say_hello , 'John' ))
menu . add_button ( ViewButton ( label = 'Say hi' , custom_id = ViewButton . ID_CALLER , followup = call_followup ))
# ViewButton.ID_SEND_MESSAGE
msg_followup = ViewButton . Followup ( 'This message is hidden!' , ephemeral = True )
menu . add_button ( ViewButton ( style = discord . ButtonStyle . green , label = 'Message' , custom_id = ViewButton . ID_SEND_MESSAGE , followup = msg_followup ))
# ViewButton.ID_CUSTOM_EMBED
custom_embed_button = ViewButton ( style = discord . ButtonStyle . blurple , label = 'Social Media Info' , custom_id = ViewButton . ID_CUSTOM_EMBED , followup = ViewButton . Followup ( embed = discord . Embed (...)))注意:当涉及使用
ViewButton.ID_CALLER的custom_id的按钮时,ViewButton.ID_SEND_MESSAGE,ViewButton.ID_CUSTOM_EMBED或链接按钮,您可以添加尽可能多的数量,最多是25个按钮或更少的按钮。对于所有其他按钮ID,每个菜单只能有一个。
当您想在菜单中对信息进行分类时,请使用选择。只有在菜单的menu_type type被TypeEmbed时才能使用选择。您应该记住,不满限制可以应用于每个消息的菜单UI项目(行)。
Page.from_embeds(embeds: Sequence[Embed])ViewMenu.add_select(select: ViewSelect)ViewMenu.remove_select(select: ViewSelect)ViewMenu.remove_all_selects()ViewMenu.disable_select(select: ViewSelect)ViewMenu.disable_all_selects()ViewMenu.enable_select(select: ViewSelect)ViewMenu.enable_all_selects()ViewMenu.get_select(title: Union[str, None])例子:
from reactionmenu import ViewMenu , ViewSelect , Page
menu = ViewMenu ( ctx , menu_type = ViewMenu . TypeEmbed )
menu . add_page ( discord . Embed ( title = "A showcase of console video games" , color = discord . Color . blurple ()))
menu . add_select ( ViewSelect ( title = "Console Video Games" , options = {
# NOTE: The discord.SelectOption parameter "default" cannot be set to True
discord . SelectOption ( label = "PlayStation" , emoji = "<:PlayStation:549638412538478602>" ) : [
Page ( embed = discord . Embed ( title = "Ratchet & Clank" , description = ..., color = discord . Color . yellow ()). set_image ( url = ...)),
Page ( embed = discord . Embed ( title = "God of War" , description = ..., color = discord . Color . blue ()). set_image ( url = ...))
],
discord . SelectOption ( label = "Xbox" , emoji = "<:Xbox:501880493285834752>" ) : [
Page ( embed = discord . Embed ( title = "Halo Infinite" , description = ..., color = discord . Color . green ()). set_image ( url = ...)),
Page ( embed = discord . Embed ( title = "Gears of War 4" , description = ..., color = discord . Color . red ()). set_image ( url = ...))
]
}))
menu . add_button ( ViewButton . back ())
menu . add_button ( ViewButton . next ())
await menu . start ()当您想使用UI选择要转到的页面时,您可以使用此类型的选择。
ViewMenu.add_go_to_select(goto: ViewSelect.GoTo)ViewMenu.enable_go_to_select(goto: ViewSelect.GoTo)ViewMenu.enable_all_go_to_selects()ViewMenu.disable_go_to_select(goto: ViewSelect.GoTo)ViewMenu.disable_all_go_to_selects()ViewMenu.remove_go_to_select(goto: ViewSelect.GoTo)ViewMenu.remove_all_go_to_selects() page_numbers参数ViewSelect.GoTo可以与3种不同类型一起使用
List[int]如果设置为整数列表,则指定的值是单击选择时唯一可用的选项page_numbers=[1, 5, 10]Dict[int, Union[str, discord.Emoji, discord.PartialEmoji]]如果您想在选择中使用表情符号,则可以使用此类型page_numbers={1 : "?️", 2 : ""}ellipsis您可以设置一个字面的省略号,以使库自动将所有页码分配给您已添加到菜单的页面。如果您有25页或更少,这可能会派上用场page_numbers=...注意:将
page_numbers参数设置为省略(...),只有在添加到select的go中,才能按照预期的方式工作。
@ bot . command ()
async def navigate ( ctx ):
menu = ViewMenu ( ctx , menu_type = ViewMenu . TypeEmbed )
menu . add_page ( discord . Embed ( title = "Twitter" ). set_image ( url = "..." ))
menu . add_page ( discord . Embed ( title = "YouTube" ). set_image ( url = "..." ))
menu . add_page ( discord . Embed ( title = "Discord" ). set_image ( url = "..." ))
# ...
menu . add_go_to_select ( ViewSelect . GoTo ( title = "Go to page..." , page_numbers = ...))
menu . add_button ( ViewButton . back ())
menu . add_button ( ViewButton . next ())
await menu . start ()await ViewMenu.refresh_menu_items()await ViewMenu.update(*, new_pages: Union[List[Union[Embed, str]], None], new_buttons: Union[List[ViewButton], None])菜单运行后,您可以更新菜单上的页面或按钮。使用ViewMenu.update() ,您可以替换页面和按钮。使用ViewMenu.refresh_menu_items()更新您已更改的按钮。
@ bot . command ()
async def menu ( ctx ):
menu = ViewMenu (..., name = 'test' )
link_button = ViewButton (..., label = 'Link' )
menu . add_button ( link_button )
menu . add_page (...)
await menu . start ()
@ bot . command ()
async def disable ( ctx ):
menu = ViewMenu . get_session ( 'test' )
link_button = menu [ 0 ]. get_button ( 'Link' , search_by = 'label' )
menu . disable_button ( link_button )
await menu . refresh_menu_items ()如果未使用ViewMenu.refresh_menu_items()刷新按钮,则在更改按钮时不会更新菜单。
当您要替换菜单上的全部或几个按钮时,使用方法ViewMenu.update(...) 。
menu = ViewMenu (...)
# in a different .command()
await menu . update ( new_pages = [ hello_embed , goodbye_embed ], new_buttons = [ link_button , next_button ])注意:使用
ViewMenu.update(...)时,无需使用ViewMenu.refresh_menu_items()因为它们在更新调用中进行了更新。
ViewButton类带有设置的Factory方法(类方法),该方法返回具有根据其custom_id (不包括链接按钮)设置的参数的ViewButton 。
ViewButton.link(label: str, url: str)style : discord.ButtonStyle.linklabel : <label>url : <url>ViewButton.back()style : discord.ButtonStyle.graylabel :“ Back”custom_id : ViewButton.ID_PREVIOUS_PAGEViewButton.next()style : discord.ButtonStyle.graylabel :“下一步”custom_id : ViewButton.ID_NEXT_PAGEViewButton.go_to_first_page()style : discord.ButtonStyle.graylabel :“第一页”custom_id : ViewButton.ID_GO_TO_FIRST_PAGEViewButton.go_to_last_page()style : discord.ButtonStyle.graylabel :“最后一页”custom_id : ViewButton.ID_GO_TO_LAST_PAGEViewButton.go_to_page()style : discord.ButtonStyle.graylabel :“页面选择”custom_id : ViewButton.ID_GO_TO_PAGEViewButton.end_session()discord.ButtonStyle.grayViewButton.ID_END_SESSIONViewButton.all()ViewButton list.go_to_first_page() .back() .next() .go_to_last_page() .go_to_page() .end_session()ViewButton.all_with_emojis()emoji参数的ViewButton list.go_to_first_page() .back() .next() .go_to_last_page() .go_to_page() .end_session()ViewButton.generate_skip(label: str, action: str, amount: int)style : discord.ButtonStyle.graylabel : <label>custom_id : ViewButton.ID_SKIPskip : ViewButton.Skip(<action>, <amount>) menu = ViewMenu ( ctx , ...)
menu . add_page (...)
menu . add_page (...)
menu . add_button ( ViewButton . back ())
menu . add_button ( ViewButton . next ())
await menu . start ()您可以将ViewButton设置为被禁用或删除的视图顿
class ViewButton.Event(event_type: str, value: int)
event_type ( str )要采取的动作。可以是“禁用”或“删除”value ( int )指定事件的设置。必须为> = 1。如果值是<= 0,则隐式设置为1例子:
menu = ViewMenu ( ctx , ...)
# disable a button after 5 clicks
button_1 = ViewButton (..., event = ViewButton . Event ( 'disable' , 5 ))
menu . add_button ( button_1 )
# remove a button after 10 clicks
button_2 = ViewButton (..., event = ViewButton . Event ( 'remove' , 10 ))
menu . add_button ( button_2 )注意:对链接按钮无效。也不理想使用
custom_idofViewButton.ID_END_SESSION的按钮
菜单继电器是函数,随时可以按下菜单中的按钮。它被认为是具有ViewButton.ID_CALLER ID的ViewButton的扩展。与呼叫者按钮不同,该按钮没有提供有关菜单上交互的详细信息,继电器可以。
ViewMenu.set_relay(func: Callable[[NamedTuple], None], *, only: Optional[List[ViewButton]]=None)ViewMenu.remove_relay()为继电器创建函数时,该功能必须包含一个位置参数。按下按钮时, RelayPayload对象(命名元组)将传递给该功能。 RelayPayload的属性是:
member ( discord.Member )按下按钮的人button ( ViewButton )按下按钮例子:
async def enter_giveaway ( payload ):
member = payload . member
channel = payload . button . menu . message . channel
await channel . send ( f" { member . mention } , you've entered the giveaway!" )
menu = ViewMenu ( ctx , ...)
menu . set_relay ( enter_giveaway ) set_relay方法带有only参数。如果该参数None ,则所有按下的按钮都将中继(链接按钮除外,因为它们不发送交互事件)。您可以提供该参数的按钮list ,因此只有从指定按钮的按钮按下将中继的按钮。
def example ( payload ):
...
menu = ViewMenu ( ctx , ...)
back_button = ViewButton . back ()
next_button = ViewButton . next ()
menu . set_relay ( example , only = [ back_button ])await ViewMenu.start(*, send_to=None, reply=False)await ViewMenu.stop(*, delete_menu_message=False, remove_buttons=False, disable_buttons=False)启动菜单时,您可以选择将菜单发送到某个频道。参数send_to是您要将菜单发送到的频道。您可以将send_to设置为频道名称( str ),通道ID( int )或通道对象( discord.TextChannel / discord.Thread )。例子:
menu = ViewMenu (...)
# channel name
await menu . start ( send_to = 'bot-commands' )
# channel ID
await menu . start ( send_to = 1234567890123456 )
# channel object
channel = guild . get_channel ( 1234567890123456 )
await menu . start ( send_to = channel )
# there's no need to specify send_to unless you want the menu to be sent to a different channel
# from the one you're sending the initial message/using the command in. the menu can be started
# in the current channel by omitting the send_to parameter
await menu . start ()注意:如果DM的菜单启动了菜单,则
send_to无效
停止菜单时只有一个选项。如果您有多个参数为True ,则只有一个将执行
delete_menu_message > disable_buttonsdisable_buttons > remove_buttons这是ViewMenu的基本实现,您可以复制和粘贴以快速演示。
import asyncio
import discord
from discord . ext import commands
from reactionmenu import ViewMenu , ViewButton
bot = commands . Bot ( command_prefix = '!' , intents = discord . Intents . all ())
async def start_bot ():
async with bot :
await bot . start ( '...' )
@ bot . command ()
async def example ( ctx ):
menu = ViewMenu ( ctx , menu_type = ViewMenu . TypeEmbed )
for member in ctx . guild . members :
if member . avatar :
embed = discord . Embed ( description = f'Joined { member . joined_at . strftime ( "%b. %d, %Y" ) } ' )
embed . set_author ( name = member . name , icon_url = member . avatar . url )
menu . add_page ( embed )
menu . add_button ( ViewButton . back ())
menu . add_button ( ViewButton . next ())
menu . add_button ( ViewButton . end_session ())
await menu . start ()
asyncio . run ( start_bot ())