Firebase Cloud FunctionsでDiscordボットを手軽に構築
こんにちは。普段はフロントエンドエンジニアとして開発に携わっているみのると申します。
今回は、Firebase Cloud Functionsを使って、FirebaseのFirestoreに条件を指定した書き込みが行われた際に、Discordにも通知が届くようなシステムを構築していきたいと思います。
以下が今回作成したGitHubリポジトリです。
手順
Firebaseの設定
まず、新規でFirebaseのプロジェクトを作成します。
次に、作成されたプロジェクトでFirestoreとFunctionsを初期化します。
プロジェクトの作成
ディレクトリを作成し、以下のコマンドを入力します。
firebase init functions
コマンドを実行すると、次のようなディレクトリ構成になります。
myproject
├── .firebaserc # firebase useでプロジェクト間を素早く切り替えるのを助ける隠しファイル
├── firebase.json # プロジェクトのプロパティを記述するファイル
└── functions # すべてのfunctionsコードが入っているディレクトリ
├── .eslintrc.json # JavaScriptのlintルールを含むオプションファイル
├── package.json # Cloud Functionsコードを説明するnpmパッケージファイル
├── index.js # Cloud Functionsコードのメインソースファイル
└── node_modules/ # package.jsonで宣言された依存関係がインストールされるディレクトリ
functionsのindex.jsの実装
先にサンプルコードを掲示します。
コード
const fetch = require("node-fetch");
const functions = require("firebase-functions");
const admin = require("firebase-admin");
// Firebaseのデフォルトアプリを初期化する
admin.initializeApp();
const channelWebhookUrl = "ここにウェブフックのURLが入ります";
exports.sendDiscordNotification = functions.firestore
.document("messages/{messageId}")
.onWrite(async (change, context) => {
const db = admin.firestore();
const messageId = context.params.messageId;
const messageDoc = await db.collection("messages").doc(messageId).get();
if (!messageDoc.exists) return;
const messageData = await messageDoc.data();
const message = `${messageData.content}`;
await fetch(channelWebhookUrl, {
method: "POST",
headers: {
Accept: "application/json",
"Content-type": "application/json",
},
body: JSON.stringify({
content: `${message}`,
}),
});
});
解説
・Cloud Firestore 関数トリガー
Firebase SDKで提供される「functions.firestore」オブジェクトを使って、特定のCloud Firestoreイベントに対応するハンドラを作成することができます。
イベントタイプ | トリガー |
---|---|
onCreate | ドキュメントが最初に書き込まれたときにトリガーされます。 |
onUpdate | すでに存在するドキュメントの値が変更されたときにトリガーされます。 |
onDelete | データを含むドキュメントが削除されたときにトリガーされます。 |
onWrite | onCreate、onUpdate または onDelete がトリガーされたときにトリガーされます。 |
今回はonWriteを使用して、作成、更新、削除が行われた際に関数が実行されるよう設定しています。
・ワイルドカードを使用してドキュメントのグループを指定する
特定のコレクション内の任意のドキュメントやドキュメントグループにトリガーを関連付ける場合、ドキュメントIDの代わりに{wildcard}
を使用します。
今回のケースでは{messageId}
を利用しています。
messageIdの内容を取得する際は、context.params.messageId
を使用して取得できます。
Discordの設定
設定画面を開き、連携サービスを選択してください。
ウェブフックを作成するを選択してください。
ウェブフックURLが作成されたら、それをコピーします。
それを先程のchannelWebhookUrl
の場所に、コピーしたウェブフックURLを貼り付けてください。
※ お名前やチャンネルはお好みで設定していただいて構いません。
cloud functionsにデプロイ
最後に以下のコマンドを入力します。
(デプロイには一定の時間がかかります。)
firebase deploy —only functions:sendDiscordNotification
おわりに
以上で、Firebase Cloud Functionsを使って、FirebaseのFirestoreに条件を指定した書き込みが行われた際に、Discordにも通知が届くようなシステムの実装を説明しました。
今回の例では、JavaScriptで実装しましたが、TypeScriptにも対応していますので、もし興味があれば試してみてください。
もし間違いや不明な箇所があれば、コメントにてお知らせいただけると幸いです。
脚注
Discussion