0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

itohalAdvent Calendar 2022

Day 22

discord.pyのTextInput

Last updated at Posted at 2022-12-21

初めに

  • WSL, Ubuntu22.04.1
  • Python 3.10.6
  • discord.py 2.1.0

という環境で行っています.

TextInput

TextInputは,Modalにおいてテキスト入力をするためのコンポーネントです.

Modalとは,

image.png

こんな感じのポップアップウィンドウです.アクティビティを退出するときに出てくる評価してねみたいなやつもModalポップアップウィンドウです.
これにテキスト入力できる欄を追加するのがTextInputです.

とりあえず,上の画像のようなModalを作ってみましょう

実験

Modalに対しTextInputを追加するには,Viewと同じように,Modalのadd_itemメソッドを利用します.また,フォームが送信されたときに処理をしたい場合はModalのサブクラスを作り,そこでon_submitメソッドをオーバーライドします.

python
import discord
from discord import Interaction, TextStyle
from discord.app_commands import CommandTree
from discord.ui import TextInput, View, Modal
import os


intents = discord.Intents.default()
client = MyClient(intents=intents)



class MyClient(discord.Client):
    def __init__(self, *, intents: discord.Intents):
        super().__init__(intents=intents)
        self.tree = CommandTree(self)

    async def setup_hook(self) -> None:
        await super().setup_hook()
        commands = await self.tree.sync()
        print(commands)

    async def on_ready(self):
        print(f"Logged in as {client.user} (ID: {client.user.id})")
        print("------")


class Questionnaire(Modal):
    def __init__(self, title: str) -> None:
        super().__init__(title=title)
        self.answer = TextInput(label="favorite point", style=TextStyle.long)
        self.add_item(self.answer)

    async def on_submit(self, interaction: Interaction) -> None:
        await interaction.response.send_message("thanks!")
        await interaction.followup.send(
            f"your favarite point is {self.answer.value}", ephemeral=True
        )


@client.tree.command(name="questionnaire")
async def app_questionnaire(interaction: Interaction):
    modal = Questionnaire("application questionnaire")
    await interaction.response.send_modal(modal)


client.run(os.getenv("TOKEN"))

動かしてみると上記の画像のようなModalが表示されます.

TextInputにはテキストボックスの長さをstyleとして指定できます,shortが1行だけ,paragraphあるいはlongを指定すると複数行のフォームとなります.paragraphの別名がlongなだけなので2種類のみです.

image.png

注意点

注意点として,TextInputはModalにしか使えません.つまりViewには追加できません.例えばcontext_menuによるメッセージの転送1をしようとするときに,メッセージにタイトルをつけようとしてTextInputを使おうかなと思っても使うことができません.下記のようなエラーが発生します.

discord.app_commands.errors.CommandInvokeError: Command 'what_input' raised an exception: HTTPException: 400 Bad Request (error code: 50035): Invalid Form Body
In data.components.0.components.0: Value of field "type" must be one of (2, 3, 5, 6, 7, 8).

意訳すると,data.components.0.components.0にあるtypeに指定する値は(2, 3, 5, 6, 7, 8)のどれかにしてくれ,というエラーです.まずdata.components.0.components.0というのは,DEVELOPER PORTALのExample Componentのところを見ると,Requestを送る際のデータ構造のようです.全体がdataという名前で,それのcomponentsの0行目の中にあるcomponentsの0行目にtypeが入っているようです.

そして,このtypeは何者かという話ですが,DEVELOPER PORTALのWhat is a Componentという項目によると,どのUIコンポーネントかを示すもののようです.もしButtonを追加してたら,そのtypeには2が入るようです.TextInputは4です.つまり,ViewにおいてTextInputは使えないということです.

また,DEVELOPER PORTALのText Inputsの欄を見るとModalでrenderされるよって書いてあると思います.なので,discord.pyのapiリファレンスだけじゃなく,ときおりDEVELOPER PORTALの方のapiリファレンスも見た方がいいとおもいました

メッセージの転送でタイトルをつけようとしたら,追加でボタンを作成してそのボタンを押したらtitleをつけるためModalを表示させるようなことをするか,そもそもタイトルの表示を諦めるか,context_menuではなくcommandにしてメッセージのIDを取得してもらってそれをcommandの引数で指定してもらう,などといったことが考えられるかもしれません.まあ,そこまでしてユーザーの入力が欲しいのかを聞かれると困ってしまいますので諦めた方がいいかもしれません.

以上となります.discord.pyのTextInputを紹介しました.

  1. メッセージを転送しようという記事を書いてます.見ていただけると嬉しいです.

0
1
0

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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?