LoginSignup
15
13

More than 1 year has passed since last update.

Discordの新機能「モーダルウィンドウ」をPythonから使ってみよう

Posted at

なんか面白そうな機能キタ――(゚∀゚)――!!

image.png
引用: Discord Developer Portal

Qiita2回目の初心者です。
ということで、テキスト入力をさせるモーダルウィンドウを表示させることができるようになりました。
おもろいなぁって思ったので、メモ程度にQiita書かせていただきます。
また、環境はnextcordですが、Discord.pyとかpycordとかでも、バージョン2.0以上なら使えるので、importの名前とかをAPIリファレンス又は勘をもとにリファクタリングしてください。

百聞は一見に如かず

まずは、コードを見てみましょう。

food.py
import nextcord
from nextcord.ext import commands
from nextcord import Interaction

bot = commands.Bot()


class FavoriteFoodModal(nextcord.ui.Modal):
    def __init__(self):
        super().__init__(
            "好きな食べ物は何ですか?",
            timeout=None,
        )

        self.food = nextcord.ui.TextInput(
            label="食べ物",
            style=nextcord.TextInputStyle.short,
            placeholder="おにぎり",
            required=True,
        )
        self.add_item(self.food)

    async def callback(self, interaction: Interaction) -> None:
        await interaction.response.send_message(f"好きな食べ物は{self.food.value}なんだね!")
        return


@bot.slash_command(name="food", description="好きな食べ物を聞きます")
async def food_slash(interaction: Interaction):
    modal = FavoriteFoodModal()
    await interaction.response.send_modal(modal=modal)

bot.run("abcdefghijklmnopqrstuvwxyz.1234567890.abcdefghijklmnopqrstu")

モーダルウィンドウは、スラッシュコマンド又はボタンなどのUIのインタラクションにて表示させることができます。
上記コードの場合、スラッシュコマンドの/foodを送信すると、FavoriteFoodModalのインスタンスを作成して、それをinteraction.response.send_modalという関数に渡して実行されていって下のように表示されます。
image.png
明らかに「レバニラ」とかを要求してそうなモーダルの完成です。
試しに「レバニラ」なんて入力してあげると、
image.png
という風に、入力された値が返ってきます。

...ちょっとだけでいいから要約して。

まず、nextcord.ui.Modalクラスを継承したクラスを作ります。
__init__の中には、モーダルウィンドウのタイトルとタイムアウト時間を指定します。
次にself内にnextcord.ui.TextInputクラスを、ラベルなどのパラメーターの値を渡してインスタンス化します。
そしたらself.add_item関数に先ほどのTextInputを渡せば完了です。
モーダルで送信が行われた際にcallback関数が実行されます。
値の取得は、self内の先ほどインスタンス化したTextInputvalueというやつが値らしいので、そっから取れます。
で、あとはメッセージ送信をするなり煮るなり焼くなりしてあげてください。

もうちょっとだけ詳しい仕様を解説するQ&A風コーナー

Q. モーダルウィンドウには複数個のテキストボックスをつけることができますか?
A. できます。

Q. ちなみに何個まで?
A. モーダルには最大で5つのテキストボックスをつけることができます。

Q. さっき言ってたラベルなどのパラメーターって実際には何があるの?
A. なんかたくさんあります。

パラメーター 変数型 説明
label str テキストボックスの上のラベル文
style nextcord.TextInputStyle テキストボックスのスタイル(後述)
*custom_id str インタラクションに関するカスタムID
*row int モーダルの中でのテキストボックスの位置(0-4)
*min_length int 最小文字数
*max_length int 最大文字数
*required bool 必須項目にするかどうか
*default_value str 最初から入力されてるデフォルトの値
*placeholder str 後ろにうすーく見えるプレースホルダーの値

Q. テキストボックスのスタイルって?(nextcord.TextInputStyleって?)
A. 1行だけのテキストボックス(nextcord.TextInputStyle.short)か、複数行入力可能なテキストボックス(nextcord.TextInputStyle.paragraph)かの違いです。
HTMLやってる人にわかりやすく伝えるなら、<input type="text">か、<textarea>かの違いです。

Q. 必須項目じゃないところで、なにも入れずに送信したらどうなるの?
A. value""(何もない文字列)が返ってきます。

Q. スマートフォン/タブレット版Discordには対応してるの?
A. なぜか画面全体を覆いますが、普通にモーダルが表示されます。

Q. 上のコードコピペしたけど動かない!
A. もし、あなたの使っているラッパーがnextcordでなければ、nextcordというところをdiscordに置き換えてみてください。(ごめんなさいあとは知りません)

Q. 自分で追加してみたけどCommand raised an exception: TypeError: Object of type TextInput is not JSON serializableってエラーが出て動かない!
A. 私も騙されましたが、TextInputクラスをインスタンス化する際に、self.titleとかを使うと、そのエラーが発生します。
理由としては多分nextcord.ui.Modalのクラス内で使われてるパラメーターを指定すると、当然それをTextInputに置き換えて、それをサーバーに送信しようとしてなんか...こう...エラーが...ってことなんでしょう。
とりあえず、使いがちですがtitleなどのパラメーターの名称は使わないようにしましょう。
パラメーターの名称などはAPIリファレンスとかを見れば大体わかります。
自分でDiscord Developer Portal眺めて頑張って解決したんです。褒めてくだs((

今後に期待

ui.Modalクラスとui.TextInputクラスが分かれてるってことは、今後はラジオボタンとかチェックボックスとかをモーダルに配置できるようになるんでしょうかね...
そうなったら結構面白そうですよね~(個人の感想)
あと、テキストボックスって機能があるだけで、画像認証BOTなんかはさらなる機能向上とか出来ますよね?ね?(同業者からの圧)

おしまい

まず、記事内にミスがあったらご容赦ください。コメントでなんか言ってもらえたら嬉しいです。
今後はDiscordBOTに関する内容とかを、後世に残すつもりでQiitaで書いていけたらなーって思ってたりしてます。
私自身の作成しているDiscordBOTは、にらBOTというもので、まぁ...地道に頑張ってるので...少しでも応援していただいたら嬉しいです...
もし出来るなら、皆さんも一緒にプログラミングをして、周りから「チョット出来る奴」みたいな目で見てもらえるようになりましょう!
では!

15
13
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
13