How to Build a Slack App with Node.js and Firebase Cloud Functions?

How to Build a Slack App with Node.js and Firebase Cloud Functions?

In this Firebase Cloud Functions tutorial, you'll learn how to build a Slack App 💬 with Node.js & Firebase Cloud Functions. A guide to serverless Slack Apps with Firebase Cloud Functions & Firestore. CyberJeff is a simple slack bot that helps automate tasks and improve productivity. Slack Apps, or Bots, allow you to extend slack with interactive features that can improve your teams productivity. The following lesson is a step-by-step guide to building a Slack App using Firebase Cloud Functions as the backend server.

Slack Apps, or Bots, allow you to extend slack with interactive features that can improve your teams productivity. The following lesson is a step-by-step guide to building a Slack App using Firebase Cloud Functions as the backend server.

Our Slack App will perform the following tasks.

  • Listen to events, such as a new user joining the #general channel.
  • Retrieve the user’s slack profile.
  • Send a private personalized message.
  • Add a slash command for user-directed actions.

Create a Slack App

At this point, it is assumed you have admin access to a Slack workspace. If not, feel free to create one to follow this tutorial.

Once you have a workspace, create a new Slack App.

Create a Slack App Create a Slack App

Verify Cloud Function Ownership

Before Slack can send events to our Cloud Function, it needs to verify that we own the server. Slack performs a handshake by sending an HTTP request with a challenge parameter to the Cloud Function, then the function must respond back with the same value.

Initialize Cloud Functions

Initialize Cloud Functions. This demo uses the TypeScript flavor.

firebase init functions

Build The Challenge Function

The function only needs to respond with the challenge one time.

export const myBot = functions.https.onRequest( (req, res) => {

  // Request from Slack
  const { challenge }  = req.body;

  // Response from You
  res.send({ challenge })

});

Deploy it

firebase deploy --only functions:myBot

Copy the Function URL from the terminal output

Copy the Function URL from the terminal output

Enter The Deployed URL

Subscribe to an event that you want to listen to, then paste in the Function URL from the last step. Slack should automatically verify the URL and give it a green checkmark ✅.

Subscribe to the member_joined_channel event. Notice how our URL is now verified. Subscribe to the member_joined_channel event. Notice how our URL is now verified.

Build the Bot

Now it’s time to do some real work.

Install Dependencies

The Slack Node SDK is a monorepo that contains several packages. The Web API can read and modify data in the workspace. Google PubSub will be used to handle long running background tasks in te following steps.

npm install @slack/web-api
npm install @google-cloud/pubsub

OAuth Token

The OAuth token is used to authenticate your bot/server into a workspace so it can interact with your channel (like post messages).

Install the app into your workspace. Install the app into your workspace.

Once installed, it will take you directly to the OAuth token. It usually starts with xoxb or xoxp.

Copy the OAuth Token Copy the OAuth Token

Copy the OAuth Token and save it as a Firebase Functions environment variable.

firebase functions:config:set slack.token=YOUR-TOKEN

Signing Secrets

When receiving events from Slack, you should validate the signing secret, which can be found in Basic Info panel. This ensures that only requests from Slack can interact with your function by decoding the digital signature of the request.

firebase functions:config:set slack.signing_secret=YOUR-TOKEN

Add Scopes (Permissions)

OAuth scopes define what your app is allowed to do. You can fine tune permissions under the OAuth & Permissions page. Follow the principle of least privledge and only allow your bot access to resources that it actually needs to do its job. In our case, we need to read a user profile and add them to a specific slack channel.

Listen to Events

Our first goal is to listen to events that happen in the Slack workspace. Slack should notify our server anytime a user joins a channel with the member_joined_channel event.

⚡ Your server must respond be quickly, within 3000ms or less, otherwise Slack will timeout and attempt to retry.

So then, how do we build an app that performs a long-running backend process? There are many right answers, but in Firebase, the best option is to enqueue a PubSub Cloud Function. It allows the initial HTTP endpoint to simply hand off the message and respond quickly to Slack.

Import the dependencies and initlizize them with the environment credentials.

import * as functions from 'firebase-functions';

import { WebClient } from '@slack/web-api';
const bot = new WebClient(functions.config().slack.token);

const { PubSub } = require('@google-cloud/pubsub');
const pubsubClient = new PubSub();

HTTP Gateway

The HTTP gateway validates the request, enqueues a PubSub message with the request, then responds with a 200 code to keep Slack happy.

Extra Snippet: verifySlackSignature

export const myBot = functions.https.onRequest( async (req, res) => {

    // Validate Signature
    verifySlackSignature(req); // See snippet above for implementation

    const data = JSON.stringify(req.body);
    const dataBuffer = Buffer.from(data);

    await pubsubClient
            .topic('slack-channel-join')
            .publisher()
            .publish(dataBuffer);

    res.sendStatus(200);

});

PubSub Function

All the heavy-lifting happens in the PubSub function because we have no time-constraints here. The message.json contains the same data you would have handled in req.body in the HTTP function.

  export const slackChannelJoin = functions.pubsub.topic('slack-channel-join')
    .onPublish(async (message, context) => {

    const { event } = message.json; 

    const { user, channel } = event;

    // TODO something cool...

});

Respond To the User as the Bot

In this section, our app makes requests to the Slack API that (1) fetch the user’s Slack profile (2) invite them to a channel, and (3) greet them with a direct message.

Note: The Slack API does not provide typings for the response object, so you’ll have to treat it as any in typescript.

export const slackChannelJoin = functions.pubsub
  .topic('slack-channel-join')
  .onPublish(async (message, context) => {

    const { event } = message.json; 

    const { user, channel } = event;

    // IDs for the channels you plan on working with
    const generalChannel = 'C12345';
    const newChannel = '#froopy-land';

    // Throw error if not on the general channel
    if (channel !== generalChannel) {
        throw Error()
    }

  // Get the full Slack profile

    const userResult = await bot.users.profile.get({ user });
    const { email, display_name } = userResult.profile as any;

    // Invite the slack user to a new channel
    const invite = await bot.channels.invite({
        channel: newChannel,
        user
    });

    // Send a Message
    const chatMessage = await bot.chat.postMessage({
        channel: newChannel,
        text: `Hey ${display_name}! So glad to have you on my Slack!`
    });

});

Additional Ideas to Try

Listen to Slash Commands

Events are great, but somethings you want to give users tools to manually kick off interactivity - that’s where slash commands come in. They work very similar to events, but are are triggered by the user entering /some-command into the workspace.

Slash commands follow the same basic flow as events Slash commands follow the same basic flow as events

Video

Nodejs Firebase Cloud webdev chatbot

What's new in Bootstrap 5 and when Bootstrap 5 release date?

How to Build Progressive Web Apps (PWA) using Angular 9

What is new features in Javascript ES2020 ECMAScript 2020

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

Random Password Generator Online

HTML Color Picker online | HEX Color Picker | RGB Color Picker

SQL-like joins in Cloud Firestore #4: Talking to Cloud Firestore from our Cloud Function

In this Firebase tutorial, we create a Cloud Function that can be called directly through a REST call. Then we set up our emulators so that we can run local instances of Cloud Functions and Cloud Firestore, and have them talk to each other

Things to know before getting your own chatbot- Custom Chatbot Development

This article gives you complete information on custom chatbots. We provide a complete understanding on chatbots and show a comparative analysis between platform chatbot and custom chatbot development

Cloud Migration Strategy

Before dipping that first toe in the cloud migration, think of devising the transition plan. 6Rs Migration Technique has become a staple of cloud migration strategy.

Hire Nodejs Developer

Looking to **hire NodeJS Developer**[https://www.dataeximit.com/node-js-development/](https://www.dataeximit.com/node-js-development/ "https://www.dataeximit.com/node-js-development/") to build a perfect back-end to your website or...

How the healthcare Industry Benefits from Hybrid Cloud Solutions? | Way2smile

Hybrid cloud solutions are the next step in the digital transformation of the healthcare industry. Here's how healthcare can benefit from cloud infrastructure.