最新の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このライブラリには、不一致の反応メニューをシンプルにするためのいくつかの方法とオプションがあります。適切なクラスをインポートしたら、次のようなコンストラクターを初期化します。
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 Language Identifier fone Data in 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.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に応じて、組み合わせを制限できます。以下は、積み重ねられているTypeEmbedのmenu_typeを備えたメニューの例です。
# 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パラメーターのみを使用することに制限されます。
メニューにどれだけの情報が適用されるかわからない場合、動的メニューが使用されます。たとえば、データベースから情報を要求する場合、その情報は常に変更される可能性があります。あなたは何かを照会すると、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 -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()
ダイナミックメニューを使用する場合、表示される唯一の埋め込みページは、追加したデータからです。ただし、データだけ以外のページを表示したい場合は、method 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使用するときにスキップするアクションとページの量を設定します。たとえば、このボタンタイプを使用して、アクションを「+」と量に設定します。「ページ1/20」にある場合、そのボタンを押すと「Page 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 | 1つのボタンを押すと複数のページを介してページングするために使用されます |
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 )注:
ReactionButton.Type.END_SESSIONのlinked_to備えたボタンには理想的ではありません
メニューリレーは、メニューの一部であるボタンが押されているときにいつでも呼び出される関数です。 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 Language Identifier fone Your Datain。emply: 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に応じて、組み合わせを制限できます。以下は、積み重ねられているTypeEmbedのmenu_typeを備えたメニューの例です。
# 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パラメーターのみを使用することに制限されます。
メニューにどれだけの情報が適用されるかわからない場合、動的メニューが使用されます。たとえば、データベースから情報を要求する場合、その情報は常に変更される可能性があります。あなたは何かを照会すると、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 -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()
ダイナミックメニューを使用する場合、表示される唯一の埋め込みページは、追加したデータからです。ただし、データだけ以外のページを表示したい場合は、method 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ボタンは、メニューと対話するために使用するものです。反応とは異なり、それらはよりクリーンに見え、より少ないレートの制限の問題を提供し、相互作用の点でより多くを提供します。ボタンを有効にして無効にし、メッセージのマークダウンハイパーリンクを使用し、非表示のメッセージを送信します。
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.ui.Buttonのサブクラスです。
以下は、ボタン用のDiscordによって設定されたルールです。
custom_idが必要で、 urlを持たない必要がありますurlが必要で、 custom_idを持つことはできませんstyle ( 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}')discord.ButtonStyle.linkを使用したボタン用のurl ( str )urldisabledにする必要がある場合( 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を使用するときに、アクションとスキップするページの量を設定します。たとえば、アクションを「+」と量に設定します。「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 (...)))注:
ViewButton.ID_CALLERのcustom_id、ViewButton.ID_SEND_MESSAGE、ViewButton.ID_CUSTOM_EMBED、またはlinkボタンのボタンに関しては、合計で25のボタン以下である限り多くを追加できます。他のすべてのボタンIDについて、各メニューには1つしかありません。
メニューに情報を分類するときに、選択が使用されます。メニューのmenu_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() ViewSelect.GoToのpage_numbersパラメーターは、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パラメーターをerlipsis(...)に設定します。メニューにページを追加した後に選択した場合にのみ機能します
@ 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クラスには、 custom_id (リンクボタンを除く)に従って設定されたパラメーターを使用してViewButtonを返すセットファクトリーメソッド(クラスメソッド)が付属しています。
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()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 )注:リンクボタンには無効です。また、
ViewButton.ID_END_SESSIONのcustom_idを備えたボタンにも理想的ではありません
メニューリレーは、メニューの一部であるボタンが押されているときにいつでも呼び出される関数です。 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無効です
メニューを停止するときに使用できるオプションは1つだけです。 Trueとして複数のパラメーターがある場合、1つだけが実行されます
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 ())