iOSエンジニアのつぶやき

毎朝8:30に iOS 関連の技術について1つぶやいています。まれに釣りについてつぶやく可能性があります。

【FCM】Functions 経由でトピック通知を登録する

今回は Firebase Cloud Messaging のトピック通知を Functions 経由で登録する方法を紹介していきたいと思います👩‍🌾

それではやっていく

Node.js で実装していくので、とりあえず FirebaseAdmin SDK を導入し、初期化します。

$ npm install firebase-admin --save
const admin = require('firebase-admin');
admin.initializeApp();

今回は notificationSettings というユーザ個別の通知設定のコレクションにドキュメントが作成された時点で、generalNotification というトピックに登録していく仕様で実装してみます。そして下記が完成したコードになります。ドキュメントの作成をトリガーに、書き込まれたデータの token を取得して subscribeToTopic() でトピックに登録しています。また、region に関してはデフォルトでは us-central1 にデプロイされてしまうので、asia-northeast1 に変更しています。

const admin = require('firebase-admin');
admin.initializeApp();

const REGION = 'asia-northeast1';
const GENERAL_NOTIFICATION_TOPIC = 'generalNotification';


exports.onNotificationSettingCreated = functions.region(REGION).firestore.document(`notificationSettings/{notificationSettingId}`).onCreate(async (snap, context) => {
    const value = snap.data().settings.isEnabledForGeneral;
    const isEnabledForGeneral = [null, undefined].includes(value) ? true : value;
    const token = snap.data().token;

    if ([null, undefined].includes(token)) {
        return console.error('Error message token not found.');
    } else if (isEnabledForGeneral) {
        await subscribeToTopic([token], GENERAL_NOTIFICATION_TOPIC);
        return;
    } else {
        return console.log('The message from the management is rejected.');
    }
});

async function subscribeToTopic(tokens, topic) {
    await admin.messaging().subscribeToTopic(tokens, topic)
        .then((response) => {
            console.log('Successfully subscribed to topic:', response);
        })
        .catch((error) => {
            console.error('Error subscribing to topic:', error);
        });
}

ついでに、トピックの購読を解除する関数も追加してみます。これはドキュメント内の settings.isEnabledForGeneral という Bool 値が更新された時にハンドリングしたいので下記のように実装します。

exports.onNotificationSettingUpdated = functions.region(REGION).firestore.document(`notificationSettings/{notificationSettingId}`).onUpdate(async (change, context) => {
    const newData = change.after.data();
    const value = newData.settings.isEnabledForGeneral;
    const isEnabledForGeneral = [null, undefined].includes(value) ? true : value;
    const token = newData.token;

    if ([null, undefined].includes(token)) {
        return console.error('Error message token not found.');
    } else {
        if (isEnabledForGeneral) {
            await subscribeToTopic([token], GENERAL_NOTIFICATION_TOPIC);
            return;
        } else {
            await unsubscribeFromTopic([tokens], GENERAL_NOTIFICATION_TOPIC);
            return;
        }
    }
});

async function unsubscribeFromTopic(tokens, topic) {
    await admin.messaging().unsubscribeFromTopic(tokens, topic)
        .then((response) => {
            console.log('Successfully unsubscribed from topic:', response);
        }).catch((error) => {
            console.error('Error unsubscribing from topic:', error);
        });
}

という感じで本日も以上になります🍺

その他の記事

yamato8010.hatenablog.com

yamato8010.hatenablog.com

yamato8010.hatenablog.com