Creating a Slack Bot

Brice McIver JavaScript, Node.js, Technology Snapshot Leave a Comment

If you have ever worked on a team project, then you’ve needed some way to communicate with your team. For a very small team with all of its members based in one place, face-to-face communication might be your go-to method of handling project conversations.

However, once your project size progresses past that point, there’s a good chance that you’ll at least evaluate using a collaborative software package to help manage your project. Slack is a popular option for this.

In this blog, I’ll show the basic steps you can take to integrate Slack with your existing tools and workflows. In particular, we will set up Slack for incoming webhooks and event subscriptions, showing how to program a Slack bot to say personalized “Welcome to the channel” and a “Goodbye” messages.

Note: this blog loosely follows the talks I gave at the KCDC and Nebraska.Code() conferences.

Let’s Get Started

For this example, I’ll create an Express app that will allow us to send messages from an external system into Slack and allow us to react to events that occur in our Slack channel.

Let’s start with generating a basic Node.js using the npm init command and moving forward from there.

Package.json file

After our initialization, we have a package.json file with our application name (slackbot, in this case) and a short description. Now we’re going to add the dependencies we need to make this an Express app.

Package.json with dependencies

We add express and body-parser so we can act as a web server (express) and parse JSON in the request and response bodies (body-parser). We do an npm install to make sure all of our dependencies get pulled in and then we’ll create our basic web server.

Let’s go through our JavaScript file (app.js) below:

var express = require('express');
var bodyParser = require('bodyParser');

var app = express();
var port = process.env.PORT || 3000;

app.use(bodyParser.json());

app.get('/', function (req, res) { res.status(200).send('Hello world!')});

app.use(function (err, req, res, next) {
    console.error(err.stack);
    res.status(400).send(err.message);
});

app.listen(port, function() {
    console.log('Slack bot listening on port ' + port);
});

The first two lines here load our dependencies. The next line initializes Express. And the following line sets our port number (3000 for local testing and the PORT environment variable when hosted).

After that, we tell Express to use body parser for converting the request and responses from strings to JSON objects. The app.get line just returns an HTTP 200 status with the text “Hello world!” The app.use section will log errors to the console as well as sending an HTTP 400 with an error message.

Finally, the app.listen section will show a short message that lets us know our app started correctly and which port it is running on. If we’ve done everything correctly, we should be able to run node app and see our startup message.

Initial app.js file

And in a browser:

Browser Hello World

Now that we have our Express app set up, let’s move to the Slack website to create a way to send messages into our Slack channel from an external source.

We start at the Slack API site and click on a nice big button labeled “Start Building.” Once there, you should have another big button labeled “Create an App.” Click it and a modal window (“Create a Slack App”) should open where you can give your app a name and assign it to your Slack team. Finish that and select “Create App.”

Incoming Webhooks

Now we’ll be at your app’s information screen. Slack gives a pretty good description of the features you can add to your app, along with a full documentation link. For now, we’re going to concentrate on the option “Incoming Webhooks”. This will allow us to create an endpoint on the Slack servers that we can POST to and have messages show up in our Slack channel.

After clicking on the “Incoming Webhooks” section, we need to activate incoming webhooks. Go ahead and click on the “Off” slider so it becomes “On.” Some more text will appear with a button “Add New Webhook to Team” at the bottom. Clicking it takes us to an OAuth screen where we can select which channel we want to post into.

Once you authorize the app to post to a channel, you’ll be taken back to the incoming webhooks pages and you’ll see an entry in the “Webhook URLs for Your Team” section. Copy that URL and we can give it a test with any tool that can do a POST. Slack gives you the full curl command to test it and here’s what it looks like in Postman.

Postman POST

And what it looks like in our Slack channel:

Slack channel Hello conference

For many people, this may be all the integration that you need. If you have internal tools for monitoring that send emails or pages when an event happens, you could have them send that text as a POST to your Slack endpoint and have your alert sent to anyone on a particular channel. If code is checked in or deployed, send a message to a Slack channel.

