10
4

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 4

discord botへのコマンド登録

Last updated at Posted at 2022-12-03

前提

  • 想定環境:linux (ubuntu)
  • pythonによる開発,つまりdiscord.pyでのdicord botの作成をする
  • botのアカウントがある
  • botがログインできる

要するに

discordbot.py
import os
from discord import Intents, Client
from dotenv import load_dotenv
load_dotenv()


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

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


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

こんな感じのプログラムが正しく動けば大丈夫です.

コマンド

まずコマンドは,discord上でチャットにスラッシュ(/)を入力すると表示されるやつです.コマンドに応じて様々な処理が可能です.
以下の画像は,デフォルトで使用できるコマンド/tableflipを実行してみたものです.

image.png

image.png

image.png

ちなみに,スラッシュから入力するコマンドはスラッシュコマンドと言います.コマンドは,任意の文字から始めたり,特定の文字列に反応したコマンドなどのテキストベースのものもあります.それと区別してスラッシュコマンドと言う,んだと思ってます.

そしてテキストベースのコマンドは,動作を保証されなくなったはずです.

September 1, 2022 is the final switchover date. This means that, if the developer of one of the apps you’re using has not made the switch yet, parts of the app might not work after that time.

とのことですので,スラッシュコマンドを使っていきましょう.

スラッシュコマンドのほかにもボタンを使ったGUI操作もできます.これらは総称してアプリケーションコマンドというみたいです.詳しくはドキュメントを読んでください.

アプリケーションコマンドを使うには,botのscopeにapplications.commandsを含める必要がありますので注意してください.

image.png

スラッシュコマンド

スラッシュコマンドはdiscord.app_commandsにあるCommandTreeを利用します.このCommandTreeのインスタンスに対しコマンドを追加していきます.そして,CommandTreeのデコレータcommand()の下に関数を書くことでコマンドの追加ができます.

discordbot.py
import os
- from discord import Intents, Client
+ from discord import Intents, Client, Interaction
+ 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 on_ready(self):
        print(f"login: {self.user.name} [{self.user.id}]")


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

+ @client.tree.command()
+ async def hello(interaction: Interaction):
+     await interaction.response.send_message(f'Hello, {interaction.user.mention}')

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

しかし今のままではスラッシュコマンドが使えません.CommandTreeに追加したコマンドはdiscordに同期しないと表示,使用することができないからです.そのため同期をさせる処理を追加します.そのタイミングはbotがログインするタイミングが一番良いでしょう.また,一度同期させれば問題ないため,今回はsetup_hook()内に処理を追加します.

discord.py
import os
from discord import Intents, Client, Interaction
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}]")


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


@client.tree.command()
async def hello(interaction: Interaction):
    await interaction.response.send_message(f'Hello, {interaction.user.mention}')


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

チャットにスラッシュを打ち込むと
image.png

実行すると

image.png

こんな風になりました.

コードの具体的なところを見ていきましょう.

@client.tree.command()
async def hello(interaction: Interaction):
    await interaction.response.send_message(f'Hello, {interaction.user.mention}')

実行されたときの画像を見てもらうとわかりますが,コマンドを使用するとそのときのメッセージ「/hello」はチャットに残りません.その代わりにどのコマンドを使用したかのメッセージに対しての返信がbotから送信されます.つまりコードは

  • どのコマンドを使用したか
    • interaction
  • 反応をするためのオブジェクト
    • response
  • 反応への返信
    • send_message(message)

という感じです.ただし,リファレンスに書いてありますが応答は一度しかできません.そのため複数回にわたってメッセージを送りたい場合,リファレンスによると

応答は一度だけ行うことができます。複数回にわたってメッセージを送信する必要がある場合は、代わりに followup を使用することを検討してください。

とありますが,followupwebhookです.現状ではこれを使えません.これを使うには...という話は正直,私には現状わかりません.気にせず使ってみたらエラー1吐きました.リファレンスのwebhookのところを読んでみてください.少なくとも,サーバーにwebhookを登録するには,サーバーのアイコンを右クリックして,サーバー設定から連携サービスを選び,そこからwebhookが作成できるみたいです.この先は知りません.申し訳ありません.

複数回メッセージを送信したい場合はchannelを取得して,そこからメッセージを送ればよいと思います.

@client.tree.command()
async def hello(interaction: Interaction):
+   await interaction.channel.send("use interaction.channel.send")
+   await interaction.channel.send("おはようございます")
    await interaction.response.send_message(f'Hello, {interaction.user.mention}')

image.png

ただ,書いたコードの順番ではないようですね.インタラクション自体はコマンドを打った時ですので,それがresponceによって書き換わっているためこのような順番になるのだと思います.そのため,responceを利用する場合は先頭に書いた方がよさそうです.

ともかく,これにてbotにスラッシュコマンドを登録することができました.別の処理をするコマンドも同様に追加することができます.
お疲れ様でした.

  1. こんなエラー吐きました.discord.app_commands.errors.CommandInvokeError: Command 'hello' raised an exception: NotFound: 404 Not Found (error code: 10015): Unknown Webhook.やはりチャンネルにwebhookを登録していないからですね.

10
4
1

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?