FirebaseのCloud Functions + Firestoreでプッシュメッセージを送る

Firebase でプッシュ通知を送る方法は色々ありますが、大した処理がないので今回はサクッとサーバーレスで Cloud Functions にデプロイします。
データベースは Realtime Database もありますが、今回は Firestore を使いたいと思います。
仕様概要
- 打刻アプリの初期設定で Firebase へユーザのデバイストークンを登録
- 通知の設定が有効で出勤時間の 10 分前で未打刻ならプッシュリマインダーを投げる
- 処理の内容は Cloud Functions に Node.js でデプロイし、生成された URL を社内サーバから
cron
で叩く
構築
Firestore
users|- id|- fcmToken|- isEnabled|- isClockedIn
Firestore のユーザデータはシンプルにトークン、設定、打刻のみです。
環境
Vagrant/Ubuntu Xenial/Node.js 8
Cloud Functions は Node.js で簡単に処理をデプロイできます。Node LTS 10 を使いたいところですが、Firebase のランタイムが 8 までなので、今回は 8 で合わせました。
Xenial で普通にapt-get
でnodejs
を入れると古いバージョンしか入らないのでご 注意を。
Firebase SDK
Node と npm が入ったところで、Firebase SDK をグローバルインストールします。
$ npm install -g firebase-tools
Firebase アカウントログイン
コマンドの後アノニマスデータを Firebase に送信していいか聞かれるので y/n を入力。表示された URL をブラウザで開いて Firebase のコンソール上でログイン認証。
$ firebase login
Firebase Functions
アプリ用の directory を切ってその中でinit
します。JavaScript か TypeScript を選べるので好きな方を選びます。勝手にファイル/ディレクトリが生成されるので、functions ディレクトリの中で firebase のモジュールをインストールします。
$ mkdir APP_DIR$ cd APP_DIR$ firebase init functions$ cd functions$ npm i -s firebase-functions@latest firebase-admin@latest
Node のランタイムはデフォルトで 14 なのですが、14, 12, 10 が選べるので 12 にしたい場合はfunctions/package.json
に追記します。階層は”dependencies
“などと一緒です。
// package.json{// ..."engines": { "node": "12" }// ...}
ロジック
firebase-admin
を初期化します。
実装したい function は『exports.エンドポイント
』の形で書きます。このファンクション名がそのままエンドポイントになります。
Promise
チェーンを書いていくことになりますが、最初にトリガーするイベントを選びます。url を叩く度に起動するならfunctions.http.onRequest()
、Realtime DB のイベントでトリガーするならfunctions.database.ref().onEVENT()
、Firestore ならfunctions.firestore.document().onEVENT()
などでチェーンを始めます。(詳しくはこちら)
Firestore のインスタンスを取得するには、admin.firestore()
で取得し、collection
を選択、get()
でスナップショットを取得します。ここで返ってくるスナップショットでforEach
を回してdocument
を取りに行きます。id はそのまま.id で取得できますが、データはdata()
で取得し、あとはそれぞれのキーで内容を取得します。
通知設定が有効で、まだ打刻しないユーザのトークンを配列に詰め込んでいきます。
トークンが集まったところで、admin.messaging()
のsendToDevice()
を使ってプッシュ通知を送っていきます。第一引数はトークンの String 配列、第二引数にペイロードを渡します。
結果のオブジェクトがPromise
で渡ってくるので、中身を見てエラーがないか確認します。(特に処理は入れてませんが、エラーコードを見てトークンが無効になっていた場合などは削除するなどの処理を入れます。)
レスポンスは特に返す必要はないですが、、一応返しています。Node.js のhttps
ですので、同じようにResponse
オブジェクトで返します。
全体像はこんな感じです。
デプロイ
デプロイは Firebase SDK のコマンド一発で行います。アカウントに権限があることを確認してください。
$ firebase deploy --only functions --project PROJECT_ID
URL が表示されれば成功です。コンソール上からもファンクションがデプロイされているのが確認できます。curl やブラウザで URL にアクセスすると、処理が走ってプッシュ通知が送られてきます。
github のレポジトリはこちら