Discord Bot チュートリアル
こんにちは。B3 の Arc です。2022 年 2 月 18 日に部内で Discord Bot の開発チュートリアルを行いました。当時の資料を元に加筆・修正を加えた物を公開してみます。
近頃の Discord Bot 界隈
最初に、近頃の Discord Bot 開発者界隈を取り巻く状況について軽く触れておきます。
むかし
昔は Bot 開発用の 2 大ライブラリとして、Python 用のdiscord.pyと Node.js 用のdiscord.jsがありました。
2021 年 8 月 28 日
この日に discord.py の開発終了がアナウンスされました。Discord 公式とのトラブルがあったようです(詳しくはググってね)。後述しますが、現在は開発が再開されたようです。
これにより、Discord 公式の REST API の仕様変更などに対応できなくなった discord.py 製 bot は死ぬ運命となりました(結果的にそうならなかったけど)。また、discord.py の後継を名乗るプロジェクトが林立する事態となりました。
Python 界隈がこの有様(だった)ので、このチュートリアルでは discord.js を使っていきます。
2022 年 3 月 6 日
……と思っていたら 3 月 6 日に discord.py の開発再開がアナウンスされました。 何が何だか分からん 再び 2 大ライブラリ時代に戻るんじゃないかなと思っています。たぶん……
環境構築・初期設定
この章では、Discord Bot を作るための環境構築・初期設定を行います。
用語集
初めに、基本的な用語について説明しておきます。
- Node.js
- サーバーサイド JavaScript 環境(ブラウザではなくサーバー上で JS を動かすための環境)の一種です。Discord Bot は Node.js 上で動きます。
- パッケージマネージャとして
npm
という物を使います。 - 最新の discord.js(v13)を使うためには、Node v16.6.0 以降が必要です。
- 公式サイト
- TypeScript
- JavaScript を静的型付けライクに拡張した言語です。静的型付け最高!
- TypeScript は直接実行することができないため、基本的には
tsc
というコンパイラで JavaScript に変換してから実行します。 - 文法は C や Java などに近い感じです。
- 公式サイト
Node.js のインストール
ダウンロードページから、Node.js の LTS 版をダウンロード・インストールしてください。
ターミナルでnode --version
を実行した際、v16.14.0
のように表示されていればインストール成功です。
プロジェクトディレクトリの作成
適当な名前のディレクトリを作ってください。
次に、ターミナルでディレクトリに移動し、npm init
を実行してください。色々聞かれますが、とりあえず全て Enter を押せばいいです。
package.json
が作成されていることを確認してください。
パッケージのインストール
開発に必要なパッケージをインストールします。次のコマンドを実行してください。
TypeScript の設定
npx tsc --init
を実行してください。tsconfig.json
が生成されれば成功です。
tsconfig.json
には、TypeScript のコンパイラ(TSC)の設定情報が含まれています。
tsconfig.json
には設定項目が大量にありますが、中身については省略します。baseUrl
の項目だけ次のように変えてください。
スクリプトの設定
package.json
の"scripts"
の箇所を次のように編集してください。
これにより、npm start
でnpx ts-node --files -r tsconfig-paths/register src/index.ts
を実行できるようになりました。
ts-node
は、.ts
ファイルを事前コンパイル無しで直接実行するためのパッケージです(正確には JIT コンパイルしているようです)。TypeScript のコードを走らせるには「tsc でコンパイル」→「Node で js を実行」 の 2 ステップを要していましたが、ts-node
を使うことで 1 ステップに抑えることができます。
いろいろ引数がついていますが、ここでは説明を省略します。気になる方はtsconfig-paths
などで検索してください。
Hello World
src
ディレクトリを作成し、その中にindex.ts
を作成してください。
そして、次のコードをコピペしてください。
最後に、プロジェクトルートに居る状態でnpm start
を実行してください。Hello World!
と表示されれば成功です!
Bot の登録・ログイン
この章では、Discord Bot をサーバーに追加した後、Bot をサーバーにログインさせます。
概ねDiscord.js Guide v12 版に沿っていますが、現行の v13 に合わせて記述を変更している箇所もあります。
Bot をサーバーに追加する
Bot をサーバーに追加していきます。最初にテスト用のサーバーを立てておいてください。
Bot の登録
まずは Bot を Discord に登録します。
- Discord にログインした状態で、Discord Developer Portal のApplicationページに移動してください。
- 右上の
New Application
をクリックして、いい感じの名前をつけてCreate
してください。
- 左のメニューから
Bot
をクリックして、Add Bot -> Yes, do it!
をクリックしてください。A wild bot has appeared!
みたいなメッセージが表示されれば OK です。
Bot をサーバーに招待
次に、Bot をサーバーに招待します。
- 左メニューから
OAuth2 -> URL Generator
を開いてください。 SCOPES
の中のbot
,applications.commands
にチェックを入れてください。BOT PERMISSIONS
の中のSend Messages
にチェックを入れてください。これにより、Bot にメッセージ送信権限が付与されます。他の権限が必要な場合は適宜チェックを増やしてください。
- 下の方にある
Generated URL
をコピーして、Web ブラウザに貼り付けてください。事前に作成したサーバーを選択して、「はい」などのボタンを押してください。 - Discord クライアント上で、サーバーに Bot が追加されたことを確認してください。
Bot をサーバーにログインさせる
環境変数と dotenv
これから Bot をサーバーにログインさせますが、その前に環境変数について説明しておきます。
Bot をログインさせる際には「トークン」という値が必要になります。この値が外部に流出した場合、他の人が Bot をサーバーにログインさせて、スパムメッセージを送信するなどの悪事を働くことができてしまいます。このため、トークンはソースコードに埋め込まずに管理する必要があります(トークンを埋め込んだソースコードを Git に Push したら外部流出したことになります)。
このような機密情報は、実行環境の環境変数に設定して、ソースコードから環境変数を読み込む必要があります。しかし、環境変数を設定するのは割とだるいです。
Node では、実行時に.env
というファイルから環境変数を読み込んで設定するdotenv
というモジュールがあります。実はこのモジュールは前章でインストールしていました。.env
ファイルを.gitignore
に設定することで、機密情報を安全に、便利に扱うことができます。
トークンを.env
ファイルに保存しておきましょう。.env
をルートディレクトリに作成して、次の内容を書き込んでください。
TOKEN=<Botのトークン>
<Botのトークン>
の箇所を実際の値で置き換えてください。Bot のトークンは次のようにして得ることができます。
- Developer Portal から前節で作成したアプリケーションを選択し、左メニューの
Bot
を選択します。 TOKEN
という所にCopy
ボタンがあるのでクリックしてください。トークンがクリップボードにコピーされます。
ログイン処理の実装
Bot をサーバーにログインさせる処理を書いていきます。
コードの中身を説明していきます。
インポート
使用するクラスなどをインポートします。
.env を読み込み、環境変数に登録
.env
を読み込んで、環境変数に登録します。環境変数へはprocess.env.<変数名>
でアクセスすることができます。
クライアントを初期化
v12
以前と異なり、現行のv13
ではClientOptions
が必須になっています。ClientOptions
のintents
で、どのイベントを Bot が受信するかを制御します。ここでは上記 2 つを指定しておけば良いでしょう。- 最後にクライアントのインスタンスを作成します。
ログイン完了時に実行するコールバック関数を登録
- ログイン完了時に
ready
イベントが発火されます。その時に実行する関数(コールバック関数)を登録しておきます。 ()=>{...}
という表記は、JS・TS 特有の「アロー関数」という物です。(詳しくはググってね)
ログイン
- 環境変数
TOKEN
の値を引数にしてログインします。
実行してみる
ここまで書けたら実際に実行してみましょう。
npm start
を実行して数秒待ってください。次のことが確認できれば成功です!
- コンソールに
I'm ready!
と表示される。 - Discord アプリ上で、登録した Bot がオンラインになっている。
確認できたら、Ctrl+C などで Bot を止めておいてください。
スラッシュコマンド
この章では、スラッシュコマンドの実装を行います。
この記事を参考にしています: discord.js でスラッシュコマンド(Slash commands)を使う - Qiita
2 種類のスラッシュコマンド
スラッシュコマンドには「ギルドコマンド」と「グローバルコマンド」の 2 種類があります。
- ギルドコマンド: 特定のサーバーを指定して登録するコマンド。
- グローバルコマンド: Bot が参加している全てのサーバーに登録されるコマンド。
グローバルコマンドは、登録後実際に使えるようになるまで 1 時間ほどかかるようです。このため、本チュートリアルではギルドコマンドを使用します。
環境変数の設定
ギルドコマンドを登録するためには、対象サーバーの ID が必要です。.env
に保存しておきます。
サーバー ID は次の方法で取得することができます。
- Discord アプリの設定画面を開き、「詳細設定」の「開発者モード」をオンにしておきます。
- サーバーアイコン上で右クリックして、「ID をコピー」を選択します。サーバー ID がクリップボードにコピーされます。
.env
に次の項目を追記してください。<サーバーID>
は実際の値に置き換えてください。
SERVER_ID=<サーバーID>
シンプルなコマンド
まず、pong
というメッセージを送信するだけのシンプルなコマンド/ping
を作成してみます。
環境変数の型定義を記述する
環境変数の型定義ファイルを作っておかないと後々面倒なので、ここで作ってしまいます。
src
に@types
ディレクトリを作成して、中にglobal.d.ts
を作り、以下の内容を入力してください。
コマンドを実装する
実際にコマンドを作っていきます。次のコードを参考にして、ready
イベントのコールバックを編集し、interactionCreate
イベントのコールバックを追加してください。async
キーワードが新しく加わっていることに注意してください。
書けたらnpm start
して、アプリ上でコマンドを使えるかどうか確認してみましょう。
引数付きコマンド
引数を受け取るコマンドを作っていきます。ここでは、引数をそのまま出力するecho
コマンドを作っていきます。
コマンドの登録
次のコードを参考にして、commands
に要素を追加してください。引数はoptions
プロパティで設定します。
コマンドの中身を実装
次のコードを参考にして、コマンドの中身を実装してください。引数はinteraction.options.getString()
などで受け取ることができます。
書けたらnpm start
して、アプリ上でコマンドを使えるかどうか確認してみましょう。
遅延応答
「コマンドを受信したら、データベースにアクセスして処理をした後に返信したい」といったケースなど、時間のかかる処理を実装したくなることがあると思います。このような処理をそのまま書いたらどうなるでしょうか?
ping
コマンドを次のように編集してみます。ここでは 4000 ミリ秒後に"pong"と返信するコードを書いています。
ping
コマンドを実際に実行してみましょう。すると、アプリケーションが応答しませんでした
などのメッセージが表示されると思います。
実は、スラッシュコマンドは3 秒以内に返信しないとエラーになります。
これを回避するため、deferReply()
, followUp()
という関数を使います。
このコードにした上でping
コマンドを実行すると、<bot名>が考え中…
というメッセージが表示された 4 秒後にpong
と表示されるはずです。意図通りの挙動になりました。
ということで、時間のかかる処理を行う時には、返信を遅延させるためにdeferReply()
やfollowUp()
を使う必要があります。
詳しくはこのページが参考になります: reply と deferReply の違い - Discord.js Japan User Group
分からないことがあったら
分からないことがある時は次のサイトが頼りになります。
- Discord.js Guide
- discord.js Documentation
- Discord.js Japan User Group (Scrapbox)
- 日本語 Wiki。やりたいことをここで検索すれば大体出てくる説があります。
おわり
スラッシュコマンドに対応した Discord Bot を作りました。後はいろいろ工夫して頑張ってください(雑)。