Skip to content

Instantly share code, notes, and snippets.

@CyberRex0
Last active June 5, 2021 06:12
Show Gist options
  • Save CyberRex0/18410693de8fb8704f40a970cfd54fae to your computer and use it in GitHub Desktop.
Save CyberRex0/18410693de8fb8704f40a970cfd54fae to your computer and use it in GitHub Desktop.

discord-ia-button-module for Discord.py

もくじ

モジュールのインポート
コンテキストの作成
ボタンの追加
注意点
備考
親オブジェクトでのボタン追加・削除・取得
備考
送信前の準備
備考
送信
編集と削除
イベント受信から応答まで
データモデルの仕様
サンプルコード

使い方

モジュールのインポート

from discord_components import InteractionButton, InteractionButtonStyles, InteractionButtonParts

コンテキストの作成

これが親オブジェクトになる。これにボタンを追加していく土台。

InteractionButton(bot: discord.Client|discord.commands.Bot)

context = InteractionButton(bot=ctx)

キーワード引数botにはクライアントを指定。

引数名 省略可能 キーワード引数か 意味
bot No Yes Botクライアント
original_message Yes Yes 元のメッセージ(ユーザーのものなど)

ボタンの追加

InteractionButtonPartsでボタンを作る。

InteractionButtonParts(name: str, label: str, url: str, style: int, disabled: bool)

引数名 省略可能 キーワード引数か 意味
name 場合による Yes ボタンのID。重複しないこと
label No Yes ボタンに表示させる文字列
url 場合による Yes ボタンにリンクさせるURL
style Yes Yes ボタンのスタイル(備考を参照すること)
disabled Yes Yes 押せなくするかどうか
button = InteractionButtonParts(name='sample1', label='ボタンだよ', style=InteractionButtonStyles.primary())

注意点

  • styleに5 (またはInteractionButtonStyles.url()) を指定した場合、urlパラメータが必須となる。それ以外の場合は、nameが必須となる。
  • labelの最大文字数は50

備考

  • ボタンのスタイルはいくつかある。

↓表(InteractionButtonStyles.は省略)

種類 色の名前 別名 ID
通常 blurple primary 1
サブ grey secondary 2
完了 green success 3
キャンセル red danger 4
URL用 - url 5

親オブジェクトでのボタン追加・削除・取得

context.add_button(button) # 追加
context.remove_button(button) # 削除
context.get_button(0) # 1個目のボタン取得

備考

  • 追加したボタンは内部プロパティbuttonsに格納される。
  • remove_buttonに指定したボタンがなくてもエラーにはならない。
  • 追加できるボタンは5つまで(でもこれ、たぶん間違ってるから後で調べ直す)

送信前の準備

context.build(content: str, embed: discord.Embed)
引数名 省略可能 キーワード引数か 意味
content embed指定なしの場合No Yes テキストメッセージ
embed content指定なしの場合No Yes 表示させたいEmbed

送信に必要なデータを生成する。

build()を呼び出さないと送信時にエラーになる。

内部プロパティjsonに辞書で保存される。

引数はなくても良い(はず)

備考

  • add_buttonまたはremove_buttonした後は必ずbuild()を呼び出すこと。

送信

obj = await context.send(channel: discord.TextChannel)
引数名 省略可能 キーワード引数か 意味
channel No Yes 送信先チャンネル

このメソッドはコルーチンである。

指定チャンネルに送信する。 channelにはDiscord.pyのTextChannelを渡すこと。

返り値として、RAWなメッセージオブジェクトが返ってくる。(InteractionButtonRemoteObject)

編集と削除

送信したボタンはあとから編集することができる。

await obj.edit(new_context: InteractionButton)

引数名 省略可能 キーワード引数か 意味
new_context No No 置き換える新しいオブジェクト

削除もできる。

await obj.delete()

イベント受信から応答まで

送信で得たオブジェクトは、InteractionButtonRemoteObjectがベースで、wait_for_press()でクリックイベントを受信する状態にできる。

その場で受け取る

event = await obj.wait_for_press(timeout: float)

引数名 省略可能 キーワード引数か 意味
timeout Yes Yes タイムアウトになるまでの時間(秒)

※wait_forと同じと考えてよい。

返り値はイベントの内容が格納されたInteractionButtonEventResponseがベースのものが得られる。 タイムアウトを指定していて、かつ時間が過ぎたときは、例外asyncio.TimeoutErrorが発生する。

バックグラウンドで受け取る

async def callback(ctx, event):
 await event.reply(f'{event.name}が押されました')

obj.set_callback(callback)
obj.start_receive()

set_callbackで受け取る関数を指定、start_receive()で開始。

停止する場合はstop_receive()、コールバック関数を外す場合はclear_callback()を呼び出す。

コールバックの関数にはctx (discord.ext.commands.Context) 、event (InteractionButtonEventResponse)の順に引数が渡される。

※何らかの理由でctxがNoneになることがある。

obj.set_callback(coro)

引数名 キーワード引数か 意味
coro No イベントを受信する関数(コルーチン)

※キーワード引数ではない

コルーチン以外のものを指定した場合はTypeErrorとなる。

イベント受信時はawait coro(data)の形で内部から呼び出される。

dataの型はInteractionButtonEventResponseである。

task = obj.start_receive(timeout: float)

引数名 省略可能 キーワード引数か 意味
timeout Yes Yes タイムアウトになるまでの時間(秒)

※キーワード引数

返り値の型はasyncio.Taskである。

応答

返り値として得られたものを使って、応答メッセージを送信できる。

