Chris Muir
Posted on June 15, 2021
Slack has done a good job of documenting how to create a basic Slack app to get you over the configuration hump. And there are some handy simple examples on Glitch which save you from having to create your own server to host the backend code. The following blog post captures my notes on how to do the same on my local Mac using NodeJS, Slack's Bolt JavaScript framework, and ngrok to expose the application to the internet.
There's nothing revolutionary in the following blog post, this is just a documentation exercise so I don't have to keep remembering every step!
Setup ngrok
Mac install instructions:
(1) Download ngrok (https://ngrok.com/download)
(2) Unzip the ngrok zip file, and drag and drop the resulting ngrok file to our user's Mac Application folder
(3) Setup a symbolic link so ngrok can be accessed across our system:
cd /usr/local/bin
ln -s /Applications/ngrok ngrok
(4) Start ngrok:
ngrok http 5000
Note we're forwarding to port 5000 in this example. Change this to whatever we want, but record the value. This will be important when we create the backend NodeJS code for the application shortly.
From the ngrok's output note the https:// forwarding address. Record this, you will need this shortly. The following is an example output:
Session Status online
Session Expires 1 hour, 59 minutes
Version 2.3.40
Region United States (us)
Web Interface http://127.0.0.1:4040
Forwarding http://165a936dd19b.ngrok.io -> http://localhost:5000
Forwarding https://165a936dd19b.ngrok.io -> http://localhost:5000
Configure the app at api.slack.com
Slack's api.slack.com website is where we setup and maintain the configuration of our application such as the application name, privileges, and the URLs for Slack to call our backend NodeJS application that we will create shortly.
In the following example we will use Slack's new beta manifest file format to setup the basic configuration.
(5) Create or reuse our own Slack account and Slack workspace
(6) Login to api.slack.com using our Slack account
(7) Select Your Apps button top right, then the Create an App button centre of the screen
(8) Select From an app manifest
(9) Step 1 of 3: Select your workspace
(10) Step 2 of 3: Copy in the following manifest file:
_metadata:
major_version: 1
minor_version: 1
display_information:
name: ScratchSlackApp
features:
app_home:
home_tab_enabled: false
messages_tab_enabled: true
messages_tab_read_only_enabled: false
bot_user:
display_name: ScratchSlackApp
always_online: false
oauth_config:
scopes:
bot:
- chat:write
- im:write
- im:history
settings:
event_subscriptions:
request_url: https://165a936dd19b.ngrok.io/slack/events
bot_events:
- message.im
org_deploy_enabled: false
socket_mode_enabled: false
Update the request_url with the ngrok https:// forwarding address from earlier.
(11) Continue with step 3 of 3: Select Create
(12) The website will now take us to the settings for the application. Ensure the Basic Information settings page is selected, then within this page under the Install your app heading, select the Install to Workspace button.
(13) In the proceeding permissions page, select the Allow button. This step will make the application available to our user in the Slack client under the Apps section. At this stage the application has no backend logic so the app will do nothing, we will create this next.
(14) Returning to the Basic Information setting page, navigate down to the App Credentials section and Show the Signing Secret (commonly known as the 'Slack Signing Secret'). Record this value, we will need this value in a moment.
(15) Select the OAuth & Permissions features page, and note the Bot User Oauth Token. Also record this value, you will need this in a moment.
ngrok note: if you stop and restart ngrok, assuming you are using the free version which does not provide a static URL, the ngrok URL will change each restart. To update the above request_url in the Slack app, visit the Event Subscriptions page and update the Request URL. However note if you manually update this value (rather than defining it through the manifest file when you first create the app), Slack will attempt to check that the URL is live and running. As such you need to create and run the Slack application first as defined in the next section before you can update the URL.
Create the NodeJS backend application
On completing the above steps, we are now ready to create the backend NodeJS application that will listen and respond to events sent by the user via the Slack client, relayed through Slack, as configured in the above settings.
In other words if the user types a message into our Slack app in the Slack client, the message will be relayed from the Slack client to Slack's own servers, whereupon Slack will look up the request_url defined above, and send the message to the defined URL where our Slack code is running and can respond.
(16) On our local Mac:
cd ~/Desktop
mkdir ScratchSlackApp
cd ScratchSlackApp
npm init -y
(17) In the same directory open the generated package.json file in our favourite text editor and overwrite the complete file with the following contents:
{
"name": "scratchslackapp",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@slack/bolt": "^3.4.0",
"dotenv": "^10.0.0"
}
}
(18) Still within our favourite text editor, create a new file app.js in the same directory and copy in the following code:
const { App, ExpressReceiver } = require('@slack/bolt');
require('dotenv').config();
const app = new App({
token: process.env.SLACK_BOT_TOKEN,
signingSecret: process.env.SLACK_SIGNING_SECRET
});
app.message(async ({ body, message, context, say }) => {
try {
if (body.event.type === 'message' && message.text !== undefined) {
say('Hi!');
}
} catch (error) {
say(error.message);
}
});
(async () => {
await app.start(process.env.PORT);
console.log('⚡️ Bolt app is running on port ' + process.env.PORT + '!');
})();
The basic code here:
New App() sets up a Slack app using the Slack Bolt JavaScript framework. This includes all the magic for setting up the required HTTP listeners, that will receive HTTP/HTTPS requests sent from Slack to our code via the request_url we configured in the manifest file earlier.
The app.message() handler receives 'text' messages from Slack which we can then respond to.
The final app.start() call in the async block starts the Bolt server, including the HTTP listeners.
(19) Note the 3 process.env calls to PORT, SLACK_BOT_TOKEN & SLACK_SIGNING_SECRET. These are the 3 values we asked you to record earlier. To set these in our favourite text editor create an additional file .env in the application's base directory, and copy in the values we recorded:
PORT=5000
SLACK_BOT_TOKEN=xoxb-123472270484-1234804366771-cEXFXx0jgAA9bnAAaS16fvgc
SLACK_SIGNING_SECRET=263b7d12a7ccaea3f838f3ef123062ef
The above values are examples only.
(20) Finally on the command line we need to install the libraries/dependencies defined in the package.json file then run our application:
npm install
node app.js
Posted on June 15, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.