Learn how to build a Slack App 💬 with Node.js & Firebase Cloud Functions. CyberJeff is a simple slack bot that helps automate tasks and improve productivity https://fireship.io/lessons/how-to-build-a-slack-bot/

Let's chat on Fireship Slack https://fireship.page.link/slack

Slack API https://api.slack.com/
PubSub https://cloud.google.com/pubsub/

#slack #nodejs #firebase

Install the quiz app 🤓

iOS https://itunes.apple.com/us/app/fireship/id1462592372?mt=8
Android https://play.google.com/store/apps/details?id=io.fireship.quizapp

Upgrade to Fireship PRO at https://fireship.io/pro
Use code lORhwXd2 for 25% off your first payment. 

My VS Code Theme:

- Atom One Dark 
- vscode-icons
- Fira Code Font
2024-02-04T06:28:12.297Z
nova-2
2-general-nova
2024-01-09.29447
30089e05-99d1-4376-b32e-c263170674af
1e61a6b3-9a38-465e-b20f-304a61307f55
8cb8822554dabc227392b8088c3ec685da5b6c65850335192fb43e91d4485742
67875a7f-c9c4-48a0-aa55-5bdb8a91c34a
deprecated
Today, I'm going to show you how I built CyberJeth, a Slack app that helps me automate things that I would otherwise have to do manually for members of our Slack channel.
If you're not already in our Slack, you should join with the link in the description.
It's a great way to communicate and you can chat with me personally along with a bunch of other developers working on a similar stack.
If you're already a pro member, you should be summoned by Cyber Jeff.
He's a faster and more reliable version of me.
When you first join the Slack channel, he'll check to c if your email has a matching account in the Firestore database with pro status.
If there's a match, he'll invite you to our pro channel and tell you how to redeem a sticker her and t shirt.
Now this is a very personalized Slack app for my business needs, but in today's video, I want to show you how to build your own from scratch.
If you're new here, like and subscribe and Check out the full write up on Fireship IO.
Now, before you start building a Slack app, you should start by outlining your actual use case because their API is absolutely massive.
It allows you to automate things within the workspace, create chatbots, interactive UI elements, and a whole bunch of other Thanks.
But if you're a developer, there are two main reasons you would build a Slack app in the first place.
Companies already using Slack may want to enhance some sort of internal process or communication flow.
That's essentially what CyberJeph is.
It's mostly an automation tool, but also serves as our new AI overlord on Slack.
The other reason you might wanna build a Slack App is to build a service to be consumed by other Slack users.
Slack has a public directory for third party apps.
All you have to do is build something useful, market It well and you'll have enterprise clients throwing money at it in no time.
Let's go ahead and get started.
You'll need 2 things for this project.
You'll need some kind of Slack workspace that you have admin access to, and then we'll be using Firebase as our serverless back end with Cloud Functions.
But feel free to use whatever Node.
Js back end you prefer.
The first thing we'll do is create a new Slack app.
You can do this from the Slack API homepage, and you'll see a big button there to create a new app.
Now like I said before, the API is massive, so So you kind of need to know what you're building before you get started.
Some apps might want to listen and react to events that happen within the workspace, while others might want to fetch or post information into it, like post new messages and things like that, or in our case, a combination of both.
We want our server to listen to the Slack event of when a new user is added to a channel and then react to it by posting a new message into the Slack workspace.
If you're not sure which API you actually need, I would highly recommend following this flowchart provided by Slack.
Now getting back to the Slack admin panel, let's enable Events.
Events are essentially outbound webhooks that allow you to listen to events that happen within the Slack workspace or events triggered by a bot.
In our case, we only care about one event, which is the member join channel event.
We simply select that from the drop down, and then you'll notice it's asking us for a request URL.
This URL will be an HTTP Firebase Cloud Function.
But before we can use it, we need to verify that we actually own it with Slack.
So you can see right now, it's currently unverified.
Let's go ahead and open up Versus Code, and then we'll open a terminal session and run Firebase init functions.
I'll be using the TypeScript flavor for this video to show you some of the out there, but feel free to use vanilla JavaScript if you prefer.
Now let's go ahead and get our endpoint verified.
All we need is an HTTP cloud function.
This function will receive a challenge parameter from the request body sent by Slack.
We simply receive the challenge parameter and then send it back as the response.
Now let's go back to the terminal and run firebase deploy.
After a minute or so, that should deploy the function and give us back our function's URL.
Go ahead and copy and paste that value as the Slack request URL.
You should immediately get a green check mark.
So now that the endpoint is verified, it's time to build something useful.
We need to make sure that our app is fully secure, and there's a couple of steps involved in that depending on the types of APIs that you plan on using.
Now back to the terminal for our Cloud Function, we'll install the Slack web API along with Google Cloud PubSub, and I'll explain why that's needed in a few minutes.
Slack provides a big monorepo with a bunch of different packages.
The web API is used if you want to post messages into Slack or modify things in the workspace.
In order to use it in a workspace, we need to authenticate it with an OAuth token.
The token is unique to the workspace and not the app itself.
So each workspace that has this app installed will have a different OAuth token.
Since this is a private app installed in a single workspace, We'll simply install it, which will take us directly to the OAuth tokens for the team.
You'll want to copy this value and then head over to the command line once again, and we'll set it up as an environment variable in the Cloud Functions environment by running Firebase functions config set Slack dot token equals ROauthoken.
And And that's the only credential you need for the Slack web API.
But our app is also listening to incoming events from Slack, so we need a way to verify that those requests are actually legitimate.
Because it's possible for a hacker to send fake requests to our Cloud Function URL.
We can prevent that by going to the basic information page and grabbing our sign in secret.
We'll also use the Firebase functions config set command to add this as an environment variable.
Now validating the signing secret from scratch is kind of a pain, So I actually put together a dedicated snippet on Fireship IO just for this purpose.
Slack has an Events API package that can do some of this for you automatically, but it doesn't really work well in a serverless environment.
All we have to do is perform timing safe string comparison using double hash message authentication code, which, of course, is something that every programmer should know how to do with their eyes Closed.
You'll see a more detailed description in the snippet, but, basically, we're taking our signing secret and then comparing it to a signature that Slack provides in the header.
If the final values match, then we know we have a valid request.
Otherwise, we reject it.
Now let's get on with the actual code implementation of the Slack app.
We'll go ahead and import the web client from Slack web API, then we'll initialize the client using the Slack token that we saved to the functions environment.
Then we'll also instantiate Google Pub Sub here.
So let me take a second to explain why we need Pub Sub.
If you're not familiar with it, it's a service that allows you to pass messages between different Google Cloud Services.
So it's very similar to HTTP, but it's fully secure within the Google Cloud infrastructure.
Now the Slack API requires that their initial request is responded to within 3000 milliseconds or 3 seconds.
If you don't respond within that time, you'll get a timeout error, and then Slack will try to retry that same endpoint.
If your app has a long running back end process, like it makes API request to some other API, then you'll need to queue up some type of background job to handle that work outside of the 3,000 millisecond limitation.
And that's exactly what our pubsub function will do.
So that means the only responsibility of the HTTP function is to verify the signature and then queue up the background job.
We can do that by stringifying the initial request body, converting it to a buffer, then using the PubSub client to publish to a specific topic using that buffer.
So, So essentially, what this does is it takes the request body and then passes it off to a PubSub function that we can handle in the next step.
And lastly, Make sure to send a response to Slack with a 200 status code.
So what we've done here is passed off all the heavy lifting to a pubsub function, which has no time limitation, so feel free to take as long as you want to handle it.
We can set up the Cloud Function, making sure to point to the same topic that we published to.
The on publish callback will give us access to the message, which has the same data contained in the original request body.
The data that's available here depends entirely on the type of event that Stripe has sent to your back end.
You'll need to mostly reference the Stripe API docs Because even though we're in TypeScript, it doesn't provide typings for the actual response data types.
When a new user is added to a channel, it will give us an event which we can access on the message JSON.
And then we can grab the user and the channel from that event.
So that gives us a user ID and a channel ID from Slack.
In this implementation, we only want to run the code if the user is being added to the general channel for the first time.
If that's not the case, we can throw an error or just return null from the function.
Now the first thing we wanna do is take that user ID and grab the full user profile, which will contain the email address and display name of that user on Slack.
We can do that by making a request with bot users profile get.
That will give us a web API response, And the actual data we want is on the result profile.
And that's an unknown type, so we'll go ahead and cast it to any so we can destructure the properties on it.
Now before we go any further, we'll need to make sure that our bot has the proper permission to read a user's profile.
You can set up permissions or scopes for your bot on the admin area for the Slack app.
You'll wanna use the principle of least privilege here and only grant access to the actual operations that your bot needs to do its job.
Now that we have the user's email address, we could make a query to Firestore to grab that actual user record from the database, but I think we should just stick to the Slack API for this demo.
We'll go ahead and invite that user to a new channel, then have the bot send them a direct message with some text that welcomes them to the new channel.
And that's basically all there is to it.
We now have a fast and secure serverless backend for building our Slack app, but there's a lot more we can do beyond this simple use case.
If you want to build a full blown conversational bot, consider using something like Dialogflow.
It makes it super easy to build bots that have human like conversations similar to the Google Assistant or Alexa, and you can add it to your Slack channel with just a few button clicks.
And if you want to make the responses from the app more interactive with buttons and images and things like that, check out BlockKit.
It's a UI framework specifically for Slack.
I'm gonna go ahead and wrap things up there.
If this video helped you, please like and subscribe, and consider becoming a pro member at FireShip IO.
You'll get access to Cyber Jeff who can only be used by pro members, but more importantly, you'll get access to a whole bunch of advanced content.
Thanks for watching, and I will talk to you soon.

