0
1

DiscordBOTでドロップダウンメニューやボタンを制御する

Posted at

はじめに

Discordでは様々なuiが準備されています。今回はドロップダウンメニューやボタンの使い方や制御について、この記事では紹介します。
基本的には下記で紹介したテンプレートをベースに、拡張して作成します。

ファイル構成は下記の通り。

ファイル構成
.
┣━ main.py
┣━ .env
┗━ cogs
  ┣━ commands.py
  ┗━ listenner.py

今回はcommands.pyを修正して作成します。

1.ボタンとドロップダウンメニューを出力するコマンドを作成する

こんな感じのボタンやドロップダウンメニューを出力するコマンドを作成してみます。
image.png

commands.py
import os,discord
from discord.ext import commands
from discord import app_commands

# DiscordサーバのIDを取得
GUILD_ID  = os.getenv('GUILD_ID')

# ボタンの挙動を定義するクラス
class Button(discord.ui.Button):
    def __init__(self, label,style):
        super().__init__(label=label,style=style)
    async def callback(self, interaction: discord.Interaction):
        await interaction.response.send_message(content=self.label+'ボタンが押されました。')

# ボタンのビューを定義するクラス
class ButtonView(discord.ui.View):
    def __init__(self, timeout=180):
        super().__init__(timeout=timeout)
        self.add_item(Button(label='OK', style=discord.ButtonStyle.success))
        self.add_item(Button(label='Cancel', style=discord.ButtonStyle.gray))

# ドロップダウンメニューの挙動を定義するクラス
class Dropdown(discord.ui.Select):
    def __init__(self,options):
        super().__init__(placeholder='好きな動物は何ですか?', min_values=1, max_values=1, options=options)

    async def callback(self, interaction: discord.Interaction):
        # 2回以上実行されないように非活性にする。
        self.disabled = True
        # edit_messageを使って変更したビューを反映する。
        await interaction.response.edit_message(view=self.view)
        # responseは1回のみのため、followupを使ってesonseに対して返信を行う。
        await interaction.followup.send(self.values[0]+'が選択されました。')

# ドロップダウンメニューのビューを定義するクラス
class DropdownView(discord.ui.View):
    def __init__(self):
        super().__init__()
        # ドロップダウンメニューのリスト
        options = [
            discord.SelectOption(label='dog', description='犬が好きです。'),
            discord.SelectOption(label='cat', description='猫が好きです。'),
            discord.SelectOption(label='bird', description='鳥が好きです。'),
        ]
        # viewにセレクトを追加
        self.add_item(Dropdown(options=options))

class MyCommands(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
    
    # ボタンを出力するスラッシュコマンドを追加
    @app_commands.command(name='button', description='ボタンを表示します。') 
    async def button(self,interaction: discord.Interaction):
        await interaction.response.send_message(view=ButtonView())

    # ドロップダウンメニューを出力するスラッシュコマンドを追加  
    @app_commands.command(name='select', description='ドロップダウンメニューを表示します。') 
    async def select(self,interaction: discord.Interaction):
        await interaction.response.send_message(view=DropdownView())

# BOTにcogを登録 ギルドコマンドとして登録
async def setup(bot: commands.Bot):
    await bot.add_cog(MyCommands(bot), guild=discord.Object(id=GUILD_ID))

イメージとしてはビューにボタンやドロップダウンメニューを配置して、それぞれのオブジェクトのcallback関数で挙動を定義する感じです。なので一つのビューの中で複数のボタンやドロップダウンメニューなどを配置できます。
また、今回は1度だけ実行させたいのでDropdowncallback関数self.disabled = Trueを指定して、ドロップダウンメニューを非活性化しています。何回でも実行しても問題なければ下記でOKです。

    async def callback(self, interaction: discord.Interaction):
        await interaction.response.send_message(self.values[0]+'が選択されました。')

2.対話的にuiを利用するやり方

例えば、ドロップダウンメニューを選択したのち、それで良いかどうかを確認したい場合があったとします。その場合、以下のようにドロップダウンメニューの後にOK,Cancelボタンを表示して選ばせるといった方法があります。
Animation.gif

以下それを実現させたコードです。

commands.py
import os,discord
from discord.ext import commands
from discord import app_commands

# DiscordサーバのIDを取得
GUILD_ID  = os.getenv('GUILD_ID')

# ボタンの挙動を定義するクラス
class Button(discord.ui.Button):
    def __init__(self, label,style):
        super().__init__(label=label,style=style)
    async def callback(self, interaction: discord.Interaction):
        await interaction.response.send_message(content=self.label+'ボタンが押されました。')

# ボタンのビューを定義するクラス
class ButtonView(discord.ui.View):
    def __init__(self, timeout=180):
        super().__init__(timeout=timeout)
        self.add_item(Button(label='OK', style=discord.ButtonStyle.success))
        self.add_item(Button(label='Cancel', style=discord.ButtonStyle.gray))

# ドロップダウンメニューの挙動を定義するクラス
class Dropdown(discord.ui.Select):
    def __init__(self,options):
        super().__init__(placeholder='好きな動物は何ですか?', min_values=1, max_values=1, options=options)

    async def callback(self, interaction: discord.Interaction):
        # edit_messageを使って表示をButtonViewへ変更する。
        await interaction.response.edit_message(content=self.values[0]+'が選択されました。よろしいですか?',view=ButtonView())

# ドロップダウンメニューのビューを定義するクラス
class DropdownView(discord.ui.View):
    def __init__(self):
        super().__init__()
        # ドロップダウンメニューのリスト
        options = [
            discord.SelectOption(label='dog', description='犬が好きです。'),
            discord.SelectOption(label='cat', description='猫が好きです。'),
            discord.SelectOption(label='bird', description='鳥が好きです。'),
        ]
        # viewにセレクトを追加
        self.add_item(Dropdown(options=options))

class MyCommands(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
    # ドロップダウンメニューを出力するスラッシュコマンドを追加  
    @app_commands.command(name='select', description='ドロップダウンメニューを表示します。') 
    async def select(self,interaction: discord.Interaction):
        await interaction.response.send_message(view=DropdownView())

# BOTにcogを登録 ギルドコマンドとして登録
async def setup(bot: commands.Bot):
    await bot.add_cog(MyCommands(bot), guild=discord.Object(id=GUILD_ID))

Dropdowncallback関数で使用するビューをドロップダウンメニュー(DropdownView)からボタン(ButtonView)へ変更しています。
contentを設定することで、メッセージとともにボタンを表示することができます。
ちなみにビューを表示させたくない場合はview=Noneとしてください。

まとめ

uiを表示させるには、viewに表示するuiを設定してsend_messageでviewを表示させるだけです。その他のuiは使ったことがないですが、おそらく同じような使い方だと思っています。(調べていません)
今回はここまで。

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