著者は、 Write for DOnations プログラムの一環として、 Free and Open SourceFundを選択して寄付を受け取りました。
序章
Discord は、世界中の何百万人ものユーザーがギルドまたはサーバーと呼ばれるコミュニティでオンラインでメッセージやボイスチャットを行えるようにするチャットアプリケーションです。 Discordは、開発者が強力なDiscordボットを構築するために使用できる広範なAPIも提供します。 ボットは、サーバーへのメッセージの送信、ユーザーのDM処理、サーバーのモデレート、ボイスチャットでのオーディオの再生などのさまざまなアクションを実行できます。 これにより、開発者は、モデレートツールやゲームなどの高度で複雑な機能を含む強力なボットを作成できます。 たとえば、ユーティリティボット Dynao は数百万のギルドにサービスを提供し、スパム保護、音楽プレーヤー、その他のユーティリティ機能などの便利な機能を備えています。 Discordボットの作成方法を学ぶことで、何千人もの人々が毎日やり取りできる多くの可能性を実装できます。
このチュートリアルでは、Node.jsとDiscord.jsライブラリを使用して、Discordボットを最初から構築します。これにより、ユーザーはDiscordAPIを直接操作できます。 Discordボットのプロファイルを設定し、ボットの認証トークンを取得し、ユーザーからの引数を使用してコマンドを処理する機能をボットにプログラムします。
前提条件
始める前に、次のものが必要になります。
-
開発マシンにインストールされているNode.js。 これをmacOSまたはUbuntu20.04にインストールするには、 Node.jsをインストールし、macOSにローカル開発環境を作成する方法またはNodeSourcePPAを使用してAptでNode.jsをインストールするの手順に従います。 ] Ubuntu20.04にNode.jsをインストールする方法のセクション。
-
Visual Studio Code 、 Atom 、 Sublime 、 nano など、任意のテキストエディター。
-
確認済みのメールアカウントを持つ無料のDiscordアカウントと、Discordボットのテストに使用する無料のDiscordサーバー。
ステップ1—DiscordBotのセットアップ
このステップでは、Discord開発者のグラフィカルユーザーインターフェイス(GUI)を使用して、Discordボットをセットアップし、プログラムに渡すボットのトークンを取得します。
Discordプラットフォームにボットを登録するには、Discordアプリケーションダッシュボードを使用します。 ここで、開発者はDiscordボットを含むDiscordアプリケーションを作成できます。
開始するには、新しいアプリケーションをクリックします。 Discordは、新しいアプリケーションの名前を入力するように求めます。 次に、作成をクリックしてアプリケーションを作成します。
注:アプリケーションの名前はボットの名前とは無関係であり、ボットはアプリケーションと同じ名前である必要はありません。
次に、アプリケーションダッシュボードを開きます。 アプリケーションにボットを追加するには、左側のナビゲーションバーのボットタブに移動します。
ボットの追加ボタンをクリックして、アプリケーションにボットを追加します。 確認を求められたら、はい、やります!ボタンをクリックします。 次に、ボットの名前、認証トークン、プロフィール写真の詳細を含むダッシュボードが表示されます。
ここのダッシュボードでボットの名前またはプロフィール写真を変更できます。 また、 Click to Reveal Token をクリックし、表示されたトークンをコピーして、ボットの認証トークンをコピーする必要があります。
警告:ボットトークンは誰でもログインできるため、共有したりアップロードしたりしないでください。
次に、ボットをテストできるDiscordギルドに追加するための招待状を作成する必要があります。 まず、アプリケーションダッシュボードのOAuth2タブの下にあるURLGeneratorページに移動します。 招待状を作成するには、下にスクロールして、スコープの下のボットを選択します。 また、ボットがギルドで実行できるアクションを制御するための権限を設定する必要があります。 このチュートリアルでは、管理者を選択します。これにより、ギルドでほぼすべてのアクションを実行する権限がボットに付与されます。 コピーボタンでリンクをコピーします。
次に、ボットをサーバーに追加します。 作成した招待リンクをたどります。 ドロップダウンメニューから、所有している、または管理者権限を持つ任意のサーバーにボットを追加できます。
次に、続行をクリックします。 管理者の横にあるチェックボックスがオンになっていることを確認します。これにより、ボット管理者のアクセス許可が付与されます。 次に、承認をクリックします。 ボットがサーバーに参加する前に、DiscordはCAPTCHAを解決するように求めます。 これで、オフラインの下にボットを追加したサーバーのメンバーリストにDiscordボットが表示されます。
これで、Discordボットが正常に作成され、サーバーに追加されました。 次に、ボットにログインするためのプログラムを作成します。
ステップ2—プロジェクトを作成する
このステップでは、ボットを構築し、プログラムでボットにログインする基本的なコーディング環境をセットアップします。
まず、ボットに必要なプロジェクトフォルダーと必要なプロジェクトファイルを設定する必要があります。
プロジェクトフォルダを作成します。
- mkdir discord-bot
作成したプロジェクトフォルダに移動します。
- cd discord-bot
次に、テキストエディタを使用して、ボットの認証トークンを保存するconfig.json
という名前のファイルを作成します。
- nano config.json
次に、次のコードを構成ファイルに追加し、強調表示されたテキストをボットの認証トークンに置き換えます。
{
"BOT_TOKEN": "YOUR BOT TOKEN"
}
ファイルを保存して終了します。
次に、package.json
ファイルを作成します。このファイルには、プロジェクトの詳細と、プロジェクトに使用する依存関係に関する情報が格納されています。 次のnpm
コマンドを実行して、package.json
ファイルを作成します。
- npm init
npm
は、プロジェクトに関するさまざまな詳細を尋ねます。 これらのプロンプトを完了するためのガイダンスが必要な場合は、npmおよびpackage.jsonでNode.jsモジュールを使用する方法でそれらについて読むことができます。
次に、DiscordAPIとの対話に使用するdiscord.js
パッケージをインストールします。 次のコマンドを使用して、npmを介してdiscord.js
をインストールできます。
- npm install discord.js
構成ファイルを設定し、必要な依存関係をインストールしたので、ボットの構築を開始する準備が整いました。 実際のアプリケーションでは、大きなボットは多くのファイルに分割されますが、このチュートリアルの目的上、ボットのコードは1つのファイルに含まれます。
まず、コードのdiscord-bot
フォルダーにindex.js
という名前のファイルを作成します。
- nano index.js
discord.js
依存関係と、ボットのトークンを含む構成ファイルを要求して、ボットのコーディングを開始します。
const Discord = require("discord.js");
const config = require("./config.json");
これに続いて、次の2行のコードを追加します。
...
const client = new Discord.Client({intents: ["GUILDS", "GUILD_MESSAGES"]});
client.login(config.BOT_TOKEN);
ファイルを保存して終了します。
コードの最初の行は、新しいDiscord.Client
を作成し、それを定数client
に割り当てます。 このクライアントは、Discord APIと対話する方法と、Discordが新しいメッセージなどのイベントを通知する方法の一部です。 クライアントは、事実上、Discordボットを表しています。 Client
コンストラクターに渡されるオブジェクトは、ボットのゲートウェイインテントを指定します。 これは、ボットがリッスンするWebSocketイベントを定義します。 ここでは、GUILDS
とGUILD_MESSAGES
を指定して、ボットがギルドでメッセージイベントを受信できるようにしました。
コードの2行目は、client
のlogin
メソッドを使用して、config.json
ファイルのトークンをパスワードとして使用して、作成したDiscordボットにログインします。 トークンにより、Discord APIは、プログラムの対象となるボットと、ボットを使用するために認証されていることを知ることができます。
次に、ノードを使用してindex.js
ファイルを実行します。
- node index.js
ボットを追加したDiscordサーバーでは、ボットのステータスがオンラインに変わります。
これで、コーディング環境が正常にセットアップされ、Discordボットにログインするための基本的なコードが作成されました。 次のステップでは、ユーザーコマンドを処理し、ボットにメッセージの送信などのアクションを実行させます。
ステップ3—最初のユーザーコマンドの処理
このステップでは、ユーザーコマンドを処理できるボットを作成します。 最初のコマンドping
を実装します。これは、"pong"
とコマンドへの応答にかかる時間で応答します。
まず、コマンドを処理できるように、ユーザーが送信するメッセージを検出して受信する必要があります。 Discordクライアントでon
メソッドを使用すると、Discordは新しいイベントに関する通知を送信します。 on
メソッドは、待機するイベントの名前と、そのイベントが発生するたびに実行される関数の2つの引数を取ります。 この方法では、イベントmessage
を待つことができます。これは、ボットがメッセージを表示する権限を持っているギルドにメッセージが送信されるたびに発生します。 したがって、メッセージがプロセスコマンドに送信されるたびに実行される関数を作成します。
最初にファイルを開きます。
- nano index.js
次のコードをファイルに追加します。
...
const client = new Discord.Client({intents: ["GUILDS", "GUILD_MESSAGES"]});
client.on("messageCreate", function(message) {
});
client.login(config.BOT_TOKEN);
messageCreate
イベントで実行されるこの関数は、パラメーターとしてmessage
を取ります。 message
には、 Discord.jsメッセージインスタンスの値が含まれます。このインスタンスには、送信されたメッセージとボットの応答に役立つメソッドに関する情報が含まれています。
次に、コマンド処理関数に次のコード行を追加します。
...
client.on("messageCreate", function(message) {
if (message.author.bot) return;
});
...
この行は、メッセージの作成者がボットであるかどうかを確認し、ボットである場合はコマンドの処理を停止します。 通常、ボットのメッセージを処理したり、応答したりしたくないため、これは重要です。 ボットは通常、他のボットからの情報を使用する必要がないため、ボットのメッセージを無視すると、処理能力が節約され、誤って返信されるのを防ぐことができます。
次に、コマンドハンドラーを作成します。 これを実現するには、Discordコマンドの通常の形式を理解することをお勧めします。 通常、Discordコマンドの構造には、プレフィックス、コマンド名、および(場合によっては)コマンド引数の3つの部分が次の順序で含まれます。
-
プレフィックス:プレフィックスは何でもかまいませんが、通常はメッセージの先頭にはない句読点または抽象的なフレーズです。 これは、メッセージの先頭にプレフィックスを含めると、ボットはこのコマンドの意図がボットがそれを処理することであることを認識していることを意味します。
-
コマンド名:ユーザーが使用するコマンドの名前。 これは、ボットが異なる機能を持つ複数のコマンドをサポートし、ユーザーが異なるコマンド名を指定することでそれらから選択できることを意味します。
-
引数:コマンドがユーザーからの追加情報を必要とするか使用する場合、ユーザーはコマンド名の後に引数を指定できます。各引数はスペースで区切られます。
注:強制されたコマンド構造はなく、ボットはコマンドを好きなように処理できますが、ここに示す構造は、大多数のボットが使用する効率的な構造です。
この形式を処理するコマンドパーサーの作成を開始するには、メッセージ処理関数に次のコード行を追加します。
...
const prefix = "!";
client.on("messageCreate", function(message) {
if (message.author.bot) return;
if (!message.content.startsWith(prefix)) return;
});
...
コードの最初の行を追加して、値"!"
を定数prefix
に割り当てます。これは、ボットのプレフィックスとして使用します。
追加するコードの2行目は、ボットが処理しているメッセージのコンテンツが設定したプレフィックスで始まっているかどうかを確認し、そうでない場合は、メッセージの処理の続行を停止します。
ここで、メッセージの残りの部分をコマンド名とメッセージに存在する可能性のある引数に変換する必要があります。 次の強調表示された行を追加します。
...
client.on("messageCreate", function(message) {
if (message.author.bot) return;
if (!message.content.startsWith(prefix)) return;
const commandBody = message.content.slice(prefix.length);
const args = commandBody.split(' ');
const command = args.shift().toLowerCase();
});
...
ここで最初の行を使用して、メッセージコンテンツからプレフィックスを削除し、結果を定数commandBody
に割り当てます。 解析されたコマンド名にプレフィックスを含めたくないので、これが必要です。
2行目は、プレフィックスが削除されたメッセージを受け取り、 split method を使用し、区切り文字としてスペースを使用します。 これにより、サブ文字列の配列に分割され、スペースがある場所で分割されます。 これにより、コマンド名を含む配列が作成され、メッセージに含まれている場合は引数が含まれます。 この配列を定数args
に割り当てます。
3行目は、args
配列(指定されたコマンド名)から最初の要素を削除し、小文字に変換してから、定数command
に割り当てます。 これにより、コマンド名を分離し、配列に引数のみを残すことができます。 また、Discordボットではコマンドは通常大文字と小文字を区別しないため、toLowerCase
メソッドも使用します。
これで、コマンドパーサーの構築、必要なプレフィックスの実装、およびメッセージからのコマンド名と引数の取得が完了しました。 次に、特定のコマンドのコードを実装して作成します。
次のコードを追加して、ping
コマンドの実装を開始します。
...
const args = commandBody.split(' ');
const command = args.shift().toLowerCase();
if (command === "ping") {
}
});
...
このifステートメントは、解析した(定数command
に割り当てられた)コマンド名が"ping"
と一致するかどうかを確認します。 含まれている場合は、ユーザーが"ping"
コマンドを使用することを示しています。 特定のコマンドのコードをif
ステートメントブロック内にネストします。 実装する他のコマンドについても、このパターンを繰り返します。
これで、"ping"
コマンドのコードを実装できます。
...
if (command === "ping") {
const timeTaken = Date.now() - message.createdTimestamp;
message.reply(`Pong! This message had a latency of ${timeTaken}ms.`);
}
...
ファイルを保存して終了します。
"ping"
コマンドブロックを追加して、Date
オブジェクトでnowメソッドを使用して検出された現在の時刻とメッセージが作成されたときのタイムスタンプの差を計算します。ミリ秒。 これは、メッセージの処理にかかった時間とボットの"ping"
を計算します。
2行目は、message
定数でreply
メソッドを使用してユーザーのコマンドに応答します。 reply method ping(ユーザーに通知し、指定されたユーザーへのメッセージを強調表示します)コマンドを呼び出したユーザーに、メソッドの最初の引数として提供されたコンテンツが続きます。 reply
メソッドが使用する応答として、メッセージと計算されたpingを含むテンプレートリテラルを提供します。
これで、"ping"
コマンドの実装は終了です。
次のコマンドを使用してボットを実行します(index.js
と同じフォルダー内)。
- node index.js
これで、ボットが表示およびメッセージを送信できる任意のチャネルでコマンド"!ping"
を使用できるようになり、応答が得られます。
これで、ユーザーコマンドを処理できるボットが正常に作成され、最初のコマンドが実装されました。 次のステップでは、sumコマンドを実装してボットの開発を続けます。
ステップ4—Sumコマンドの実装
次に、"!sum"
コマンドを実装してプログラムを拡張します。 このコマンドは、すべての引数の合計をユーザーに返す前に、任意の数の引数を取り、それらを合計します。
Discordボットがまだ実行中の場合は、CTRL + C
でそのプロセスを停止できます。
index.js
ファイルをもう一度開きます。
- nano index.js
"!sum"
コマンドの実装を開始するには、else-if
ブロックを使用します。 pingコマンド名を確認した後、コマンド名が"sum"
と等しいかどうかを確認します。 一度に処理されるコマンドは1つだけなので、else-if
ブロックを使用します。したがって、プログラムがコマンド名"ping"
と一致する場合、"sum"
をチェックする必要はありません。 ] 指図。 次の強調表示された行をファイルに追加します。
...
if (command === "ping") {
const timeTaken = Date.now() - message.createdTimestamp;
message.reply(`Ping! This message had a latency of ${timeTaken}ms.`);
}
else if (command === "sum") {
}
});
...
"sum"
コマンドのコードの実装を開始できます。 "sum"
コマンドのコードは、作成したelse-if
ブロック内に配置されます。 ここで、次のコードを追加します。
...
else if (command === "sum") {
const numArgs = args.map(x => parseFloat(x));
const sum = numArgs.reduce((counter, x) => counter += x);
message.reply(`The sum of all the arguments you provided is ${sum}!`);
}
...
引数リストでmapメソッドを使用し、args
配列の各項目でparseFloat 関数を使用して、新しいリストを作成します。 これにより、すべての項目が文字列ではなく数値である新しい配列(定数numArgs
に割り当てられます)が作成されます。 これは、後でそれらを合計することにより、数値の合計を正常に見つけることができることを意味します。
2行目は、定数numArgs
でreduceメソッドを使用して、リスト内のすべての要素を合計する関数を提供します。 numArgs
のすべての要素の合計を定数sum
に割り当てます。
次に、メッセージオブジェクトでreply
メソッドを使用して、ユーザーがボットに送信するすべての引数の合計を含むテンプレートリテラルでユーザーのコマンドに応答します。
これで、"sum"
コマンドの実装は終了です。 次に、次のコマンドを使用してボットを実行します(index.js
と同じフォルダー内)。
- node index.js
これで、ボットが表示およびメッセージを送信できる任意のチャネルで"!sum"
コマンドを使用できます。
以下は、index.js
ボットスクリプトの完成版です。
const Discord = require("discord.js");
const config = require("./config.json");
const client = new Discord.Client({intents: ["GUILDS", "GUILD_MESSAGES"]});
const prefix = "!";
client.on("messageCreate", function(message) {
if (message.author.bot) return;
if (!message.content.startsWith(prefix)) return;
const commandBody = message.content.slice(prefix.length);
const args = commandBody.split(' ');
const command = args.shift().toLowerCase();
if (command === "ping") {
const timeTaken = Date.now() - message.createdTimestamp;
message.reply(`Pong! This message had a latency of ${timeTaken}ms.`);
}
else if (command === "sum") {
const numArgs = args.map(x => parseFloat(x));
const sum = numArgs.reduce((counter, x) => counter += x);
message.reply(`The sum of all the arguments you provided is ${sum}!`);
}
});
client.login(config.BOT_TOKEN);
このステップでは、sum
コマンドを実装して、Discordボットをさらに開発しました。
結論
これで、複数の異なるユーザーコマンドとコマンド引数を処理できるDiscordボットが正常に実装されました。 ボットを拡張したい場合は、より多くのコマンドを実装するか、Discord APIのより多くの部分を試して、強力なDiscordボットを作成することができます。 Discord.jsドキュメントまたはDiscordAPIドキュメントを確認して、DiscordAPIの知識を深めることができます。 特に、ボットコマンドをスラッシュコマンドに変換できます。これは、Discord.jsv13のベストプラクティスです。
Discordボットを作成するときは、開発者がDiscordAPIを使用する方法を概説したDiscordAPIの利用規約を常に念頭に置く必要があります。 Node.jsの詳細については、Node.jsシリーズのコーディング方法をご覧ください。