A nice advantage to a system like this versus an email distribution list is that people can choose which channels they join. If you aren’t interested in build notification, leave that channel. If you aren’t on call for emergency alerts, mute notifications for that channel until you are on call.

Unfortunately, incoming webhooks only give us a one-way solution. We can send information into Slack, but we can’t get any information back from Slack. Let’s take care of that now.

Listen To Events

Heading back to your apps on the Slack API, let’s add the ability to listen to events.

Under the Features group on the sidebar, you’ll see a link named “Event Subscriptions” (which can also be found on our app’s basic information screen in the “Add features and functionality” section). Clicking on that again takes us to a screen where we need to enable this feature. Click the slider to “On” and take a look at the other information we need to add.

The first piece of requested information is a request URL. Slack will send a POST request to this URL when the events we’ve registered for occur. So we’ll need to create a POST endpoint in our Express app for this purpose.

Further down, you see where we can add events to listen for. For our example, we’re going to receive a message when a user enters or leaves a particular Slack channel (the member_joined_channel and member_left_channel events).

If you add those events and save your changes, you’ll get a message saying that you need to reinstall your app because your scope has changed. Click on the “Install App” link in the sidebar (under Settings) and then click on the “Reinstall App” button. You’ll be taken back to the OAuth screen again and asked to authorize for the ability to access channel information (for our entered and left messages).

Alright, time to head back to our app and make the necessary changes. We’ll use a new file to hold our Slack code (named hellobot.js in our example), a few additional changes to our app.js file, and a small text file as part of our deploying the app to Heroku (since Slack needs a publicly accessible endpoint to hit).

Hellobot.js part 1

Some key things to note here:

  1. We need the https library so we can call our incoming webhook URL.
  2. The first if statement allows our app to successfully register as an event listener with Slack.
  3. The second if statement looks for event callbacks and sets up a POST to our incoming webhook.
  4. Depending on the type of event we get, we’ll post a “Welcome to the channel” or a “Goodbye” message.

App.js part 2

  1. We add a require to our app.js to include the new hellobot.js code
  2. We add a POST endpoint with the name ‘hello’

Procfile

This allows Heroku to know how to start our app once we deploy it there.

I won’t go over how to deploy to Heroku in this post, but let’s continue assuming that we deployed our app to Heroku and we’ve entered our endpoint location into the Slack Event Subscriptions page. When you enter and leave the channel at this point, you’ll get a message looking something like this.

Enter and Leave part 1

Not exactly what we’re hoping for.

Slack Developer Kit

We can translate that user ID using other Slack API calls, but those will also require us to implement OAuth workflows. At that point, this leaves the realm of “simple Slack bot.” Unless Slack has done all that work for us (which it has).

Here is an example of the same hellobot.js file using the Slack Developer Kit for Node.

Hellobot.js with Node Developer Kit

Here we:

  • add the library (@slack/client, also added to our package.json dependencies),
  • initialize it using the OAuth token (which can be retrieved from the OAuth section of your app’s Slack webpage),
  • use the users.info call to get the username from the request posted by Slack,
  • and use the chat.postMessage call to place our message into the channel (instead of using the incoming webhook we were using before).

Let’s check if that looks any better:

Enter leave channel part 2

Looking much better!

Final Thoughts

Thanks for following along. So, we started with a blank Node.js app, created a basic Express app, set up Slack for incoming webhooks and event subscriptions, and showed how to program a Slack bot using the raw API as well as the Slack Developer Kit.

If JavaScript isn’t your language of choice, check out the Slack libraries page (https://api.slack.com/community). For almost any programming language you can think of, you’ll find someone who has written a wrapper for the Slack API in that language. What is your first Slack bot going to do? Let us know in the comments!


About the Author
Brice McIver

Brice McIver

Brice McIver is a software consultant with Keyhole Software in Leawood, KS. He began his career over 14 years ago in the health care IT industry and has continued to help companies in the insurance, agriculture, transportation, and investment industries modernize their enterprise software applications. Outside of work, he enjoys the time he spends with his daughter and twin boys.


Share this Post

Leave a Reply