🕌

discord.pyでのui系のあれこれ

2024/02/16に公開

こんにちは、最近とあるところでの質問でなんか多いなって思った質問がいくつかあるので、ここでまとめて書いときます。

基本

basic.py
import discord


class BasicView(discord.ui.View):
    
    @discord.ui.button(label="Click!")
    async def click(self, interaction: discord.Interaction, button: discord.Button) -> None:
        await interaction.response.send_message("Clicked")


@tree.command()
async def button(interaction: discord.Interaction) -> None:
    await interaction.response.send_message(view=BasicView())

botが落ちて起動した後でも、クリックして反応するようにする

down-click.py
class NotTimeoutView(discord.ui.View):
    
    @discord.ui.button(label="Click!", custom_id="sample")
    async def click(self, interaction: discord.Interaction, button: discord.Button) -> None:
        await interaction.response.send_message("Clicked")

# タイムアウトを設定しないように`None`を渡す。そして事前にインスタンスを作っとく
view = NotTimeoutView(timeout=None)

# 生成したインスタンスをbotに登録する。
# そうすることで落ちる前に作られたボタン入りのメッセージが実行できる
bot.add_view(view)

@tree.command()
async def click_two(interaction: discord.Interaction) -> None:
    # 生成されたviewを繰り返し使うことで、同じボタンであることを認識するようにできる。
    await interaction.response.send_message(view=view)

custom_idを指定しないと動きません。

ボタンに着色する

デコレーターであるdiscord.ui.buttonstyle引数にスタイルを指定すれば、着色できます。以下はそのサンプルコードです。

button-color.py
class ColorView(discord.ui.View):
    
    # 緑色のボタン
    @discord.ui.button(label="green", style=discord.ButtonStyle.green)
    async def green(self, interaction: discord.Interaction, button: discord.Button) -> None:
        await interaction.response.send_message("あなたは緑色のボタンを押しました")
    
    # 赤色のボタン
    @discord.ui.button(label="red", style=discord.ButtonStyle.red)
    async def red(self, interaction: discord.Interaction, button: discord.Button) -> None:
        await interaction.response.send_message("赤色のボタンを押しました。")

ボタンをリンクにする

ボタンをクリックするとどこかのページを飛ばすようにすることができます。この場合デコレーターを使って作ることはできませんので書き方が違います。見ればおそらくわかるので以下がサンプルコードです。

link.py
@tree.command()
async def search(interaction: discord.Interaction) -> None:
    view = discord.ui.View()
    # Googleのボタンを追加
    view.add_item(discord.ui.Button(label="Google", url="https://google.com"))
    # Bingのボタンを追加
    view.add_item(discord.ui.Button(label="Bing", url="https://www.bing.com"))
    # Yahoo japanのボタンを追加
    view.add_item(discord.ui.Button(label="Yahoo japan!", url="https://www.yahoo.co.jp/"))
    await interaction.response.send_message(view=view)

Selectの基本

選択できます。

basic.py
import discord


class Dropdown(discord.ui.Select):

    def __init__(self):
        # オプション、ここでは赤、緑、青を選べるようになっている。
        options = [
            discord.SelectOption(label='赤', description='赤色です。'),
            discord.SelectOption(label='青', description='青色です。'),
            discord.SelectOption(label='緑', description='緑色'),
        ]

        # placeholderはタイトルみたいなもの、min_valuesは最低限選択しないといけない数、max_valuesは最大で何個選択できる数
        super().__init__(placeholder='あなたの好きな色はなんですか?', min_values=1, max_values=1, options=options)

    async def callback(self, interaction: discord.Interaction):
        # ここで返答を返す。
        await interaction.response.send_message(f'あなたが好きな色は{self.values[0]}なんですね!"')


class BasicView(discord.ui.View):

    def __init__(self):
        super().__init__()
        # viewにセレクトを追加
        self.add_item(BasicSelect())


@tree.command()
async def favorite_color(interaction: discord.Interaction) -> None:
    await interaction.response.send_message(view=BasicView())

Modalの基本

Modalはフォームみたいなものだと思ってくださればいいです。以下が基本のコードです。

basic.py
import discord

# タイトルで自己紹介と書かれたモーダルを作成
class Modal(discord.ui.Modal, title="自己紹介"):

    # 名前を入力するための欄を作る
    name = discord.ui.TextInput(label="お名前")

    # フォームのデータを受け取る
    async def on_submit(self, interaction: discord.Interaction) -> None:
        # 入力された名前を送信
        await interaction.response.send_message(self.name.value)

動的なモーダル

ラベルとかを実行時に変更するコードです。以下がサンプルコードです。

dynamic_modal.py
class Modal(discord.ui.Modal, title="自己紹介"):

    def __init__(self, default_name: str):
        super().__init__()

        self.name = discord.ui.TextInput(label="お名前", default=default_name)
        self.add_item(self.name)
    
    # 以下基本と同じ
    async def on_submit(self, interaction: discord.Interaction) -> None:
        ...

@tree.command()
async def introduce(interaction: discord.Interaction, default_name: str = "名無し") -> None:
    await interaction.response.send_modal(Modal(default_name))

最後に

よく質問されるところを中心にサンプルを書いてみましたが、いかがでしょうか?

たまにこれどうやるんだろうと疑問に持った時も何回もあったので一部僕がわからなかったところも載せてます。

では、さよなら。👋

GitHubで編集を提案
Discord.py Community

Discussion