await event.reply(text: str)

引数名 省略可能 キーワード引数か 意味
text No No テキストメッセージ
embed Yes Yes 埋め込み
hidden Yes Yes メッセージ送信者にのみ表示するか

embedにはdiscord.Embedを指定できる。

hiddenはbool。

イベントを受け取ったことだけ通知して別な処理をしたいとき

ack()で、メッセージの送信はしないが、受信したということだけ通知できる。

await event.ack()

データモデルの仕様

InteractionButton

属性名 内容
bot Client系 クライアント
embed discord.Embed 埋め込み
original_message discord.Message 元のメッセージ(ユーザーのものなど)
json dict 送信用内部辞書
buttons list ボタンの格納先
メソッド名 内容
add_button ボタン追加
add_buttons 複数ボタン追加
remove_button ボタン削除
get_button ボタン取得
build データ生成
await send 送信

備考

bot、jsonを直接編集することは望ましくない。

InteractionButtonParts

属性名 内容
name str ボタンのID
type int Component Type
label str ボタンに表示させる文字列
style int ボタンのスタイル
url str ボタンに結びつけるURL
disabled bool 無効にするかどうか
メソッド名 内容
to_dict JSON変換用

備考

typeは常に2で固定。

InteractionButtonRemoteObject

属性名 内容
bot Client系 クライアント
payload dict RAWメッセージオブジェクト
id int メッセージID
channel_id int チャンネルID
message discord.Message メッセージオブジェクト
original_message discord.Message 元のメッセージ(ユーザーのものなど)
guild_id int サーバーID
timeout int タイムアウトまでの秒数
メソッド名 内容
await delete メッセージ削除
await edit メッセージ編集
set_callback コールバック設定
clear_callback コールバック解除
start_receive イベント受信開始
stop_receive イベント受信停止
await wait_for_press イベント受信待受

備考

bot, payload, id, channel_id, message, guild_idを直接編集することは望ましくない。

InteractionButtonEventResponse

属性名 内容
bot Client系 クライアント
data dict イベントデータ
REPLY_TOKEN str コールバック用ワンタイムトークン
name str ボタンのID
message discord.Message ボタンが置かれているメッセージオブジェクト
original_message discord.Message 元のメッセージ(ユーザーのものなど)
ctx Context コンテキストオブジェクト(クライアントにdiscord.Clientを使用時は常にNone)
メソッド名 内容
await reply メッセージ返信
await ack 受信確認通知
await custom_response 手動でレスポンス送信

備考

bot, data, REPLY_TOKEN, name, messageを直接編集することは望ましくない。

サンプルコード

クライアントの変数名はbot、チャンネルオブジェクトが入った変数をchannelとしている。

シンプルにボタン配置

from discord_components import InteractionButton, InteractionButtonParts
context = InteractionButton(bot=bot)
button = InteractionButtonParts(name='sample1', label='ボタンだよ')
context.add_button(button)
context.build(content='↓ただのボタン')
await context.send(channel=channel)

ボタンの色を変える

from discord_components import InteractionButton, InteractionButtonStyles, InteractionButtonParts
context = InteractionButton(bot=bot)
button = InteractionButtonParts(name='sample2', label='操作を取り消す', style=InteractionButtonStyles.red())
context.add_button(button)
context.build(content='↓ただのボタン')
await context.send(channel=channel)

絵文字付きボタン

from discord_components import InteractionButton, InteractionButtonStyles, InteractionButtonParts
context = InteractionButton(bot=bot)
button = InteractionButtonParts(name='sample2', label='再生', emoji=u'\U000025b6\U0000fe0f')
context.add_button(button)
context.build(content='再生パネル')
await context.send(channel=channel)

Webサイトに飛ぶボタン

from discord_components import InteractionButton, InteractionButtonStyles, InteractionButtonParts
context = InteractionButton(bot=bot)
button = InteractionButtonParts(name='sample3', label='検索結果を表示', url='https://www.google.com/', style=InteractionButtonStyles.url())
context.add_button(button)
context.build(content='Googleで調べる:')
await context.send(channel=channel)

10秒以内にクリックされたらなにかメッセージを送る

from discord_components import InteractionButton, InteractionButtonStyles, InteractionButtonParts
context = InteractionButton(bot=bot)
button = InteractionButtonParts(name='sample4', label='ここをクリック')
context.add_button(button)
context.build(content='押してね↓')
obj = await context.send(channel=channel)
resp = await obj.wait_for_press(timeout=10.0)
await resp.reply('押されました')

寝るのを促すなにか (モジュール応用編)

from discord_components import InteractionButton, InteractionButtonStyles, InteractionButtonParts

async def reaction(ev):
 if ev.name == 'sleep':
  await ev.reply('(つ∀-)オヤスミー')
 elif ev.name == 'cancel':
  await ev.reply('発狂(は')
 elif ev.name == 'noact':
  await ev.ack()

context = InteractionButton(bot=bot)
button1 = InteractionButtonParts(name='sleep', label='寝る', style=InteractionButtonStyles.primary())
button2 = InteractionButtonParts(name='cancel', label='夜ふかしする', style=InteractionButtonStyles.grey())
button3 = InteractionButtonParts(name='noact', label='なにもしない', style=InteractionButtonStyles.grey())
context.add_buttons([button1, button2, button3])

em = discord.Embed(title='寝る')
em.description = '寝ることができます'

context.build(embed=em)
obj = await context.send(channel=channel)
obj.set_callback(reaction)
t = obj.start_receive()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment