
どーも!
たかぽんです...!
今回はDiscordにてよく見かけるスラッシュコマンドを自作してみようと思います...!
普通に個人同士の通話等でdiscordを使っているとあんまり見かけないかもしれないのですが...
筆者は普段仮想通貨のプロジェクトでよく見かけていて、例えば、該当プロジェクトのウォレットごとの情報を取得したり...といったちょっと便利なことに使えるコマンドになっています。
厳密にはslackでもそんな感じのものを見かけた気がするのですが...
slackはまた今度(もしくはこの記事を書いた後ついでに)調べてみようと思います...!
また、今回はpython3が使えるMacのユーザー向けになっています。
Windowsの方等は少し異なる部分が出てくると思うので、ご留意ください。
Discordのスラッシュコマンド
Discordでスラッシュコマンドを使用する場合、サーバーのチャンネルにて"/"を入力すると、そのサーバーで使用できるスラッシュコマンドの確認ができます。

おそらくデフォルトで新規作成されたサーバーにはビルトインで"/giphy"といったコマンドがあるかと思います。
試しにそのコマンドを叩いてみると...?

"query"という形でどんな内容で検索する?というのを指定する必要があるので、helloで検索をするとそれっぽいGif画像がでてきました。

実際に洗濯をすると、そのGIFが投稿されます。
このように、"/"から始まるコマンドを打つことで、引数を渡したりもでき、さまざまな便利機能を使うことができます。
今回はこれに似た形で、簡単な文字列を返すコマンドをpythonで作ってみます...!
ではやっていきましょう!
discordの設定画面でBotの設定をする
まずはdiscordで設定をしていきましょう...!
まずは以下のdiscord開発者ポータルへアクセスし、アプリケーションを作成していきます。
アクセスすると、以下のような画面が出てきます。

右上の"New Application"から新規のアプリケーションを作成します。

警告文が出ていますが、すでに過去にappを作ったことがなければ無視でOKです。
今回はテスト用のお試しとして、"takapon-test"としてみました。
作成をすると、以下の様な感じになると思います。

画面左上の"SELECTED APP"が先ほど指定した名前になっていることを確認しておきます。
また、"General Information"として、簡単な説明だけ追記しました。
では、今度はこのappにてBotを作成します。
画面左のジグソーアイコンからBotを選択します。

こんな画面になっていると思うので、"Add Bot"からBotを作成します...!

新規作成したら、上記の様な画面になると思うので、"Reset Token"から、このBotへアクセスするためのトークン情報を更新・取得しておきます。
(このTokenの情報が第三者に漏れると、Botを自由に使われてしまうので、管理には気をつけてください...!)
トークンを確認・コピーできたら、今度は"OAuth2"の設定を行います。
画面左のOAuth2をクリック。
すると、以下のように"OAuth2 URL Generator"というものが表示されます。
以下で選択しているように、"bot", "applications.commands", "SendMessages"を選択します。

すると、したの方に以下のようなURLが発行されるので、コピーして別のブラウザで開きましょう。

アクセスすると、以下のようにサーバーに対してこのAppを追加する認証画面が出てきます。
最初は"サーバーに追加"の箇所から、追加したいサーバーを選択します。(筆者の場合は"Taka base"という自分だけ入っているdiscordサーバーに追加しました。)
TakaponTestアプリケーションがこのサーバーに対してのリソースにアクセスできるようにしてあげる必要があるんですね。(その細かい設定を先ほどOAuth2にて行いました。)

また、この際、おそらく該当サーバーの管理者権限がないとうまく進めないと思うので、もしうまくいかない場合は、やりたいことに合わせて、前述のOAuth2のURLを各サーバー管理者に共有して追加してもらいましょう。
先ほどOAuthで追加していたSend Messageにあたる項目のみ表示されていることを確認して認証を。


問題なく追加できれば、以下のように一般チャンネルに以下のようなようこそメッセージが出てくるかと思います。

これでdiscord側の準備はOKです...!
pythonで必要なパッケージを用意する
さて、それでは次にpythonでパッケージをinstallしていきます...!
各自のpythonにて、以下のような形でpy-cordをinstallします。
python3 -m pip install -U py-cord --pre
Windowsの方は少しコマンドが異なるようです。
(詳細は下記の公式のチュートリアルをご参照ください)
インストールができたら、今度は任意のフォルダで以下のようなファイルを作成します。
名前はなんでも良いのですが、今回は"command-bot.py"としておきました。
import discord
from discord import Option
TOKEN = 'ここに各自のDiscordBotトークンを入れる'
DISCORD_SERVER_IDS = ここに各自のサーバーIDを入れる
client = discord.Bot()
@client.event
async def on_ready():
print(f"{client.user} コマンド待機中...")
@client.slash_command(description="こんにちわコマンド", guild_ids=[DISCORD_SERVER_IDS])
async def hello(
ctx: discord.ApplicationContext,
name: Option(str, required=False, description="input name")
):
name = name or ctx.author.name
await ctx.respond(f"{name} さん, こんにちは。")
@client.slash_command(description="こんばんわコマンド", guild_ids=[DISCORD_SERVER_IDS])
async def goodnight(
ctx: discord.ApplicationContext,
name: Option(str, required=False, description="input name")
):
name = name or ctx.author.name
await ctx.respond(f"{name} さん, こんばんわ。")
client.run(TOKEN)
すごく簡単にご説明しておくと...
最初に必要になる情報を記載(TOKENやアクセス先のサーバーID)、そしてその後"@client.event"の箇所でサーバー稼働中(後ほどサーバーを動かして、slashコマンドの入力待機をします。)のログを出しています。
詳しくは以下をご参考ください。
そして、その後、"@client.slash_command"から、実際にカスタムで作成するコマンドを定義しています。
今回は"/hello"コマンド、"/goodnight"コマンドの二つを定義していることがわかるかと思います。
@client.slash_commandでは第一引数に簡単なコマンドの説明、第二引数としてサーバーIDを渡しています。
その後、helloという形でメソッドの定義をしていますね。
第一引数は呼び出された時の細かい情報が入ったオブジェクト(例えばコマンドを打ったユーザー名や時刻などが自動で渡されてきます。)、第二引数以降はユーザーに任意に設定できる引数で、今回はユーザーが入力した文字列をわたしています。
このユーザーの入力があった場合はその文字列をnameとして、それがない場合はctxからスラッシュコマンドを叩いたユーザーの名称を取得...といった具合です。
第一引数で使用できる情報の詳細は以下を参照ください。
それぞれの具体的な処理内容は単純で...
nameにあたる文字列が引数に渡されたらその名前を入れて挨拶を返し、もし何も引数に渡されなかった場合はコマンドを呼び出したユーザーのアカウント名から取得した名前を用いて挨拶を返します。
"name or ctx.author.name"はnameが存在すればnameを返し、存在しない場合はその次のctx.author.nameを返す...といった具合です。
上記が実装できたら、CUI上でpythonを実行します。
コマンドは以下になります。
taka@Taka discord % python3 command-bot.py
takapon-test#9930 コマンド待機中...
このような形になっていればOKです。
※ここで"ssl.SSLCertVerificationError:"といったエラーが出た場合、以下の記事を参考に、解決できるかもしれないので、ご参考いただければと思います。
今回作っているスラッシュコマンドはバックエンドで常に稼働しているサーバーがあり、そこで前述のhelloメソッドやgoodnightメソッドが呼び出されます。
そのため、上記のcommand-bot.pyを実行すると、スラッシュコマンドの入力を待機する状態になり、その状態でdiscordに"/hello"を入力すると...

こんな形でこんにちわコマンドが出てくるようになります。
実際に打てば..?

一回目が引数なし、2回目が引数ありでの実行になります。
もちろん、"/goodnight"コマンドも使えるので、是非試してみてください。
まとめ
さて、今回は簡単なdiscord botを作ってみました...!
ちょっと常時稼働させる場合は何かしらサーバー立てる必要がありそうだったので、実用で動かそうとするとハードルは上がりそうですね...
スラッシュコマンドのためにわざわざサーバー立てるの?ってなりそう。
できれば筆者はカスタマイズしつつ色々便利機能追加していきたいのですが、cronでの定期実行等と比べて常時稼働だとコストが気になる...
そこらへんのベストプラクティスよく知らないのですが...サーバーレスに呼ばれた時だけ起動する...みたいなのできないのだろうか...
ちょっとまた後日調べてみようと思います。
いい方法が見つかればまた別途記事にしようかなと...!
それでわ!