Speaker 0: Today, I'm going to show you how I built CyberJeth, a Slack app that helps me automate things that I would otherwise have to do manually for members of our Slack channel. If you're not already in our Slack, you should join with the link in the description. It's a great way to communicate and you can chat with me personally along with a bunch of other developers working on a similar stack. If you're already a pro member, you should be summoned by Cyber Jeff. He's a faster and more reliable version of me.

When you first join the Slack channel, he'll check to c if your email has a matching account in the Firestore database with pro status. If there's a match, he'll invite you to our pro channel and tell you how to redeem a sticker her and t shirt. Now this is a very personalized Slack app for my business needs, but in today's video, I want to show you how to build your own from scratch. If you're new here, like and subscribe and Check out the full write up on Fireship IO. Now, before you start building a Slack app, you should start by outlining your actual use case because their API is absolutely massive.

It allows you to automate things within the workspace, create chatbots, interactive UI elements, and a whole bunch of other Thanks. But if you're a developer, there are two main reasons you would build a Slack app in the first place. Companies already using Slack may want to enhance some sort of internal process or communication flow. That's essentially what CyberJeph is. It's mostly an automation tool, but also serves as our new AI overlord on Slack.

The other reason you might wanna build a Slack App is to build a service to be consumed by other Slack users. Slack has a public directory for third party apps. All you have to do is build something useful, market It well and you'll have enterprise clients throwing money at it in no time. Let's go ahead and get started. You'll need 2 things for this project.

You'll need some kind of Slack workspace that you have admin access to, and then we'll be using Firebase as our serverless back end with Cloud Functions. But feel free to use whatever Node. Js back end you prefer. The first thing we'll do is create a new Slack app. You can do this from the Slack API homepage, and you'll see a big button there to create a new app.

Now like I said before, the API is massive, so So you kind of need to know what you're building before you get started. Some apps might want to listen and react to events that happen within the workspace, while others might want to fetch or post information into it, like post new messages and things like that, or in our case, a combination of both. We want our server to listen to the Slack event of when a new user is added to a channel and then react to it by posting a new message into the Slack workspace. If you're not sure which API you actually need, I would highly recommend following this flowchart provided by Slack. Now getting back to the Slack admin panel, let's enable Events.

Events are essentially outbound webhooks that allow you to listen to events that happen within the Slack workspace or events triggered by a bot. In our case, we only care about one event, which is the member join channel event. We simply select that from the drop down, and then you'll notice it's asking us for a request URL. This URL will be an HTTP Firebase Cloud Function. But before we can use it, we need to verify that we actually own it with Slack.

So you can see right now, it's currently unverified. Let's go ahead and open up Versus Code, and then we'll open a terminal session and run Firebase init functions. I'll be using the TypeScript flavor for this video to show you some of the out there, but feel free to use vanilla JavaScript if you prefer. Now let's go ahead and get our endpoint verified. All we need is an HTTP cloud function.

This function will receive a challenge parameter from the request body sent by Slack. We simply receive the challenge parameter and then send it back as the response. Now let's go back to the terminal and run firebase deploy. After a minute or so, that should deploy the function and give us back our function's URL. Go ahead and copy and paste that value as the Slack request URL.

You should immediately get a green check mark. So now that the endpoint is verified, it's time to build something useful. We need to make sure that our app is fully secure, and there's a couple of steps involved in that depending on the types of APIs that you plan on using. Now back to the terminal for our Cloud Function, we'll install the Slack web API along with Google Cloud PubSub, and I'll explain why that's needed in a few minutes. Slack provides a big monorepo with a bunch of different packages.

The web API is used if you want to post messages into Slack or modify things in the workspace. In order to use it in a workspace, we need to authenticate it with an OAuth token. The token is unique to the workspace and not the app itself. So each workspace that has this app installed will have a different OAuth token. Since this is a private app installed in a single workspace, We'll simply install it, which will take us directly to the OAuth tokens for the team.

You'll want to copy this value and then head over to the command line once again, and we'll set it up as an environment variable in the Cloud Functions environment by running Firebase functions config set Slack dot token equals ROauthoken. And And that's the only credential you need for the Slack web API. But our app is also listening to incoming events from Slack, so we need a way to verify that those requests are actually legitimate. Because it's possible for a hacker to send fake requests to our Cloud Function URL. We can prevent that by going to the basic information page and grabbing our sign in secret.

We'll also use the Firebase functions config set command to add this as an environment variable. Now validating the signing secret from scratch is kind of a pain, So I actually put together a dedicated snippet on Fireship IO just for this purpose. Slack has an Events API package that can do some of this for you automatically, but it doesn't really work well in a serverless environment. All we have to do is perform timing safe string comparison using double hash message authentication code, which, of course, is something that every programmer should know how to do with their eyes Closed. You'll see a more detailed description in the snippet, but, basically, we're taking our signing secret and then comparing it to a signature that Slack provides in the header.

If the final values match, then we know we have a valid request. Otherwise, we reject it. Now let's get on with the actual code implementation of the Slack app. We'll go ahead and import the web client from Slack web API, then we'll initialize the client using the Slack token that we saved to the functions environment. Then we'll also instantiate Google Pub Sub here.

So let me take a second to explain why we need Pub Sub. If you're not familiar with it, it's a service that allows you to pass messages between different Google Cloud Services. So it's very similar to HTTP, but it's fully secure within the Google Cloud infrastructure. Now the Slack API requires that their initial request is responded to within 3000 milliseconds or 3 seconds. If you don't respond within that time, you'll get a timeout error, and then Slack will try to retry that same endpoint.

If your app has a long running back end process, like it makes API request to some other API, then you'll need to queue up some type of background job to handle that work outside of the 3,000 millisecond limitation. And that's exactly what our pubsub function will do. So that means the only responsibility of the HTTP function is to verify the signature and then queue up the background job. We can do that by stringifying the initial request body, converting it to a buffer, then using the PubSub client to publish to a specific topic using that buffer. So, So essentially, what this does is it takes the request body and then passes it off to a PubSub function that we can handle in the next step.

And lastly, Make sure to send a response to Slack with a 200 status code. So what we've done here is passed off all the heavy lifting to a pubsub function, which has no time limitation, so feel free to take as long as you want to handle it. We can set up the Cloud Function, making sure to point to the same topic that we published to. The on publish callback will give us access to the message, which has the same data contained in the original request body. The data that's available here depends entirely on the type of event that Stripe has sent to your back end.

You'll need to mostly reference the Stripe API docs Because even though we're in TypeScript, it doesn't provide typings for the actual response data types. When a new user is added to a channel, it will give us an event which we can access on the message JSON. And then we can grab the user and the channel from that event. So that gives us a user ID and a channel ID from Slack. In this implementation, we only want to run the code if the user is being added to the general channel for the first time.

If that's not the case, we can throw an error or just return null from the function. Now the first thing we wanna do is take that user ID and grab the full user profile, which will contain the email address and display name of that user on Slack. We can do that by making a request with bot users profile get. That will give us a web API response, And the actual data we want is on the result profile. And that's an unknown type, so we'll go ahead and cast it to any so we can destructure the properties on it.

Now before we go any further, we'll need to make sure that our bot has the proper permission to read a user's profile. You can set up permissions or scopes for your bot on the admin area for the Slack app. You'll wanna use the principle of least privilege here and only grant access to the actual operations that your bot needs to do its job. Now that we have the user's email address, we could make a query to Firestore to grab that actual user record from the database, but I think we should just stick to the Slack API for this demo. We'll go ahead and invite that user to a new channel, then have the bot send them a direct message with some text that welcomes them to the new channel.

