Message Buttons with Node.js
#Message Buttons with Node.js
Published: January 13, 2017
Message buttons in Slack enable a whole new level of interaction between users and the apps they love. This tutorial will guide you through a very basic implementation of the feature. At the end, you'll have a great foundation for building an app that delights your users.
Hereâs what youâll build! đš
Itâs a simple app⊠and thatâs the point! By conquering the basics, building interesting and complex interactions suddenly becomes much more attainable.
Before you get started
Message buttons are only available to Slack apps and will not work with stand-alone custom integrations. For the purposes of this tutorial, you will need to have created an app and have installed it on your team using our OAuth process and have included the commands scope.
đš If you are new to Slack apps and havenât yet worked with the OAuth process, it might be best starting HERE and coming back to this tutorial. đš
We'll use a Node.js app as an example. The concepts and patterns should readily transfer if your weapon of choice is Python, Ruby, or another web-friendly language.
What youâll need
- Slack app (listed here) installed on your team with the commands OAuth scope
- Server running Node.js
- Publicly accessible server with a valid SSL certificate
- Following Node.js modules:
- Express: popular HTTP framework
- Request: simple HTTP request client
- Body-parser: parsing middleware for Express.js
The beginning of your Node.js server file should resemble:
var express = require('express')
var request = require('request')
var bodyParser = require('body-parser')
var app = express()
var urlencodedParser = bodyParser.urlencoded({ extended: false })
Enable interactive messages
First, letâs setup a Request URL to handle interactive message requests:
Important: The Request URL must point to a TLS-enabled HTTPS URL located on a publicly accessible server with a valid SSL certificate.
-
Select your app here: https://api.slack.com/apps
-
Click the Interactive Messages link in the menu.
-
Click Enable Interactive Messages, enter your Request URL and click Enable Interactive Messages again.
This URL is the endpoint on your server for all action messages triggered by users in Slack. You only need one Request URL as the data needed to decipher between users, teams, and button events is delivered with each request. Youâll see more about this later. Promise.
Send buttons from a slash command trigger
Letâs quickly add a slash command to your app called /send-me-buttons
:
-
Select your app here: https://api.slack.com/apps
-
Click the Slash Commands link in the menu
-
Click Create New Command, enter /send-me-buttons in the Command field and enter your endpoint to receive your slash command events in the Request URL field. Note that commands bundled with apps only accept a POST routing method.
-
Take note of the Verification Token found on your appâs settings page in Slack under the App Credentials link. This token will be passed with each execution of a slash command and can be used to verify the authenticity of the request.
Add a POST route for slash commands
Now add the route you entered as the Request URL in the previous step. It should look something like this:
app.post('/slack/slash-commands/send-me-buttons', (req, res) =>{
})
Respond to slash command with message buttons
The request sent to your slash command Request URL is URL encoded so youâll have to decode this to retrieve the response_URL
. You will use this URL to post your button message to your user in Slack.
Add the urlencodedParser
variable that you defined earlier as a callback to decode the request body into JSON. The buttons are sent within the attachment of a message as an array of objects called actions
. Simply add the code below and there you have it!
app.post('/slack/slash-commands/send-me-buttons', urlencodedParser, (req, res) =>{
res.status(200).end() // best practice to respond with empty 200 status code
var reqBody = req.body
var responseURL = reqBody.response_url
if (reqBody.token != YOUR_APP_VERIFICATION_TOKEN){
res.status(403).end("Access forbidden")
}else{
var message = {
"text": "This is your first interactive message",
"attachments": [
{
"text": "Building buttons is easy right?",
"fallback": "Shame... buttons aren't supported in this land",
"callback_id": "button_tutorial",
"color": "#3AA3E3",
"attachment_type": "default",
"actions": [
{
"name": "yes",
"text": "yes",
"type": "button",
"value": "yes"
},
{
"name": "no",
"text": "no",
"type": "button",
"value": "no"
},
{
"name": "maybe",
"text": "maybe",
"type": "button",
"value": "maybe",
"style": "danger"
}
]
}
]
}
sendMessageToSlackResponseURL(responseURL, message)
}
})
Add the following function to send your JSON message to Slack using the response_url
that you received in the previous step. Youâll use this function again when you respond to button actions from your user.
function sendMessageToSlackResponseURL(responseURL, JSONmessage){
var postOptions = {
uri: responseURL,
method: 'POST',
headers: {
'Content-type': 'application/json'
},
json: JSONmessage
}
request(postOptions, (error, response, body) => {
if (error){
// handle errors as you see fit
}
})
}
As a fun side project, try some different formatting options with the Message Builder.
Receive and respond to button clicks
Now that your Node.js app is setup to send buttons to Slack, letâs configure a POST route to accept button actions.
When a user clicks on a button, your server will be sent a URL encoded request containing a body parameter called payload
which will contain data youâll need to handle the userâs action and to respond accordingly.
Pass the urlencodedParser
variable once again as a callback to retrieve the payload. The payload
is itself a URL encoded JSON string so use the JSON.parse()
method to extract the desired data.
Youâll then invoke your sendMessageToSlackResponseURL
function passing the response_url
and JSON message to respond as you did with the slash command.
Your interactive messages Request URL handler will look like this:
app.post('/slack/actions', urlencodedParser, (req, res) =>{
res.status(200).end() // best practice to respond with 200 status
var actionJSONPayload = JSON.parse(req.body.payload) // parse URL-encoded payload JSON string
var message = {
"text": actionJSONPayload.user.name+" clicked: "+actionJSONPayload.actions[0].name,
"replace_original": false
}
sendMessageToSlackResponseURL(actionJSONPayload.response_url, message)
})
To better understand the above code, hereâs an example of the payload youâll receive when your user clicks the "yes" button:
{
"actions":[
{
"name":"yes",
"value":"yes"
}
],
"callback_id":"button_tutorial",
"team":{
"id":"USERS_TEAM_ID",
"domain":"TEAM_NAME"
},
"channel":{
"id":"CHANNEL_ID",
"name":"CHANNEL_NAME"
},
"user":{
"id":"USER_ID",
"name":"USER_NAME"
},
"action_ts":"1471473851.000000",
"message_ts":"1471473846.000000",
"attachment_id":"1",
"token":"TOKEN",
"response_url":"UNIQUE_RESPONSE_URL"
}
Last steps
-
Save your server file
-
Restart your Node.js app
-
Execute the
/send-me-buttons
slash command from your Slack client -
Start clicking buttons!
đ YOUâRE DONE! đ
Whatâs next?
Now that youâve added message buttons to your app, hereâs a list of topics and features to investigate as you enhance your app:
-
Explore richer attachment formatting in your responses
-
Use the chat.update Web API method and the timestamp value to replace the original message. Check our docs for hints.
-
Add a database to your app to manage installations
-
Check out the complete message buttons documentation to see whatâs available to your button-enabled app! đ
Was this page helpful?