DEV Community

Tom Quirk
Tom Quirk

Posted on • Originally published at blog.runtimehq.com

Create a Slack Bot with Node.js: The Definitive Guide

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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.

  1. Navigate to https://api.slack.com/apps?new_app=1.
  2. Select From an app manifest.
  3. 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, the redirect_urls example below would become: https://92832de0.ngrok.io/slack/oauth_redirect

  1.  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
Enter fullscreen mode Exit fullscreen mode

App Manifest for your Slack bot

  1. 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.

  1. Select Install App on the left sidebar.
  2. Select Install to Workspace, and select Allow on the installation page.
  3. 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Add your environment variables

  1. Create a .env file.
  2. 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'
Enter fullscreen mode Exit fullscreen mode

Create the bot server

  1. Create an index.js file. This will be the entry point for our bot server.
  2. 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})`);
})();
Enter fullscreen mode Exit fullscreen mode
  1.  Check the server works by starting the bot server with nodemon.

nodemon restarts the server whenever we edit our index.js file

nodemon --exec node index.js
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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!');
});
Enter fullscreen mode Exit fullscreen mode

Now, we can test the slash command in Slack. Type /customer in Slack. This should yield the following result:
Slash command example

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);
Enter fullscreen mode Exit fullscreen mode

Let's run it in Slack and see the result. Type /customer in Slack:
Final slash command example


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.

Discussion (0)