How to write a Slackbot in 40 lines of code
In about 15 minutes, I’ll show you how to build a Slackbot using Node.js, Express, and the Genius API. No prior coding skills required.
I’m part of the growing VNYL Slack community, where we chat about vinyl records, our favorite #vibes, and just about anything music-related.
I thought it would be cool to be able to share Genius links in the chatroom, so I decided to write a Slackbot that takes in an artist and song title and returns a link to a Genius.com:
What is a Slackbot?
Before we get started, let’s understand what we’re building.
Slack has an API called “Slash commands” that lets a user type a slash (/) followed by a keyword and them some text. A good example of this is the /giphy slash command.
The Slackbot we’re building is just a web server that relays messages between Slack and Genius.com’s API using HTTP.
When we type “/genius Justin Bieber Sorry”, it sends that text to our node server which converts the message into a search query to Genius.com’s API. Then we send the data back to Slack.
Building the Node.js server
Before we start, make sure you have Node and Git installed. If you have Homebrew, just open up a Terminal window and type:
brew install node git
Now let’s start coding. Find a folder on your computer to host the code. I personally use ~/Code (on Mac, a folder called Code in my home directory). If this is your first time coding, type this in Terminal:
mkdir ~/Code cd ~/Code
Next let’s clone the repo from Github. You may need to give Github your ssh key:
git clone email@example.com:mager/slack-genius.git my-slackbot
This will have created a folder called my-slackbot with the working Slackbot code inside. Jump into the folder and install all the dependencies:
cd my-slackbot npm i
You can replace
my-slackbot with anything you want.
After npm is finished installing dependencies, run:
You should see something like this:
App is running locally. Visit http://localhost:9001 to test it out. You should see “It works!”.
We just told Node to run our local index.js file, and it’s listening for requests at http://localhost:9001.
Let’s understand the 40 lines of code in index.js before we move any further.
Express framework & HTTP
As mentioned before, our Slackbot is just a server that sends and receives messages using HTTP. We’ll use Express to handle those requests since it’s lightweight and well-documented.
Let’s step through the code in four sections. Here’s the beginning of index.js:
Here, we’re initializing some variables from libraries that we’ll use later. url helps format a URL, request will help us send a proper request back to Slack when we’re ready, and bodyParser helps us parse JSON and x-www-form-urlencoded data.
Line 1 tells Node and Express to use whatever port is set in the environment variable, or 9001 if it isn’t set. When we host the live version on a production box in the future, the port will be a dynamic number that we can’t hardcode.
Lines 3–5 aren’t technically needed, but it lets us know our app is running properly when we visit the main root of the app (in this case /).
Handling the POST data
As you may know, HTTP mainly consists of GET and POST data. When you visit http://google.com, your browser is sending a GET request to Google’s servers asking to serve you the page. When you type something in the search box and press enter, that data is sent to Google’s servers using a POST request.
In our case, the Slack slash command will make a POST to our Slackbot, then we’ll make a GET request to Genius, and finally, we’ll make a POST back to Slack.
In this next section, we’ll use app.post. This code is triggered when a POST request is sent to the URL ‘/post’. Let’s dissect it:
First we need to take a search term from the Slack slash command (req.body.text), then format a URL to request data from Genius. We will do that using Node’s built-in url library in lines 2–8 above).
We’re going to use Genius’ search endpoint, documented here. It takes in a q parameter (the search query) and an access_token (I’l explain how to get that shortly). The variable parsed_url will look something like this:
In lines 10–22 above, we’re using the Node request library to pass in the parsed URL, pull out the first link from the JSON that was returned (line 13), then construct a proper response back to Slack (lines 15–20).
The last section of code tells Node which port to listen on:
That’s it all the code we’ll need to write.
One more thing before we get it working in Slack: the access token from Genius. Create a new API client there.
Once you save it, you should have a “Generate Access Token” at the bottom:
Copy down that access token, we’ll use it in the next section.
Deploying to Heroku
Since Slack doesn’t send commands to localhost, we need to deploy this code somewhere that Slack can access. The easiest way is to do it with Heroku.
Sign up for an account, install the toolbelt, login, create the app, and push it live (run these commands separately):
brew install heroku-toolbelt heroku login heroku create git push heroku master</pre>
It should take 10–30 seconds to push to Heroku.
To make sure it’s working on Heroku type:
And you should see the same “It works!” page from before.
Take note of that URL because we’ll use it in the next section.
Now we can add our Genius access token as a Heroku environmental variable:
heroku config:add GENIUS_ACCESS=[your token]
You can check to see if it was successfully added by logging into your Heroku dashboard.
Setting up Slack
Goto your team’s Custom Integrations page on Slack and add a slash command. Here is what my settings page looks like:
This settings page is pretty self explanatory.
The main thing to notice here is the “Command” (the /slash command you want to use) and the “URL” (your Heroku URL + /post at the end).
Cross your fingers, refresh Slack (⌘ + R), and try out your new command:
Hopefully this tutorial helped you understand how you can take user input from Slack, ping external services, and return valuable data to your community. You could use this example app with just about any API that uses HTTP.
I recommend using Postman or cURL to test the HTTP requests. Heroku also has some great logging utilities:
heroku logs --tail
Please let me know in the comments if you had any trouble setting this up, or any other feedback. Make pull requests on Github and help me improve it!