And that's basically all there is to it. We now have a fast and secure serverless backend for building our Slack app, but there's a lot more we can do beyond this simple use case. If you want to build a full blown conversational bot, consider using something like Dialogflow. It makes it super easy to build bots that have human like conversations similar to the Google Assistant or Alexa, and you can add it to your Slack channel with just a few button clicks. And if you want to make the responses from the app more interactive with buttons and images and things like that, check out BlockKit.

It's a UI framework specifically for Slack. I'm gonna go ahead and wrap things up there. If this video helped you, please like and subscribe, and consider becoming a pro member at FireShip IO. You'll get access to Cyber Jeff who can only be used by pro members, but more importantly, you'll get access to a whole bunch of advanced content. Thanks for watching, and I will talk to you soon.
Today, I'm going to show you how I built CyberJeth, a Slack app that helps me automate things that I would otherwise have to do manually for members of our Slack channel.
If you're not already in our Slack, you should join with the link in the description. It's a great way to communicate and you can chat with me personally along with a bunch of other developers working on a similar stack. If you're already a pro member, you should be summoned by Cyber Jeff.
networking
He's a faster and more reliable version of me. When you first join the Slack channel, he'll check to c if your email has a matching account in the Firestore database with pro status. If there's a match, he'll invite you to our pro channel and tell you how to redeem a sticker her and t shirt. Now this is a very personalized Slack app for my business needs, but in today's video, I want to show you how to build your own from scratch. If you're new here, like and subscribe and Check out the full write up on Fireship IO. Now, before you start building a Slack app, you should start by outlining your actual use case because their API is absolutely massive. It allows you to automate things within the workspace, create chatbots, interactive UI elements, and a whole bunch of other Thanks. But if you're a developer, there are two main reasons you would build a Slack app in the first place. Companies already using Slack may want to enhance some sort of internal process or communication flow. That's essentially what CyberJeph is. It's mostly an automation tool, but also serves as our new AI overlord on Slack. The other reason you might wanna build a Slack App is to build a service to be consumed by other Slack users. Slack has a public directory for third party apps. All you have to do is build something useful, market It well and you'll have enterprise clients throwing money at it in no time. Let's go ahead and get started. You'll need 2 things for this project. You'll need some kind of Slack workspace that you have admin access to, and then we'll be using Firebase as our serverless back end with Cloud Functions. But feel free to use whatever Node. Js back end you prefer. The first thing we'll do is create a new Slack app. You can do this from the Slack API homepage, and you'll see a big button there to create a new app. Now like I said before, the API is massive, so So you kind of need to know what you're building before you get started. Some apps might want to listen and react to events that happen within the workspace, while others might want to fetch or post information into it, like post new messages and things like that, or in our case, a combination of both. We want our server to listen to the Slack event of when a new user is added to a channel and then react to it by posting a new message into the Slack workspace. If you're not sure which API you actually need, I would highly recommend following this flowchart provided by Slack. Now getting back to the Slack admin panel, let's enable Events. Events are essentially outbound webhooks that allow you to listen to events that happen within the Slack workspace or events triggered by a bot. In our case, we only care about one event, which is the member join channel event. We simply select that from the drop down, and then you'll notice it's asking us for a request URL. This URL will be an HTTP Firebase Cloud Function. But before we can use it, we need to verify that we actually own it with Slack. So you can see right now, it's currently unverified. Let's go ahead and open up Versus Code, and then we'll open a terminal session and run Firebase init functions. I'll be using the TypeScript flavor for this video to show you some of the out there, but feel free to use vanilla JavaScript if you prefer. Now let's go ahead and get our endpoint verified. All we need is an HTTP cloud function. This function will receive a challenge parameter from the request body sent by Slack. We simply receive the challenge parameter and then send it back as the response. Now let's go back to the terminal and run firebase deploy. After a minute or so, that should deploy the function and give us back our function's URL. Go ahead and copy and paste that value as the Slack request URL. You should immediately get a green check mark. So now that the endpoint is verified, it's time to build something useful. We need to make sure that our app is fully secure, and there's a couple of steps involved in that depending on the types of APIs that you plan on using. Now back to the terminal for our Cloud Function, we'll install the Slack web API along with Google Cloud PubSub, and I'll explain why that's needed in a few minutes. Slack provides a big monorepo with a bunch of different packages. The web API is used if you want to post messages into Slack or modify things in the workspace. In order to use it in a workspace, we need to authenticate it with an OAuth token. The token is unique to the workspace and not the app itself. So each workspace that has this app installed will have a different OAuth token. Since this is a private app installed in a single workspace, We'll simply install it, which will take us directly to the OAuth tokens for the team. You'll want to copy this value and then head over to the command line once again, and we'll set it up as an environment variable in the Cloud Functions environment by running Firebase functions config set Slack dot token equals ROauthoken. And And that's the only credential you need for the Slack web API. But our app is also listening to incoming events from Slack, so we need a way to verify that those requests are actually legitimate. Because it's possible for a hacker to send fake requests to our Cloud Function URL. We can prevent that by going to the basic information page and grabbing our sign in secret. We'll also use the Firebase functions config set command to add this as an environment variable. Now validating the signing secret from scratch is kind of a pain, So I actually put together a dedicated snippet on Fireship IO just for this purpose. Slack has an Events API package that can do some of this for you automatically, but it doesn't really work well in a serverless environment. All we have to do is perform timing safe string comparison using double hash message authentication code, which, of course, is something that every programmer should know how to do with their eyes Closed. You'll see a more detailed description in the snippet, but, basically, we're taking our signing secret and then comparing it to a signature that Slack provides in the header. If the final values match, then we know we have a valid request. Otherwise, we reject it. Now let's get on with the actual code implementation of the Slack app. We'll go ahead and import the web client from Slack web API, then we'll initialize the client using the Slack token that we saved to the functions environment.
Then we'll also instantiate Google Pub Sub here. So let me take a second to explain why we need Pub Sub. If you're not familiar with it, it's a service that allows you to pass messages between different Google Cloud Services. So it's very similar to HTTP, but it's fully secure within the Google Cloud infrastructure.
google
Now the Slack API requires that their initial request is responded to within 3000 milliseconds or 3 seconds. If you don't respond within that time, you'll get a timeout error, and then Slack will try to retry that same endpoint. If your app has a long running back end process, like it makes API request to some other API, then you'll need to queue up some type of background job to handle that work outside of the 3,000 millisecond limitation. And that's exactly what our pubsub function will do. So that means the only responsibility of the HTTP function is to verify the signature and then queue up the background job. We can do that by stringifying the initial request body, converting it to a buffer, then using the PubSub client to publish to a specific topic using that buffer. So, So essentially, what this does is it takes the request body and then passes it off to a PubSub function that we can handle in the next step. And lastly, Make sure to send a response to Slack with a 200 status code. So what we've done here is passed off all the heavy lifting to a pubsub function, which has no time limitation, so feel free to take as long as you want to handle it.
We can set up the Cloud Function, making sure to point to the same topic that we published to. The on publish callback will give us access to the message, which has the same data contained in the original request body. The data that's available here depends entirely on the type of event that Stripe has sent to your back end.
publishing
You'll need to mostly reference the Stripe API docs Because even though we're in TypeScript, it doesn't provide typings for the actual response data types. When a new user is added to a channel, it will give us an event which we can access on the message JSON. And then we can grab the user and the channel from that event. So that gives us a user ID and a channel ID from Slack. In this implementation, we only want to run the code if the user is being added to the general channel for the first time. If that's not the case, we can throw an error or just return null from the function. Now the first thing we wanna do is take that user ID and grab the full user profile, which will contain the email address and display name of that user on Slack. We can do that by making a request with bot users profile get. That will give us a web API response, And the actual data we want is on the result profile. And that's an unknown type, so we'll go ahead and cast it to any so we can destructure the properties on it. Now before we go any further, we'll need to make sure that our bot has the proper permission to read a user's profile. You can set up permissions or scopes for your bot on the admin area for the Slack app. You'll wanna use the principle of least privilege here and only grant access to the actual operations that your bot needs to do its job. Now that we have the user's email address, we could make a query to Firestore to grab that actual user record from the database, but I think we should just stick to the Slack API for this demo.
We'll go ahead and invite that user to a new channel, then have the bot send them a direct message with some text that welcomes them to the new channel. And that's basically all there is to it. We now have a fast and secure serverless backend for building our Slack app, but there's a lot more we can do beyond this simple use case.
networking
telecommunications
If you want to build a full blown conversational bot, consider using something like Dialogflow. It makes it super easy to build bots that have human like conversations similar to the Google Assistant or Alexa, and you can add it to your Slack channel with just a few button clicks. And if you want to make the responses from the app more interactive with buttons and images and things like that, check out BlockKit. It's a UI framework specifically for Slack. I'm gonna go ahead and wrap things up there. If this video helped you, please like and subscribe, and consider becoming a pro member at FireShip IO. You'll get access to Cyber Jeff who can only be used by pro members, but more importantly, you'll get access to a whole bunch of advanced content. Thanks for watching, and I will talk to you soon.
robotics
multimedia
youtube
streaming
video gaming
internet
social media
software
Today, I'm going to show you how I built CyberJeth, a Slack app that helps me automate things that I would otherwise have to do manually for members of our Slack channel. If you're not already in our Slack, you should join with the link in the description. It's a great way to communicate and you can chat with me personally along with a bunch of other developers working on a similar stack. If you're already a pro member, you should be summoned by Cyber Jeff. He's a faster and more reliable version of me. When you first join the Slack channel, he'll check to c if your email has a matching account in the Firestore database with pro status. If there's a match, he'll invite you to our pro channel and tell you how to redeem a sticker her and t shirt. Now this is a very personalized Slack app for my business needs, but in today's video, I want to show you how to build your own from scratch. If you're new here, like and subscribe and Check out the full write up on Fireship IO. Now, before you start building a Slack app, you should start by outlining your actual use case because their API is absolutely massive. It allows you to automate things within the workspace, create chatbots, interactive UI elements, and a whole bunch of other Thanks. But if you're a developer, there are two main reasons you would build a Slack app in the first place. Companies already using Slack may want to enhance some sort of internal process or communication flow. That's essentially what CyberJeph is. It's mostly an automation tool, but also serves as our new AI overlord on Slack. The other reason you might wanna build a Slack App is to build a service to be consumed by other Slack users. Slack has a public directory for third party apps. All you have to do is build something useful, market It well and you'll have enterprise clients throwing money at it in no time. Let's go ahead and get started. You'll need 2 things for this project. You'll need some kind of Slack workspace that you have admin access to, and then we'll be using Firebase as our serverless back end with Cloud Functions. But feel free to use whatever Node. Js back end you prefer. The first thing we'll do is create a new Slack app. You can do this from the Slack API homepage, and you'll see a big button there to create a new app. Now like I said before, the API is massive, so So you kind of need to know what you're building before you get started. Some apps might want to listen and react to events that happen within the workspace, while others might want to fetch or post information into it, like post new messages and things like that, or in our case, a combination of both. We want our server to listen to the Slack event of when a new user is added to a channel and then react to it by posting a new message into the Slack workspace. If you're not sure which API you actually need, I would highly recommend following this flowchart provided by Slack. Now getting back to the Slack admin panel, let's enable Events. Events are essentially outbound webhooks that allow you to listen to events that happen within the Slack workspace or events triggered by a bot. In our case, we only care about one event, which is the member join channel event. We simply select that from the drop down, and then you'll notice it's asking us for a request URL. This URL will be an HTTP Firebase Cloud Function. But before we can use it, we need to verify that we actually own it with Slack. So you can see right now, it's currently unverified. Let's go ahead and open up Versus Code, and then we'll open a terminal session and run Firebase init functions. I'll be using the TypeScript flavor for this video to show you some of the out there, but feel free to use vanilla JavaScript if you prefer. Now let's go ahead and get our endpoint verified. All we need is an HTTP cloud function. This function will receive a challenge parameter from the request body sent by Slack. We simply receive the challenge parameter and then send it back as the response. Now let's go back to the terminal and run firebase deploy. After a minute or so, that should deploy the function and give us back our function's URL. Go ahead and copy and paste that value as the Slack request URL. You should immediately get a green check mark. So now that the endpoint is verified, it's time to build something useful. We need to make sure that our app is fully secure, and there's a couple of steps involved in that depending on the types of APIs that you plan on using. Now back to the terminal for our Cloud Function, we'll install the Slack web API along with Google Cloud PubSub, and I'll explain why that's needed in a few minutes. Slack provides a big monorepo with a bunch of different packages. The web API is used if you want to post messages into Slack or modify things in the workspace. In order to use it in a workspace, we need to authenticate it with an OAuth token. The token is unique to the workspace and not the app itself. So each workspace that has this app installed will have a different OAuth token. Since this is a private app installed in a single workspace, We'll simply install it, which will take us directly to the OAuth tokens for the team. You'll want to copy this value and then head over to the command line once again, and we'll set it up as an environment variable in the Cloud Functions environment by running Firebase functions config set Slack dot token equals ROauthoken. And And that's the only credential you need for the Slack web API. But our app is also listening to incoming events from Slack, so we need a way to verify that those requests are actually legitimate. Because it's possible for a hacker to send fake requests to our Cloud Function URL. We can prevent that by going to the basic information page and grabbing our sign in secret. We'll also use the Firebase functions config set command to add this as an environment variable. Now validating the signing secret from scratch is kind of a pain, So I actually put together a dedicated snippet on Fireship IO just for this purpose. Slack has an Events API package that can do some of this for you automatically, but it doesn't really work well in a serverless environment. All we have to do is perform timing safe string comparison using double hash message authentication code, which, of course, is something that every programmer should know how to do with their eyes Closed. You'll see a more detailed description in the snippet, but, basically, we're taking our signing secret and then comparing it to a signature that Slack provides in the header. If the final values match, then we know we have a valid request. Otherwise, we reject it. Now let's get on with the actual code implementation of the Slack app. We'll go ahead and import the web client from Slack web API, then we'll initialize the client using the Slack token that we saved to the functions environment. Then we'll also instantiate Google Pub Sub here. So let me take a second to explain why we need Pub Sub. If you're not familiar with it, it's a service that allows you to pass messages between different Google Cloud Services. So it's very similar to HTTP, but it's fully secure within the Google Cloud infrastructure. Now the Slack API requires that their initial request is responded to within 3000 milliseconds or 3 seconds. If you don't respond within that time, you'll get a timeout error, and then Slack will try to retry that same endpoint. If your app has a long running back end process, like it makes API request to some other API, then you'll need to queue up some type of background job to handle that work outside of the 3,000 millisecond limitation. And that's exactly what our pubsub function will do. So that means the only responsibility of the HTTP function is to verify the signature and then queue up the background job. We can do that by stringifying the initial request body, converting it to a buffer, then using the PubSub client to publish to a specific topic using that buffer. So, So essentially, what this does is it takes the request body and then passes it off to a PubSub function that we can handle in the next step. And lastly, Make sure to send a response to Slack with a 200 status code. So what we've done here is passed off all the heavy lifting to a pubsub function, which has no time limitation, so feel free to take as long as you want to handle it. We can set up the Cloud Function, making sure to point to the same topic that we published to. The on publish callback will give us access to the message, which has the same data contained in the original request body. The data that's available here depends entirely on the type of event that Stripe has sent to your back end. You'll need to mostly reference the Stripe API docs Because even though we're in TypeScript, it doesn't provide typings for the actual response data types. When a new user is added to a channel, it will give us an event which we can access on the message JSON. And then we can grab the user and the channel from that event. So that gives us a user ID and a channel ID from Slack. In this implementation, we only want to run the code if the user is being added to the general channel for the first time. If that's not the case, we can throw an error or just return null from the function. Now the first thing we wanna do is take that user ID and grab the full user profile, which will contain the email address and display name of that user on Slack. We can do that by making a request with bot users profile get. That will give us a web API response, And the actual data we want is on the result profile. And that's an unknown type, so we'll go ahead and cast it to any so we can destructure the properties on it. Now before we go any further, we'll need to make sure that our bot has the proper permission to read a user's profile. You can set up permissions or scopes for your bot on the admin area for the Slack app. You'll wanna use the principle of least privilege here and only grant access to the actual operations that your bot needs to do its job. Now that we have the user's email address, we could make a query to Firestore to grab that actual user record from the database, but I think we should just stick to the Slack API for this demo. We'll go ahead and invite that user to a new channel, then have the bot send them a direct message with some text that welcomes them to the new channel. And that's basically all there is to it. We now have a fast and secure serverless backend for building our Slack app, but there's a lot more we can do beyond this simple use case. If you want to build a full blown conversational bot, consider using something like Dialogflow. It makes it super easy to build bots that have human like conversations similar to the Google Assistant or Alexa, and you can add it to your Slack channel with just a few button clicks. And if you want to make the responses from the app more interactive with buttons and images and things like that, check out BlockKit. It's a UI framework specifically for Slack. I'm gonna go ahead and wrap things up there. If this video helped you, please like and subscribe, and consider becoming a pro member at FireShip IO. You'll get access to Cyber Jeff who can only be used by pro members, but more importantly, you'll get access to a whole bunch of advanced content. Thanks for watching, and I will talk to you soon.
Today,
today
I'm
i'm
going
going
to
to
show
show
you
you
how
how
I
i
built
built
CyberJeth,
cyberjeth
a
a
Slack
slack
app
app
that
that
helps
helps
me
me
automate
automate
things
things
that
that
I
i
would
would
otherwise
otherwise
have
have
to
to
do
do
manually
manually
for
for
members
members
of
of
our
our
Slack
slack
channel.
channel
If
if
you're
you're
not
not
already
already
in
in
our
our
Slack,
slack
you
you
should
should
join
join
with
with
the
the
link
link
in
in
the
the
description.
description
It's
it's
a
a
great
great
way
way
to
to
communicate
communicate
and
and
you
you
can
can
chat
chat
with
with
me
me
personally
personally
along
along
with
with
a
a
bunch
bunch
of
of
other
other
developers
developers
working
working
on
on
a
a
similar
similar
stack.
stack
If
if
you're
you're
already
already
a
a
pro
pro
member,
member
you
you
should
should
be
be
summoned
summoned
by
by
Cyber
cyber
Jeff.
jeff
He's
he's
a
a
faster
faster
and
and
more
more
reliable
reliable
version
version
of
of
me.
me
When
when
you
you
first
first
join
join
the
the
Slack
slack
channel,
channel
he'll
he'll
check
check
to
to
c
c
if
if
your
your
email
email
has
has
a
a
matching
matching
account
account
in
in
the
the
Firestore
firestore
database
database
with
with
pro
pro
status.
status
If
if
there's
there's
a
a
match,
match
he'll
he'll
invite
invite
you
you
to
to
our
our
pro
pro
channel
channel
and
and
tell
tell
you
you
how
how
to
to
redeem
redeem
a
a
sticker
sticker
her
her
and
and
t
t
shirt.
shirt
Now
now
this
this
is
is
a
a
very
very
personalized
personalized
Slack
slack
app
app
for
for
my
my
business
business
needs,
needs
but
but
in
in
today's
today's
video,
video
I
i
want
want
to
to
show
show
you
you
how
how
to
to
build
build
your
your
own
own
from
from
scratch.
scratch
If
if
you're
you're
new
new
here,
here
like
like
and
and
subscribe
subscribe
and
and
Check
check
out
out
the
the
full
full
write
write
up
up
on
on
Fireship
fireship
IO.
io
Now,
now
before
before
you
you
start
start
building
building
a
a
Slack
slack
app,
app
you
you
should
should
start
start
by
by
outlining
outlining
your
your
actual
actual
use
use
case
case
because
because
their
their
API
api
is
is
absolutely
absolutely
massive.
massive
It
it
allows
allows
you
you
to
to
automate
automate
things
things
within
within
the
the
workspace,
workspace
create
create
chatbots,
chatbots
interactive
interactive
UI
ui
elements,
elements
and
and
a
a
whole
whole
bunch
bunch
of
of
other
other
Thanks.
thanks
But
but
if
if
you're
you're
a
a
developer,
developer
there
there
are
are
two
two
main
main
reasons
reasons
you
you
would
would
build
build
a
a
Slack
slack
app
app
in
in
the
the
first
first
place.
place
Companies
companies
already
already
using
using
Slack
slack
may
may
want
want
to
to
enhance
enhance
some
some
sort
sort
of
of
internal
internal
process
process
or
or
communication
communication
flow.
flow
That's
that's
essentially
essentially
what
what
CyberJeph
cyberjeph
is.
is
It's
it's
mostly
mostly
an
an
automation
automation
tool,
tool
but
but
also
also
serves
serves
as
as
our
our
new
new
AI
ai
overlord
overlord
on
on
Slack.
slack
The
the
other
other
reason
reason
you
you
might
might
wanna
wanna
build
build
a
a
Slack
slack
App
app
is
is
to
to
build
build
a
a
service
service
to
to
be
be
consumed
consumed
by
by
other
other
Slack
slack
users.
users
Slack
slack
has
has
a
a
public
public
directory
directory
for
for
third
third
party
party
apps.
apps
All
all
you
you
have
have
to
to
do
do
is
is
build
build
something
something
useful,
useful
market
market
It
it
well
well
and
and
you'll
you'll
have
have
enterprise
enterprise
clients
clients
throwing
throwing
money
money
at
at
it
it
in
in
no
no
time.
time
Let's
let's
go
go
ahead
ahead
and
and
get
get
started.
started
You'll
you'll
need
need
2
2
things
things
for
for
this
this
project.
project
You'll
you'll
need
need
some
some
kind
kind
of
of
Slack
slack
workspace
workspace
that
that
you
you
have
have
admin
admin
access
access
to,
to
and
and
then
then
we'll
we'll
be
be
using
using
Firebase
firebase
as
as
our
our
serverless
serverless
back
back
end
end
with
with
Cloud
cloud
Functions.
functions
But
but
feel
feel
free
free
to
to
use
use
whatever
whatever
Node.
node
Js
js
back
back
end
end
you
you
prefer.
prefer
The
the
first
first
thing
thing
we'll
we'll
do
do
is
is
create
create
a
a
new
new
Slack
slack
app.
app
You
you
can
can
do
do
this
this
from
from
the
the
Slack
slack
API
api
homepage,
homepage
and
and
you'll
you'll
see
see
a
a
big
big
button
button
there
there
to
to
create
create
a
a
new
new
app.
app
Now
now
like
like
I
i
said
said
before,
before
the
the
API
api
is
is
massive,
massive
so
so
So
so
you
you
kind
kind
of
of
need
need
to
to
know
know
what
what
you're
you're
building
building
before
before
you
you
get
get
started.
started
Some
some
apps
apps
might
might
want
want
to
to
listen
listen
and
and
react
react
to
to
events
events
that
that
happen
happen
within
within
the
the
workspace,
workspace
while
while
others
others
might
might
want
want
to
to
fetch
fetch
or
or
post
post
information
information
into
into
it,
it
like
like
post
post
new
new
messages
messages
and
and
things
things
like
like
that,
that
or
or
in
in
our
our
case,
case
a
a
combination
combination
of
of
both.
both
We
we
want
want
our
our
server
server
to
to
listen
listen
to
to
the
the
Slack
slack
event
event
of
of
when
when
a
a
new
new
user
user
is
is
added
added
to
to
a
a
channel
channel
and
and
then
then
react
react
to
to
it
it
by
by
posting
posting
a
a
new
new
message
message
into
into
the
the
Slack
slack
workspace.
workspace
If
if
you're
you're
not
not
sure
sure
which
which
API
api
you
you
actually
actually
need,
need
I
i
would
would
highly
highly
recommend
recommend
following
following
this
this
flowchart
flowchart
provided
provided
by
by
Slack.
slack
Now
now
getting
getting
back
back
to
to
the
the
Slack
slack
admin
admin
panel,
panel
let's
let's
enable
enable
Events.
events
Events
events
are
are
essentially
essentially
outbound
outbound
webhooks
webhooks
that
that
allow
allow
you
you
to
to
listen
listen
to
to
events
events
that
that
happen
happen
within
within
the
the
Slack
slack
workspace
workspace
or
or
events
events
triggered
triggered
by
by
a
a
bot.
bot
In
in
our
our
case,
case
we
we
only
only
care
care
about
about
one
one
event,
event
which
which
is
is
the
the
member
member
join
join
channel
channel
event.
event
We
we
simply
simply
select
select
that
that
from
from
the
the
drop
drop
down,
down
and
and
then
then
you'll
you'll
notice
notice
it's
it's
asking
asking
us
us
for
for
a
a
request
request
URL.
url
This
this
URL
url
will
will
be
be
an
an
HTTP
http
Firebase
firebase
Cloud
cloud
Function.
function
But
but
before
before
we
we
can
can
use
use
it,
it
we
we
need
need
to
to
verify
verify
that
that
we
we
actually
actually
own
own
it
it
with
with
Slack.
slack
So
so
you
you
can
can
see
see
right
right
now,
now
it's
it's
currently
currently
unverified.
unverified
Let's
let's
go
go
ahead
ahead
and
and
open
open
up
up
Versus
versus
Code,
code
and
and
then
then
we'll
we'll
open
open
a
a
terminal
terminal
session
session
and
and
run
run
Firebase
firebase
init
init
functions.
functions
I'll
i'll
be
be
using
using
the
the
TypeScript
typescript
flavor
flavor
for
for
this
this
video
video
to
to
show
show
you
you
some
some
of
of
the
the
out
out
there,
there
but
but
feel
feel
free
free
to
to
use
use
vanilla
vanilla
JavaScript
javascript
if
if
you
you
prefer.
prefer
Now
now
let's
let's
go
go
ahead
ahead
and
and
get
get
our
our
endpoint
endpoint
verified.
verified
All
all
we
we
need
need
is
is
an
an
HTTP
http
cloud
cloud
function.
function
This
this
function
function
will
will
receive
receive
a
a
challenge
challenge
parameter
parameter
from
from
the
the
request
request
body
body
sent
sent
by
by
Slack.
slack
We
we
simply
simply
receive
receive
the
the
challenge
challenge
parameter
parameter
and
and
then
then
send
send
it
it
back
back
as
as
the
the
response.
response
Now
now
let's
let's
go
go
back
back
to
to
the
the
terminal
terminal
and
and
run
run
firebase
firebase
deploy.
deploy
After
after
a
a
minute
minute
or
or
so,
so
that
that
should
should
deploy
deploy
the
the
function
function
and
and
give
give
us
us
back
back
our
our
function's
function's
URL.
url
Go
go
ahead
ahead
and
and
copy
copy
and
and
paste
paste
that
that
value
value
as
as
the
the
Slack
slack
request
request
URL.
url
You
you
should
should
immediately
immediately
get
get
a
a
green
green
check
check
mark.
mark
So
so
now
now
that
that
the
the
endpoint
endpoint
is
is
verified,
verified
it's
it's
time
time
to
to
build
build
something
something
useful.
useful
We
we
need
need
to
to
make
make
sure
sure
that
that
our
our
app
app
is
is
fully
fully
secure,
secure
and
and
there's
there's
a
a
couple
couple
of
of
steps
steps
involved
involved
in
in
that
that
depending
depending
on
on
the
the
types
types
of
of
APIs
apis
that
that
you
you
plan
plan
on
on
using.
using
Now
now
back
back
to
to
the
the
terminal
terminal
for
for
our
our
Cloud
cloud
Function,
function
we'll
we'll
install
install
the
the
Slack
slack
web
web
API
api
along
along
with
with
Google
google
Cloud
cloud
PubSub,
pubsub
and
and
I'll
i'll
explain
explain
why
why
that's
that's
needed
needed
in
in
a
a
few
few
minutes.
minutes
Slack
slack
provides
provides
a
a
big
big
monorepo
monorepo
with
with
a
a
bunch
bunch
of
of
different
different
packages.
packages
The
the
web
web
API
api
is
is
used
used
if
if
you
you
want
want
to
to
post
post
messages
messages
into
into
Slack
slack
or
or
modify
modify
things
things
in
in
the
the
workspace.
workspace
In
in
order
order
to
to
use
use
it
it
in
in
a
a
workspace,
workspace
we
we
need
need
to
to
authenticate
authenticate
it
it
with
with
an
an
OAuth
oauth
token.
token
The
the
token
token
is
is
unique
unique
to
to
the
the
workspace
workspace
and
and
not
not
the
the
app
app
itself.
itself
So
so
each
each
workspace
workspace
that
that
has
has
this
this
app
app
installed
installed
will
will
have
have
a
a
different
different
OAuth
oauth
token.
token
Since
since
this
this
is
is
a
a
private
private
app
app
installed
installed
in
in
a
a
single
single
workspace,
workspace
We'll
we'll
simply
simply
install
install
it,
it
which
which
will
will
take
take
us
us
directly
directly
to
to
the
the
OAuth
oauth
tokens
tokens
for
for
the
the
team.
team
You'll
you'll
want
want
to
to
copy
copy
this
this
value
value
and
and
then
then
head
head
over
over
to
to
the
the
command
command
line
line
once
once
again,
again
and
and
we'll
we'll
set
set
it
it
up
up
as
as
an
an
environment
environment
variable
variable
in
in
the
the
Cloud
cloud
Functions
functions
environment
environment
by
by
running
running
Firebase
firebase
functions
functions
config
config
set
set
Slack
slack
dot
dot
token
token
equals
equals
ROauthoken.
roauthoken
And
and
And
and
that's
that's
the
the
only
only
credential
credential
you
you
need
need
for
for
the
the
Slack
slack
web
web
API.
api
But
but
our
our
app
app
is
is
also
also
listening
listening
to
to
incoming
incoming
events
events
from
from
Slack,
slack
so
so
we
we
need
need
a
a
way
way
to
to
verify
verify
that
that
those
those
requests
requests
are
are
actually
actually
legitimate.
legitimate
Because
because
it's
it's
possible
possible
for
for
a
a
hacker
hacker
to
to
send
send
fake
fake
requests
requests
to
to
our
our
Cloud
cloud
Function
function
URL.
url
We
we
can
can
prevent
prevent
that
that
by
by
going
going
to
to
the
the
basic
basic
information
information
page
page
and
and
grabbing
grabbing
our
our
sign
sign
in
in
secret.
secret
We'll
we'll
also
also
use
use
the
the
Firebase
firebase
functions
functions
config
config
set
set
command
command
to
to
add
add
this
this
as
as
an
an
environment
environment
variable.
variable
Now
now
validating
validating
the
the
signing
signing
secret
secret
from
from
scratch
scratch
is
is
kind
kind
of
of
a
a
pain,
pain
So
so
I
i
actually
actually
put
put
together
together
a
a
dedicated
dedicated
snippet
snippet
on
on
Fireship
fireship
IO
io
just
just
for
for
this
this
purpose.
purpose
Slack
slack
has
has
an
an
Events
events
API
api
package
package
that
that
can
can
do
do
some
some
of
of
this
this
for
for
you
you
automatically,
automatically
but
but
it
it
doesn't
doesn't
really
really
work
work
well
well
in
in
a
a
serverless
serverless
environment.
environment
All
all
we
we
have
have
to
to
do
do
is
is
perform
perform
timing
timing
safe
safe
string
string
comparison
comparison
using
using
double
double
hash
hash
message
message
authentication
authentication
code,
code
which,
which
of
of
course,
course
is
is
something
something
that
that
every
every
programmer
programmer
should
should
know
know
how
how
to
to
do
do
with
with
their
their
eyes
eyes
Closed.
closed
You'll
you'll
see
see
a
a
more
more
detailed
detailed
description
description
in
in
the
the
snippet,
snippet
but,
but
basically,
basically
we're
we're
taking
taking
our
our
signing
signing
secret
secret
and
and
then
then
comparing
comparing
it
it
to
to
a
a
signature
signature
that
that
Slack
slack
provides
provides
in
in
the
the
header.
header
If
if
the
the
final
final
values
values
match,
match
then
then
we
we
know
know
we
we
have
have
a
a
valid
valid
request.
request
Otherwise,
otherwise
we
we
reject
reject
it.
it
Now
now
let's
let's
get
get
on
on
with
with
the
the
actual
actual
code
code
implementation
implementation
of
of
the
the
Slack
slack
app.
app
We'll
we'll
go
go
ahead
ahead
and
and
import
import
the
the
web
web
client
client
from
from
Slack
slack
web
web
API,
api
then
then
we'll
we'll
initialize
initialize
the
the
client
client
using
using
the
the
Slack
slack
token
token
that
that
we
we
saved
saved
to
to
the
the
functions
functions
environment.
environment
Then
then
we'll
we'll
also
also
instantiate
instantiate
Google
google
Pub
pub
Sub
sub
here.
here
So
so
let
let
me
me
take
take
a
a
second
second
to
to
explain
explain
why
why
we
we
need
need
Pub
pub
Sub.
sub
If
if
you're
you're
not
not
familiar
familiar
with
with
it,
it
it's
it's
a
a
service
service
that
that
allows
allows
you
you
to
to
pass
pass
messages
messages
between
between
different
different
Google
google
Cloud
cloud
Services.
services
So
so
it's
it's
very
very
similar
similar
to
to
HTTP,
http
but
but
it's
it's
fully
fully
secure
secure
within
within
the
the
Google
google
Cloud
cloud
infrastructure.
infrastructure
Now
now
the
the
Slack
slack
API
api
requires
requires
that
that
their
their
initial
initial
request
request
is
is
responded
responded
to
to
within
within
3000
3000
milliseconds
milliseconds
or
or
3
3
seconds.
seconds
If
if
you
you
don't
don't
respond
respond
within
within
that
that
time,
time
you'll
you'll
get
get
a
a
timeout
timeout
error,
error
and
and
then
then
Slack
slack
will
will
try
try
to
to
retry
retry
that
that
same
same
endpoint.
endpoint
If
if
your
your
app
app
has
has
a
a
long
long
running
running
back
back
end
end
process,
process
like
like
it
it
makes
makes
API
api
request
request
to
to
some
some
other
other
API,
api
then
then
you'll
you'll
need
need
to
to
queue
queue
up
up
some
some
type
type
of
of
background
background
job
job
to
to
handle
handle
that
that
work
work
outside
outside
of
of
the
the
3,000
3,000
millisecond
millisecond
limitation.
limitation
And
and
that's
that's
exactly
exactly
what
what
our
our
pubsub
pubsub
function
function
will
will
do.
do
So
so
that
that
means
means
the
the
only
only
responsibility
responsibility
of
of
the
the
HTTP
http
function
function
is
is
to
to
verify
verify
the
the
signature
signature
and
and
then
then
queue
queue
up
up
the
the
background
background
job.
job
We
we
can
can
do
do
that
that
by
by
stringifying
stringifying
the
the
initial
initial
request
request
body,
body
converting
converting
it
it
to
to
a
a
buffer,
buffer
then
then
using
using
the
the
PubSub
pubsub
client
client
to
to
publish
publish
to
to
a
a
specific
specific
topic
topic
using
using
that
that
buffer.
buffer
So,
so
So
so
essentially,
essentially
what
what
this
this
does
does
is
is
it
it
takes
takes
the
the
request
request
body
body
and
and
then
then
passes
passes
it
it
off
off
to
to
a
a
PubSub
pubsub
function
function
that
that
we
we
can
can
handle
handle
in
in
the
the
next
next
step.
step
And
and
lastly,
lastly
Make
make
sure
sure
to
to
send
send
a
a
response
response
to
to
Slack
slack
with
with
a
a
200
200
status
status
code.
code
So
so
what
what
we've
we've
done
done
here
here
is
is
passed
passed
off
off
all
all
the
the
heavy
heavy
lifting
lifting
to
to
a
a
pubsub
pubsub
function,
function
which
which
has
has
no
no
time
time
limitation,
limitation
so
so
feel
feel
free
free
to
to
take
take
as
as
long
long
as
as
you
you
want
want
to
to
handle
handle
it.
it
We
we
can
can
set
set
up
up
the
the
Cloud
cloud
Function,
function
making
making
sure
sure
to
to
point
point
to
to
the
the
same
same
topic
topic
that
that
we
we
published
published
to.
to
The
the
on
on
publish
publish
callback
callback
will
will
give
give
us
us
access
access
to
to
the
the
message,
message
which
which
has
has
the
the
same
same
data
data
contained
contained
in
in
the
the
original
original
request
request
body.
body
The
the
data
data
that's
that's
available
available
here
here
depends
depends
entirely
entirely
on
on
the
the
type
type
of
of
event
event
that
that
Stripe
stripe
has
has
sent
sent
to
to
your
your
back
back
end.
end
You'll
you'll
need
need
to
to
mostly
mostly
reference
reference
the
the
Stripe
stripe
API
api
docs
docs
Because
because
even
even
though
though
we're
we're
in
in
TypeScript,
typescript
it
it
doesn't
doesn't
provide
provide
typings
typings
for
for
the
the
actual
actual
response
response
data
data
types.
types
When
when
a
a
new
new
user
user
is
is
added
added
to
to
a
a
channel,
channel
it
it
will
will
give
give
us
us
an
an
event
event
which
which
we
we
can
can
access
access
on
on
the
the
message
message
JSON.
json
And
and
then
then
we
we
can
can
grab
grab
the
the
user
user
and
and
the
the
channel
channel
from
from
that
that
event.
event
So
so
that
that
gives
gives
us
us
a
a
user
user
ID
id
and
and
a
a
channel
channel
ID
id
from
from
Slack.
slack
In
in
this
this
implementation,
implementation
we
we
only
only
want
want
to
to
run
run
the
the
code
code
if
if
the
the
user
user
is
is
being
being
added
added
to
to
the
the
general
general
channel
channel
for
for
the
the
first
first
time.
time
If
if
that's
that's
not
not
the
the
case,
case
we
we
can
can
throw
throw
an
an
error
error
or
or
just
just
return
return
null
null
from
from
the
the
function.
function
Now
now
the
the
first
first
thing
thing
we
we
wanna
wanna
do
do
is
is
take
take
that
that
user
user
ID
id
and
and
grab
grab
the
the
full
full
user
user
profile,
profile
which
which
will
will
contain
contain
the
the
email
email
address
address
and
and
display
display
name
name
of
of
that
that
user
user
on
on
Slack.
slack
We
we
can
can
do
do
that
that
by
by
making
making
a
a
request
request
with
with
bot
bot
users
users
profile
profile
get.
get
That
that
will
will
give
give
us
us
a
a
web
web
API
api
response,
response
And
and
the
the
actual
actual
data
data
we
we
want
want
is
is
on
on
the
the
result
result
profile.
profile
And
and
that's
that's
an
an
unknown
unknown
type,
type
so
so
we'll
we'll
go
go
ahead
ahead
and
and
cast
cast
it
it
to
to
any
any
so
so
we
we
can
can
destructure
destructure
the
the
properties
properties
on
on
it.
it
Now
now
before
before
we
we
go
go
any
any
further,
further
we'll
we'll
need
need
to
to
make
make
sure
sure
that
that
our
our
bot
bot
has
has
the
the
proper
proper
permission
permission
to
to
read
read
a
a
user's
user's
profile.
profile
You
you
can
can
set
set
up
up
permissions
permissions
or
or
scopes
scopes
for
for
your
your
bot
bot
on
on
the
the
admin
admin
area
area
for
for
the
the
Slack
slack
app.
app
You'll
you'll
wanna
wanna
use
use
the
the
principle
principle
of
of
least
least
privilege
privilege
here
here
and
and
only
only
grant
grant
access
access
to
to
the
the
actual
actual
operations
operations
that
that
your
your
bot
bot
needs
needs
to
to
do
do
its
its
job.
job
Now
now
that
that
we
we
have
have
the
the
user's
user's
email
email
address,
address
we
we
could
could
make
make
a
a
query
query
to
to
Firestore
firestore
to
to
grab
grab
that
that
actual
actual
user
user
record
record
from
from
the
the
database,
database
but
but
I
i
think
think
we
we
should
should
just
just
stick
stick
to
to
the
the
Slack
slack
API
api
for
for
this
this
demo.
demo
We'll
we'll
go
go
ahead
ahead
and
and
invite
invite
that
that
user
user
to
to
a
a
new
new
channel,
channel
then
then
have
have
the
the
bot
bot
send
send
them
them
a
a
direct
direct
message
message
with
with
some
some
text
text
that
that
welcomes
welcomes
them
them
to
to
the
the
new
new
channel.
channel
And
and
that's
that's
basically
basically
all
all
there
there
is
is
to
to
it.
it
We
we
now
now
have
have
a
a
fast
fast
and
and
secure
secure
serverless
serverless
backend
backend
for
for
building
building
our
our
Slack
slack
app,
app
but
but
there's
there's
a
a
lot
lot
more
more
we
we
can
can
do
do
beyond
beyond
this
this
simple
simple
use
use
case.
case
If
if
you
you
want
want
to
to
build
build
a
a
full
full
blown
blown
conversational
conversational
bot,
bot
consider
consider
using
using
something
something
like
like
Dialogflow.
dialogflow
It
it
makes
makes
it
it
super
super
easy
easy
to
to
build
build
bots
bots
that
that
have
have
human
human
like
like
conversations
conversations
similar
similar
to
to
the
the
Google
google
Assistant
assistant
or
or
Alexa,
alexa
and
and
you
you
can
can
add
add
it
it
to
to
your
your
Slack
slack
channel
channel
with
with
just
just
a
a
few
few
button
button
clicks.
clicks
And
and
if
if
you
you
want
want
to
to
make
make
the
the
responses
responses
from
from
the
the
app
app
more
more
interactive
interactive
with
with
buttons
buttons
and
and
images
images
and
and
things
things
like
like
that,
that
check
check
out
out
BlockKit.
blockkit
It's
it's
a
a
UI
ui
framework
framework
specifically
specifically
for
for
Slack.
slack
I'm
i'm
gonna
gonna
go
go
ahead
ahead
and
and
wrap
wrap
things
things
up
up
there.
there
If
if
this
this
video
video
helped
helped
you,
you
please
please
like
like
and
and
subscribe,
subscribe
and
and
consider
consider
becoming
becoming
a
a
pro
pro
member
member
at
at
FireShip
fireship
IO.
io
You'll
you'll
get
get
access
access
to
to
Cyber
cyber
Jeff
jeff
who
who
can
can
only
only
be
be
used
used
by
by
pro
pro
members,
members
but
but
more
more
importantly,
importantly
you'll
you'll
get
get
access
access
to
to
a
a
whole
whole
bunch
bunch
of
of
advanced
advanced
content.
content
Thanks
thanks
for
for
watching,
watching
and
and
I
i
will
will
talk
talk
to
to
you
you
soon.
soon
success
The speakers discuss building a CyberJeth Slack app, which allows for automation, communication, and a whole bunch of other features. They also discuss the need for a serverless back end and a public directory for third-party apps. They explain how to enable Events in Slack workspace, verifying endpoints, and how to use the public cloud function to publish a message to a specific topic using a buffer. They also discuss validating requests through command lines, importing the web client, and the use of a unique public cloud token to authenticate the app. They also mention a framework for building conversational bots using APIs and invite a new participant to join the conversation.
How to Build a Slack App
Today, I'm going to show you how I built CyberJeth, a Slack app that helps me automate things that I would otherwise have to do manually for members of our Slack channel. If you're not already in our Slack, you should join with the link in the description. It's a great way to communicate and you can chat with me personally along with a bunch of other developers working on a similar stack. If you're already a pro member, you should be summoned by Cyber Jeff. He's a faster and more reliable version of me. When you first join the Slack channel, he'll check to c if your email has a matching account in the Firestore database with pro status. If there's a match, he'll invite you to our pro channel and tell you how to redeem a sticker her and t shirt. Now this is a very personalized Slack app for my business needs, but in today's video, I want to show you how to build your own from scratch. If you're new here, like and subscribe and Check out the full write up on Fireship IO. Now, before you start building a Slack app, you should start by outlining your actual use case because their API is absolutely massive. It allows you to automate things within the workspace, create chatbots, interactive UI elements, and a whole bunch of other Thanks. But if you're a developer, there are two main reasons you would build a Slack app in the first place. Companies already using Slack may want to enhance some sort of internal process or communication flow. That's essentially what CyberJeph is. It's mostly an automation tool, but also serves as our new AI overlord on Slack. The other reason you might wanna build a Slack App is to build a service to be consumed by other Slack users. Slack has a public directory for third party apps. All you have to do is build something useful, market It well and you'll have enterprise clients throwing money at it in no time. Let's go ahead and get started. You'll need 2 things for this project. You'll need some kind of Slack workspace that you have admin access to, and then we'll be using Firebase as our serverless back end with Cloud Functions. But feel free to use whatever Node. Js back end you prefer. The first thing we'll do is create a new Slack app. You can do this from the Slack API homepage, and you'll see a big button there to create a new app. Now like I said before, the API is massive, so So you kind of need to know what you're building before you get started. Some apps might want to listen and react to events that happen within the workspace, while others might want to fetch or post information into it, like post new messages and things like that, or in our case, a combination of both. We want our server to listen to the Slack event of when a new user is added to a channel and then react to it by posting a new message into the Slack workspace. If you're not sure which API you actually need, I would highly recommend following this flowchart provided by Slack. Now getting back to the Slack admin panel, let's enable Events. Events are essentially outbound webhooks that allow you to listen to events that happen within the Slack workspace or events triggered by a bot. In our case, we only care about one event, which is the member join channel event. We simply select that from the drop down, and then you'll notice it's asking us for a request URL. This URL will be an HTTP Firebase Cloud Function. But before we can use it, we need to verify that we actually own it with Slack. So you can see right now, it's currently unverified. Let's go ahead and open up Versus Code, and then we'll open a terminal session and run Firebase init functions. I'll be using the TypeScript flavor for this video to show you some of the out there, but feel free to use vanilla JavaScript if you prefer. Now let's go ahead and get our endpoint verified. All we need is an HTTP cloud function. This function will receive a challenge parameter from the request body sent by Slack. We simply receive the challenge parameter and then send it back as the response. Now let's go back to the terminal and run firebase deploy. After a minute or so, that should deploy the function and give us back our function's URL. Go ahead and copy and paste that value as the Slack request URL. You should immediately get a green check mark. So now that the endpoint is verified, it's time to build something useful. We need to make sure that our app is fully secure, and there's a couple of steps involved in that depending on the types of APIs that you plan on using. Now back to the terminal for our Cloud Function, we'll install the Slack web API along with Google Cloud PubSub, and I'll explain why that's needed in a few minutes. Slack provides a big monorepo with a bunch of different packages. The web API is used if you want to post messages into Slack or modify things in the workspace. In order to use it in a workspace, we need to authenticate it with an OAuth token. The token is unique to the workspace and not the app itself. So each workspace that has this app installed will have a different OAuth token. Since this is a private app installed in a single workspace, We'll simply install it, which will take us directly to the OAuth tokens for the team. You'll want to copy this value and then head over to the command line once again, and we'll set it up as an environment variable in the Cloud Functions environment by running Firebase functions config set Slack dot token equals ROauthoken. And And that's the only credential you need for the Slack web API. But our app is also listening to incoming events from Slack, so we need a way to verify that those requests are actually legitimate. Because it's possible for a hacker to send fake requests to our Cloud Function URL. We can prevent that by going to the basic information page and grabbing our sign in secret. We'll also use the Firebase functions config set command to add this as an environment variable. Now validating the signing secret from scratch is kind of a pain, So I actually put together a dedicated snippet on Fireship IO just for this purpose. Slack has an Events API package that can do some of this for you automatically, but it doesn't really work well in a serverless environment. All we have to do is perform timing safe string comparison using double hash message authentication code, which, of course, is something that every programmer should know how to do with their eyes Closed. You'll see a more detailed description in the snippet, but, basically, we're taking our signing secret and then comparing it to a signature that Slack provides in the header. If the final values match, then we know we have a valid request. Otherwise, we reject it. Now let's get on with the actual code implementation of the Slack app. We'll go ahead and import the web client from Slack web API, then we'll initialize the client using the Slack token that we saved to the functions environment. Then we'll also instantiate Google Pub Sub here. So let me take a second to explain why we need Pub Sub. If you're not familiar with it, it's a service that allows you to pass messages between different Google Cloud Services. So it's very similar to HTTP, but it's fully secure within the Google Cloud infrastructure. Now the Slack API requires that their initial request is responded to within 3000 milliseconds or 3 seconds. If you don't respond within that time, you'll get a timeout error, and then Slack will try to retry that same endpoint. If your app has a long running back end process, like it makes API request to some other API, then you'll need to queue up some type of background job to handle that work outside of the 3,000 millisecond limitation. And that's exactly what our pubsub function will do. So that means the only responsibility of the HTTP function is to verify the signature and then queue up the background job. We can do that by stringifying the initial request body, converting it to a buffer, then using the PubSub client to publish to a specific topic using that buffer. So, So essentially, what this does is it takes the request body and then passes it off to a PubSub function that we can handle in the next step. And lastly, Make sure to send a response to Slack with a 200 status code. So what we've done here is passed off all the heavy lifting to a pubsub function, which has no time limitation, so feel free to take as long as you want to handle it. We can set up the Cloud Function, making sure to point to the same topic that we published to. The on publish callback will give us access to the message, which has the same data contained in the original request body. The data that's available here depends entirely on the type of event that Stripe has sent to your back end. You'll need to mostly reference the Stripe API docs Because even though we're in TypeScript, it doesn't provide typings for the actual response data types. When a new user is added to a channel, it will give us an event which we can access on the message JSON. And then we can grab the user and the channel from that event. So that gives us a user ID and a channel ID from Slack. In this implementation, we only want to run the code if the user is being added to the general channel for the first time. If that's not the case, we can throw an error or just return null from the function. Now the first thing we wanna do is take that user ID and grab the full user profile, which will contain the email address and display name of that user on Slack. We can do that by making a request with bot users profile get. That will give us a web API response, And the actual data we want is on the result profile. And that's an unknown type, so we'll go ahead and cast it to any so we can destructure the properties on it. Now before we go any further, we'll need to make sure that our bot has the proper permission to read a user's profile. You can set up permissions or scopes for your bot on the admin area for the Slack app. You'll wanna use the principle of least privilege here and only grant access to the actual operations that your bot needs to do its job. Now that we have the user's email address, we could make a query to Firestore to grab that actual user record from the database, but I think we should just stick to the Slack API for this demo. We'll go ahead and invite that user to a new channel, then have the bot send them a direct message with some text that welcomes them to the new channel. And that's basically all there is to it. We now have a fast and secure serverless backend for building our Slack app, but there's a lot more we can do beyond this simple use case. If you want to build a full blown conversational bot, consider using something like Dialogflow. It makes it super easy to build bots that have human like conversations similar to the Google Assistant or Alexa, and you can add it to your Slack channel with just a few button clicks. And if you want to make the responses from the app more interactive with buttons and images and things like that, check out BlockKit. It's a UI framework specifically for Slack. I'm gonna go ahead and wrap things up there. If this video helped you, please like and subscribe, and consider becoming a pro member at FireShip IO. You'll get access to Cyber Jeff who can only be used by pro members, but more importantly, you'll get access to a whole bunch of advanced content. Thanks for watching, and I will talk to you soon.
The speakers discuss building a CyberJeth Slack app, which allows for automation, communication, and a whole bunch of other features. They also discuss the need for a serverless back end and a public directory for third-party apps. They explain how to enable Events in Slack workspace, verifying endpoints, and how to use the public cloud function to publish a message to a specific topic using a buffer. They also discuss validating requests through command lines, importing the web client, and the use of a unique public cloud token to authenticate the app. They also mention a framework for building conversational bots using APIs and invite a new participant to join the conversation.