If this is the millionth article you've found on how to build a Slack bot with Node.js, I'm sorry.
I've built a few Slack bots, some of which have launched on the Slack App Directory. I'm going to give you a no-bullshit tutorial on creating a Slack bot with Node.js.
We'll build an internal tool that your team can use to get information about your customers using a slash command. I'm not going to teach you how to build a Slack app for the Slack App Directory.
Quick plug: if you want to skip this entire article and focus on writing your internal tool, try Runtime.
Set up Ngrok
Ngrok is how you'll connect your Slack workspace (on the internet) to your locally-running Slack bot (on your machine). It has a free plan, but the Basic plan is affordable and extremely useful for building Slack bots.
Security note: Ngrok exposes your machine to the internet, making it a potential attack vector. If you're building your Slack bot on your work machine, get Ngrok approved by your security team.
Create an Ngrok account and follow the set-up steps. When you're finished, expose a web server on port 8080:
ngrok http 8080
This should produce the Ngrok console UI:
ngrok by @inconshreveable
Tunnel Status online
Version 2.0/2.0
Web Interface http://127.0.0.1:4040
Forwarding http://92832de0.ngrok.io -> localhost:8080
Forwarding https://92832de0.ngrok.io -> localhost:8080
Connnections ttl opn rt1 rt5 p50 p90
0 0 0.00 0.00 0.00 0.00
If you're on the free Ngrok plan, don't close this terminal window. The forwarding URL is randomly generated, and will change when you restart Ngrok.
Take note of the Forwarding
URL. In the example above, it is: https://92832de0.ngrok.io
.
Set up your Slack app
Before we start writing code, we need to create a Slack App.
- Navigate to https://api.slack.com/apps?new_app=1.
- Select From an app manifest.
- Replace
<NGROK_FORWARDING_URL>
with your Ngrok forwarding URL in the App Manifest YAML file below.
In the Ngrok example above, we would use
https://92832de0.ngrok.io
. So, theredirect_urls
example below would become:https://92832de0.ngrok.io/slack/oauth_redirect
- Copy-paste the YAML contents in the Enter app manifest below section.
_metadata:
major_version: 1
minor_version: 1
display_information:
name: NodeBot
description: Our internal Slack bot.
features:
bot_user:
display_name: NodeBot
always_online: true
slash_commands:
- command: /customer
url: <NGROK_FORWARDING_URL>/slack/events
description: Get data about a customer
usage_hint: /customer <customer id>
should_escape: false
oauth_config:
redirect_urls:
- <NGROK_FORWARDING_URL>/slack/oauth_redirect
scopes:
bot:
- commands
- chat:write
- chat:write.public
settings:
org_deploy_enabled: false
socket_mode_enabled: false
token_rotation_enabled: false
App Manifest for your Slack bot
- Select Next, then select Create.
Scroll down to the **App credentials **section and take note of the following values:
Client ID
Client secret
Signing secret
Finally, install the app to your Slack workspace.
- Select Install App on the left sidebar.
- Select Install to Workspace, and select Allow on the installation page.
- Take note of the
Bot User OAuth Token
.
Set up your Slack bot code
Let's ensure your local environment is set up correctly. The dependencies for this Slack bot are as follows:
node >=12.13.0
npm >=6.12.0
Start by creating a new directory for the Slack bot and initialising npm
:
mkdir slackbot-node
cd slackbot-node
npm init
Follow the prompts (tip: hold down the Enter key).
Let's install the project dependencies. Our main dependency is Bolt, the official Slack framework for building Slack apps with JavaScript.
npm install --save @slack/bolt dotenv
npm install --save-dev nodemon
Add your environment variables
- Create a
.env
file. - Add the following contents to your
.env
file, and add the values you took note of in the Set up your Slack app section.
SLACK_CLIENT_ID=<YOUR SLACK CLIENT ID>
SLACK_CLIENT_SECRET=<YOUR SLACK CLIENT SECRET>
SLACK_SIGNING_SECRET=<YOUR SLACK SIGNING SECRET>
SLACK_BOT_USER_TOKEN=<YOUR SLACKBOT USER TOKEN>
SLACK_OAUTH_STATE_SECRET='my-state-secret'
Create the bot server
- Create an
index.js
file. This will be the entry point for our bot server. - Copy-paste the following code:
require("dotenv").config();
const { App } = require("@slack/bolt");
const port = process.env.PORT || 8080;
const app = new App({
token: process.env.SLACK_BOT_USER_TOKEN,
signingSecret: process.env.SLACK_SIGNING_SECRET,
});
// Slash command handler goes here.
(async () => {
await app.start(port);
console.log(`🤖 Slack bot at your service (http://localhost:${port})`);
})();
- Check the server works by starting the bot server with
nodemon
.
nodemon
restarts the server whenever we edit ourindex.js
file
nodemon --exec node index.js
You should get the following output:
[nodemon] 2.0.13
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node index.js`
🤖 Slack bot at your service (http://localhost:8080)
Add a slash command
The App Manifest file that we used to create our Slack app has already added a slash command for us; it's called /customer
. Whenever somebody in your Slack workspace types /customer
, Slack will send a POST request to your bot server; we need to program our bot server to respond correctly to the /customer
slash command.
Add the following code to index.js
:
// Handle the /customer slash command
app.command('/customer', async ({ command, ack, respond }) => {
// Acknowledge command request
await ack();
await respond('Slack bot at your service!');
});
Now, we can test the slash command in Slack. Type /customer
in Slack. This should yield the following result:
Getting customer data
Finally, the juicy part. The method for getting customer data will vary based on your tech stack and where your customer data lives. Typically, you'll execute a database query here. For now, let's return some dummy user data.
Format your response with the Slack Block Kit Builder.
const customerData = {
name: "Jane Doe",
email: "jane@company.com",
activeUsers: 10,
plan: "Enterprise",
totalSpend: "$1002.26",
};
// Format the text however you like; Slack supports Markdown.
const header = `*${customerData.name}* (${customerData.email})`;
const body = `>${customerData.plan} plan\n>${customerData.activeUsers} users\n>${customerData.totalSpend} total spend`;
const response = {
response_type: "in_channel", // make the response public
blocks: [
{
type: "section",
text: {
type: "mrkdwn",
text: `${header}\n${body}`,
},
},
],
};
await respond(response);
Let's run it in Slack and see the result. Type /customer
in Slack:
Building and maintaining internal Slack bots is a hassle. I built Runtime to help you rapidly create custom Slack bots. Write your internal script in your technology of choice, and Runtime handles the rest. Let me know what you think on Twitter.
Top comments (0)