🐼

Firebase Cloud FunctionsでDiscordボットを手軽に構築

2023/04/11に公開約3,600字

こんにちは。普段はフロントエンドエンジニアとして開発に携わっているみのると申します。

今回は、Firebase Cloud Functionsを使って、FirebaseのFirestoreに条件を指定した書き込みが行われた際に、Discordにも通知が届くようなシステムを構築していきたいと思います。

以下が今回作成したGitHubリポジトリです。
https://github.com/nt-mino/firebase-discord

手順

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の実装

先にサンプルコードを掲示します。

コード

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にも対応していますので、もし興味があれば試してみてください。

もし間違いや不明な箇所があれば、コメントにてお知らせいただけると幸いです。

脚注

  1. https://firebase.google.com/docs/functions/manage-functions?hl=ja
  2. https://firebase.google.com/docs/functions/get-started?hl=ja
  3. https://firebase.google.com/docs/functions/firestore-events?hl=ja

Discussion

ログインするとコメントできます