4
7

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 6

discord pyのcontext menuとbutton

Posted at

前提

この記事ではdiscord.pyによるdiscord bot制作において,context menuとbuttonの作成について説明していきます.
以下のサンプルコードを用いて発展させていきます.

サンプルコード
discordbot.py
import os
from discord import Intents, Client
from discord.app_commands import CommandTree
from dotenv import load_dotenv
load_dotenv()


class MyClient(Client):
    def __init__(self, intents: Intents) -> None:
        super().__init__(intents=intents)
        self.tree = CommandTree(self)

    async def setup_hook(self) -> None:
        await self.tree.sync()

    async def on_ready(self):
        print(f"login: {self.user.name} [{self.user.id}]")
        print(self.get_guild(1047700283217686719))


intents = Intents.default()
client = MyClient(intents=intents)
client.run(os.getenv("TOKEN"))

また,今回はCommandTreeのcommandデコレータを使ってコマンドを登録していきますが,add_command()を使って登録してもいいと思います.
そして上記のサンプルコード,および記事の作成にあたって公式のサンプルを参考にしてます.あともちろんAPIリファレンスも見てます.

ContextMenu

まず,ContextMenuのコマンドは,

image.png

これです.ContextMenuを登録すると右クリックで表示されるメニューに「アプリ」が追加され,それをマウスオーバーするとコマンドが表示されるようになります.右クリックのメニューがコンテキストメニューのことです.

ちなみにクリックして実行すると
image.png

こんな感じのことを言うように設定しています.コードは以下の通りです.

discordbot.py
import os
- from discord import Intents, Client
+ from discord import Intents, Client, Interaction, Member
from discord.app_commands import CommandTree
from dotenv import load_dotenv
load_dotenv()


class MyClient(Client):
    def __init__(self, intents: Intents) -> None:
        super().__init__(intents=intents)
        self.tree = CommandTree(self)

    async def setup_hook(self) -> None:
        await self.tree.sync()

    async def on_ready(self):
        print(f"login: {self.user.name} [{self.user.id}]")
        print(self.get_guild(1047700283217686719))


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


+ @client.tree.context_menu()
+ async def greeting(interaction: Interaction, member: Member):
+     await interaction.response.send_message(f"this is {member.nick} !!!")

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

context_menu()のデコレータを利用してコマンドを作ります.引数にはスラッシュコマンドを利用したときに発生するInteractionと,どこを右クリックしたときにコマンドが表示されるかの変数を記述する必要があります.リファレンスによると,

関数は第一パラメータとして Interaction を取り、第二パラメータとして Member 、 User 、 Message 、または Member と User の typing.Union を取らないといけません。

MemberとUserの違いは,Memberがギルド,つまりそのサーバーに参加しているユーザーで,Userはサーバーに参加しているかに依存しないユーザーです.例えばニックネームはサーバー依存ですのでUserでは取れずMemberである必要があります.
まとめると右クリックしてコマンドを実行できる場所は,誰かのアカウントのところかメッセージのところです.

Button

Buttonは,

image.png

こういうやつです.ボタンにcallback関数を追加することで固有の処理を追加できます.コードは以下の通りです.

discordbot.py
import os
import discord
- from discord import Intents, Client, Interaction, Member
+ from discord import Intents, Client, Interaction, Member, ButtonStyle
from discord.app_commands import CommandTree
from dotenv import load_dotenv
load_dotenv()


class MyClient(Client):
    def __init__(self, intents: Intents) -> None:
        super().__init__(intents=intents)
        self.tree = CommandTree(self)

    async def setup_hook(self) -> None:
        await self.tree.sync()

    async def on_ready(self):
        print(f"login: {self.user.name} [{self.user.id}]")
        print(self.get_guild(1047700283217686719))


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


@client.tree.context_menu()
async def greeting(interaction: Interaction, member: Member):
    await interaction.response.send_message(f"this is {member.nick} !!!")


+ class YesButton(discord.ui.Button):
+     def __init__(self, *, style: ButtonStyle = ButtonStyle.secondary, label: str = "yes"):
+         super().__init__(style=style, label=label)
+ 
+     async def callback(self, interaction: Interaction):
+         await interaction.response.send_message("clicked")
+         await interaction.followup.send("you may push yes......")


+ class NoButton(discord.ui.Button):
+     def __init__(self, *, style: ButtonStyle = ButtonStyle.secondary, label: str = "no"):
+         super().__init__(style=style, label=label)
+ 
+     async def callback(self, interaction: Interaction):
+         await interaction.response.send_message("clicked")
+         await interaction.followup.send("you may push nooooooo!!!!")


+ @client.tree.command()
+ async def button(interaction: Interaction):
+     view = discord.ui.View()
+     view.add_item(YesButton(style=discord.ButtonStyle.primary))
+     view.add_item(NoButton(style=discord.ButtonStyle.grey))

    await interaction.response.send_message("do you want to button?", view=view)

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

ボタンのUIを作成している部分はbutton関数です.discordにおいてUIを作成するためにはViewクラスのインスタンスにUIアイテムを追加していきます.今回はボタンを追加することになります.
そしてボタンを押されたときに実行する関数を設定するために,discord.ui.Buttonクラスを継承したクラスにおいてcallbackメソッドをオーバーライドします.callbackメソッド内に書かれた処理がボタンを押したときに実行されます.

このようなボタンを作成して実行してみた結果が以下の通りです.初めてgifを作ったのでので荒いのは見逃してください.とりあえず,ボタンを押したら返信したなってことがわかれば大丈夫です.

discordbot-button.gif

以上がcontext menuとbuttonの作成について説明となります.context menuとbuttonだけでなく,ドロップダウンリストやテキスト入力もできますので,リファレンスを読んでみてください.
お疲れ様でした.

4
7
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
4
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?