Отправка уведомлений Firebase Cloud Messaging из терминала

  • #code
  • #it
  • #problem-solving

Проблема

Если вы только начали использовать FCM, возможно, вы бы хотели отправлять уведомления не только в одну тему, а в несколько, причем с разными условиями.

Это возможно, например:

('en' in topics) && ('blog' in topics)

Однако, на момент написания этого текста, в консоли Firebase отсутствует возможность создавать компании с таким условием.

Решение

Можно написать простенькую утилиту для отправки уведомлений прямо из командной строки с помощью Admin SDK.

Я использовал Handlebars для подстановки данных в JSON шаблон.

import {program} from "commander";  
import {initializeApp} from "firebase-admin/app";  
import {cert} from "firebase-admin/app";  
import Handlebars from "handlebars";  
  
import {getMessaging} from "firebase-admin/messaging";  
import {readFile} from "node:fs/promises";  
import {createInterface} from "node:readline";  
import nestedProperty from "nested-property";  
import chalk from "chalk";  
  
  
  
const rl = createInterface({  
    input: process.stdin,  
    output: process.stdout,  
})  
  
async function q(query) {  
    return await new Promise(resolve => {  
        return rl.question(query, resolve)  
    })  
}  
  
program  
    .version("0.0.1")  
    .description("Command line tool for sending notifications with FCM")  
    .command("send <template_file> <credentials_file>")  
    .description("Send notification")  
    .action(async (template_file, credentials_file) => {  
        // Init app  
        initializeApp({  
            credential: cert(credentials_file)  
        });  
  
        const template = await readFile(template_file, 'utf8')  
  
        const compiledTemplate = Handlebars.compile(template);  
  
        let context = {}  
        // Спрашиваем у пользователя значения для всех найденных переменных
        for (let variable of template.matchAll(/{{[{]?(.*?)[}]?}}/g)) {  
            variable = variable[1].trim()  
  
            nestedProperty.set(context, variable, await q(chalk.green(`Enter ${chalk.yellow(variable)}: `)))  
        }  
        const jsonValue = compiledTemplate(context);  
  
        console.log(chalk.green("Template with applied values:"))  
        console.log(jsonValue);  
        if ((await q(chalk.yellow("Send? (y/N):"))) === 'y') {  
            await getMessaging().send(JSON.parse(jsonValue));  
            console.log(chalk.green("DONE"));  
            process.exit(0);  
        } else {  
            console.log(chalk.red("Cancelled"));  
        }  
    })  
;  
program.parse(process.argv);

Затем, можно использовать такого вида шаблоны:

{  
  "notification": {  
    "title": "Check out new blogpost at captaindno.xyz",  
    "body": "{{ body }}"  
  },  
  "webpush": {  
    "fcmOptions": {  
      "link": "{{ link }}"  
    }  
  },  
  "condition": "('en' in topics) && ('blog' in topics)"  
}

Это очень простой пример, его можно и нужно переделать под себя. Весь код доступен на GitHub

Кажется (но это не точно), вам нравится мой контент. Перейдите в раздел настроек, чтобы подписаться на пуш-уведомления или разрешить сбор аналитических данных, которые позволяют улучшать этот сайт и его содержимое.

Перейти к настройкам