Вы можете установить последнюю версию библиотеки 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Эта библиотека поставляется с несколькими методами и вариантами, чтобы сделать меню реакции раздора простым. После того, как вы импортируете надлежащие классы, вы инициализируете конструктор, как SO:
menu = ReactionMenu ( method , menu_type = ReactionMenu . TypeEmbed )method ( Union[discord.ext.commands.Context, discord.Interaction] ) Контекст или объект взаимодействияmenu_type ( MenuType ) Конфигурация менюReactionMenu.TypeEmbedReactionMenu.TypeEmbedDynamic .ReactionMenu.TypeText , только текстовое меню страниц.| Имя | Тип | Значение по умолчанию | Используется для | Информация |
|---|---|---|---|---|
wrap_in_codeblock | str | None | ReactionMenu.TypeEmbedDynamic | Идентификатор языка кода дискорда 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 |
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 , страницы могут быть либо str , discord.Embed , либо комбинацией content и files (пример ниже)
menu_type - это ReactionMenu.TypeEmbedmenu_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 с TypeEmbed , на каждой странице всегда должно быть встроено. Если menu_type был TypeText , встраивания не разрешены, и вы будете ограничены только использованием параметра files .
Динамическое меню используется, когда вы не знаете, сколько информации будет применяться к меню. Например, если вы должны запросить информацию из базы данных, эта информация всегда может измениться. Вы запрашиваете что -то, и вы можете получить 1500 результатов назад, а в следующем, может быть, всего 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 - Идентификатор языка при обворачивании данных в код Discord 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 с ReactionButton.Type.CALLER |
event | ReactionButton.Event | None | Определите, когда кнопка должна быть удалена в зависимости от того, сколько раз она нажимала |
skip | ReactionButton.Skip | None | Установите действие и количество страниц, чтобы пропустить при использовании linked_to of ReactionButton.Type.SKIP . Например, используя этот тип кнопки, установите действие на «+» и сумму 3. Если вы находитесь на «Страница 1/20», нажатие этой кнопки приведет вас на «Страница 4/20» |
| Свойство | Возврат тип | Информация |
|---|---|---|
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 .
Примечание. Реакция Buttons с
ReactionButton.Type.CALLERнемного отличается, поэтому существует выделенный раздел, объясняющий, как они работают и как их реализовать ниже ниже
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 есть details Kwarg, и это то, что вы используете с .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 поставляется с установленными заводскими методами (методами класса), которые возвращают ReactionButton с параметрами, установленными в соответствии с их linked_to .
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()list ReactionButton в следующем порядке.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_toofReactionButton.Type.END_SESSION
Реле меню - это функции, которые называются в любое время, когда нажимается кнопка, которая находится в стороне от меню. Он считается расширением ReactionButton , носит с помощью linked_to of ReactionButton.Type.CALLER . В отличие от кнопок Caller, которые не дают никаких подробностей о взаимодействиях в меню, реле.
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 ), идентификатор канала ( 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 ()Примечание:
send_toне действителен, если меню было запущено в DM
Вот основная реализация 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 | Идентификатор языка кода дискорда, чтобы обернуть ваши данные в. Пример: 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 is ViewMenu.TypeEmbed , используйте Encedsmenu_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 с TypeEmbed , на каждой странице всегда должно быть встроено. Если menu_type был TypeText , встраивания не разрешены, и вы будете ограничены только использованием параметра files .
Динамическое меню используется, когда вы не знаете, сколько информации будет применяться к меню. Например, если вы должны запросить информацию из базы данных, эта информация всегда может измениться. Вы запрашиваете что -то, и вы можете получить 1500 результатов назад, а в следующем, может быть, всего 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 - Идентификатор языка при обворачивании данных в код Discord 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 Hyperlinds в его сообщениях и даже отправьте скрытые сообщения.
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 .
Ниже приведены правила, установленные Discord для кнопок:
custom_id , и не может быть urlurl и не может иметь custom_idstyle ( discord.ButtonStyle ) кнопка стиляlabel ( str ) текст на кнопкеcustom_id ( str ) идентификатор, чтобы определить, какое действие должна предпринять эта кнопка. Доступные идентификаторы: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 для кнопки со стилем discord.ButtonStyle.linkdisabled ( bool ), если кнопка должна быть отключенаfollowup ( ViewButton.Followup ) Сообщение, отправленное после нажатия кнопки. Доступно только для кнопок, которые имеют custom_id ViewButton.ID_CALLER или ViewButton.ID_SEND_MESSAGE . ViewButton.Followup - это класс, в котором есть параметры, аналогичные discord.abc.Messageable.send() , и используется для управления, если сообщение является эфемерным, содержит файл, Enced, TTS и т. Д.event ( ViewButton.Event ) Установите кнопку для отключения или удаления, когда она нажимается определенным количеством раз | Имя | Тип | Значение по умолчанию | Используется для |
|---|---|---|---|
name | str | None | Имя кнопки |
skip | ViewButton.Skip | None | Установите действие и количество страниц, чтобы пропустить при использовании custom_id of ViewButton.ID_SKIP . Например, настройка действия на «+» и сумму 3. Если вы находитесь на «Страница 1/20», нажатие этой кнопки приведет вас на «Страница 4/20» |
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 (...)))Примечание. Когда речь идет о кнопках с помощью
custom_idViewButton.ID_CALLER,ViewButton.ID_SEND_MESSAGE,ViewButton.ID_CUSTOM_EMBEDили кнопок ссылки, вы можете добавить столько, сколько вы хотели бы, чтобы в общей сложности было 25 кнопок или меньше. Для всех других идентификаторов кнопок каждое меню может иметь только одно.
Выбор используется, когда вы хотите классифицировать информацию в своем меню. Выбор может использоваться только тогда TypeEmbed когда меню menu_type Вы должны иметь в виду, что к каждому сообщению могут применяться ограничения на разнообразии в отношении количества элементов пользовательского интерфейса меню (строк).
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 ()Вы можете использовать этот тип выбора, когда вы хотите использовать пользовательский интерфейс, чтобы выбрать страницу для перейти.
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для Ellipsis (...) работает только так, как задумано, если вы добавили «Выбрать» после добавления страниц в меню
@ 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 поставляется с установленными фабричными методами (методами класса), которые возвращают ViewButton с параметрами, установленными в соответствии с их custom_id (исключая кнопки ссылки).
ViewButton.link(label: str, url: str)style : discord.ButtonStyle.linklabel : <label>url : <url>ViewButton.back()style : discord.ButtonStyle.graylabel : "назад"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()list ViewButton в следующем заказе.go_to_first_page() .back() .next() .go_to_last_page() .go_to_page() .end_session()ViewButton.all_with_emojis()emoji list ViewButton.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_idViewButton.ID_END_SESSION
Реле меню - это функции, которые называются в любое время, когда нажимается кнопка, которая находится в стороне от меню. Он рассматривается как расширение ViewButton , с идентификатором ViewButton.ID_CALLER . В отличие от кнопок Caller, которые не дают никаких подробностей о взаимодействиях в меню, реле.
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 ), идентификатор канала ( 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 ()Примечание:
send_toне действителен, если меню было запущено в DM
При остановке меню доступна только один вариант. Если у вас есть несколько параметров как 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 ())