Published by A&A Agency Updated at:

A&a

  Front-endAngularReactUIJavascriptWebsiteAppUXFirebaseHTML 5SASS developers  

Back

How to Send a Slack Message with PubSub Firebase Cloud Functions

First published:

front-end developers
build a website
build an app
coding tutorial
website help
user experience
firebase
typescript
firebase cloud functions
pubsub
slack
slack-api

A casestudy using Firebase Pub/Sub Cloud Functions to send a Slack message to a specific channel, with code examples showing how to publish the message to a topic and retrieve it in a subscriber to forward on to the Slack API.

Front-end developers building an app or website may need to implement serverless solutions for backend functionality. PubSub Cloud Functions provide one such serverless solution for running code in response to events, without the need to manage servers or infrastructure.

Firebase is a platform that offers a suite of tools to build and operate apps. Firebase Cloud Functions is a serverless solution offered by Firebase that enables developers to run backend code in response to events, such as changes in data in Firebase Realtime Database or Firebase Cloud Firestore.

In this article, we will explore how to use Firebase Cloud Functions and the PubSub messaging pattern to send a Slack message from a serverless environment. We will also use TypeScript to write our code.

Why Use PubSub Messaging Pattern?

PubSub messaging is a popular messaging pattern used in serverless environments. It allows for decoupling of the components of an application by separating publishers from subscribers. Publishers send messages to a topic, while subscribers receive messages from the same topic.

In a serverless environment, this pattern can be used to trigger Cloud Functions in response to messages published to a topic. Cloud Functions can subscribe to a topic and execute when messages are published to that topic.

How to Use Firebase Cloud Functions and PubSub to Send a Slack Message

To send a Slack message from a Firebase Cloud Function using PubSub, we need to implement two Cloud Functions:

  1. A function that publishes a message to a PubSub topic when triggered by an HTTP request.

  2. A function that subscribes to the PubSub topic and sends the Slack message when triggered by the message published to the topic.

Lets look at these functions in detail. But first, we will look at PubSub functions in a little more detail, as this is key to our implementation.

What is a PubSub function?

PubSub functions, also known as publish-subscribe functions, implement the PubSub messaging pattern. In this pattern, messages are published to a topic, and subscribers receive these messages from the topic asynchronously. This decouples the publishers and subscribers, allowing for greater flexibility and scalability in distributed systems.

PubSub functions are particularly useful in event-driven architectures, where they can be used to trigger actions in response to certain events. For example, a PubSub function can be used to send a notification to a user when a new message is received, or to update a database record when a user makes a purchase. By leveraging PubSub functions, developers can build event-driven systems that are highly scalable, fault-tolerant, and cost-effective.

Subscribing to a Firebase PubSub Topic

In creating our Firebase PubSub Cloud Function, we first need to subscribe to a topic. The Firebase Functions SDK provides built-in facilities for us to do exactly that. Here's an example of how to create a Firebase Cloud Function that subscribes to the alert-message topic and logs any received messages:

import * as functions from "firebase-functions"; import { TOPICS } from "./vars"; /** * Cloud Function that subscribes to the "alert-message" PubSub topic * and logs any received messages. */ export = functions.pubsub.topic(TOPICS.AlertMessage).onPublish( async (message) => { try { // Extract the message data const data = message.json; functions.logger.log("Received message:", data); } catch (error) { functions.logger.error("Error processing message", error); } } );

In this function, we define a Cloud Function that subscribes to the alert-message topic using the functions.pubsub.topic().onPublish() method. Whenever a message is published to the topic, the function is triggered and logs the received message data to the console.

Triggering a Slack Message from a Firebase Cloud Function

Now that we have subscribed to the alert-message PubSub topic, we can create a Cloud Function that triggers when a message is received on the topic and sends it on via a webhook to the Slack API. Webhooks can be set up within the Slack interface to post messages to a specific channel (instructions here).

Using the function shell we wrote above, here's an example of how to write a Firebase Cloud Function in TypeScript that sends the message on to a Slack webhook:

import * as functions from "firebase-functions"; import axios, { AxiosRequestConfig } from 'axios'; import { SLACK_WEBHOOK_URL, TOPICS } from "./vars"; export = functions.pubsub.topic(TOPICS.AlertMessage).onPublish( async (message) => { try { let data = message.json; if (!data && message.data) { data = JSON.parse(Buffer.from(message.data, 'base64').toString()); } // Send the message to Slack const opts: AxiosRequestConfig = { headers: { 'Content-type': 'application/json' } }; return axios.post(SLACK_WEBHOOK_URL, data, opts) .then(() => { functions.logger.log("Slack message sent successfully", resp); }) .catch((error) => { functions.logger.error("Error sending Slack message", error); }); } catch (error) { functions.logger.error("Error sending Slack message", error); } } );

In this function, we initialize the Slack client using a bot token (this must be obtained from Slack - full instructions here). We then define a Cloud Function that subscribes to the alert-message topic and triggers whenever a new message is published to the topic. Inside the function, we extract the message data and construct the message text. Finally, we use the Slack Web API client to send the message to the specified channel using the chat.postMessage method, and handle any errors that may occur during the message sending process.

Publishing a Message

Now let's move on to the publisher function, which publishes a message to the alert-message topic when triggered by an HTTP request. Here's an example of how to write a Firebase Cloud Function in TypeScript that publishes a message to the alert-message topic using the @google-cloud/pubsub module:

import * as functions from "firebase-functions"; import { PubSub } from "@google-cloud/pubsub"; import { TOPICS } from "./vars"; /** * Cloud Function that publishes a message to the "alert-message" PubSub topic * when triggered by an HTTP request. */ export const publishMessageToTopic = functions.https.onRequest( async (request, response) => { // Initialize PubSub client const pubsubClient = new PubSub(); // Extract the message data from the request body const { text } = request.body; // Construct the Pub/Sub message object const messageObject = { text }; try { // Get the topic from the PubSub client const topic = pubsubClient.topic(TOPICS.AlertMessage); // Publish the message to the selected topic const resp = await topic.publishMessage({ json: messageObject }); functions.logger.log("Message published to topic successfully", resp); // Send a response to the HTTP request indicating success response.status(200).send(resp); } catch (error) { functions.logger.error("Error publishing message to topic", error); // Send a response to the HTTP request indicating failure response.status(500).send("Error publishing message to topic"); } } );

In this function, we initialize the PubSub client and define a Cloud Function that triggers when an HTTP request is received. We extract the message data from the request body, and publish the message to the my-topic topic using the publishJSON method. We then handle any errors that may occur during the message publishing process and send an appropriate response to the client.

Conclusion

In this article, we explored how to use Firebase Cloud Functions and the PubSub messaging pattern to send a Slack message from a serverless environment. We saw how to implement two Cloud Functions: one that publishes a message to a Pub/Sub topic, and one that subscribes to the same topic and sends the Slack message.

We also used TypeScript to write our code, taking advantage of its static typing and enhanced developer experience.

By leveraging serverless solutions such as Firebase Cloud Functions and messaging patterns such as Pub/Sub, front-end developers can implement powerful backend functionality without having to manage servers or infrastructure, enabling them to focus on building great apps and websites.

Notes on the code

This code utilizes a 'vars.ts' file to store a few global variables. Most notably, it includes an enum called TOPICS to store a list of available topic names. This is simply a neat way to store all the names in one place and have one version of the truth. It avoids spelling mistakes, or having to copy and paste between files. For completeness, the enum looks like this:

export enum TOPICS { AlertMessage = "alert-message", InfoMessage = "info-message", ... }