Posted on • Originally published atblog.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, tryRuntime.
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 @inconshreveableTunnel Status onlineVersion 2.0/2.0Web Interface http://127.0.0.1:4040Forwarding http://92832de0.ngrok.io -> localhost:8080Forwarding https://92832de0.ngrok.io -> localhost:8080Connnections 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 theForwarding
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 tohttps://api.slack.com/apps?new_app=1.
- SelectFrom 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 theEnter app manifest below section.
_metadata:major_version:1minor_version:1display_information:name:NodeBotdescription:Our internal Slack bot.features:bot_user:display_name:NodeBotalways_online:trueslash_commands:-command:/customerurl:<NGROK_FORWARDING_URL>/slack/eventsdescription:Get data about a customerusage_hint:/customer <customer id>should_escape:falseoauth_config:redirect_urls:-<NGROK_FORWARDING_URL>/slack/oauth_redirectscopes:bot:-commands-chat:write-chat:write.publicsettings:org_deploy_enabled:falsesocket_mode_enabled:falsetoken_rotation_enabled:false
App Manifest for your Slack bot
- SelectNext, then selectCreate.
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.
- SelectInstall App on the left sidebar.
- SelectInstall to Workspace, and selectAllow 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 initialisingnpm
:
mkdirslackbot-nodecdslackbot-nodenpm init
Follow the prompts (tip: hold down the Enter key).
Let's install the project dependencies. Our main dependency isBolt, the official Slack framework for building Slack apps with JavaScript.
npm install --save @slack/bolt dotenvnpm 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 theSet 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");constport=process.env.PORT||8080;constapp=newApp({token:process.env.SLACK_BOT_USER_TOKEN,signingSecret:process.env.SLACK_SIGNING_SECRET,});// Slash command handler goes here.(async()=>{awaitapp.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
TheApp 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 toindex.js
:
// Handle the /customer slash commandapp.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 theSlack Block Kit Builder.
constcustomerData={name:"Jane Doe",email:"jane@company.com",activeUsers:10,plan:"Enterprise",totalSpend:"$1002.26",};// Format the text however you like; Slack supports Markdown.constheader=`*${customerData.name}* (${customerData.email})`;constbody=`>${customerData.plan} plan\n>${customerData.activeUsers} users\n>${customerData.totalSpend} total spend`;constresponse={response_type:"in_channel",// make the response publicblocks:[{type:"section",text:{type:"mrkdwn",text:`${header}\n${body}`,},},],};awaitrespond(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 builtRuntime 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 onTwitter.
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse