See https://slackhq.com/get-more-done-with-message-buttons-5fa5b283a59#.kn5h19a9h
The power of this if integrated with Hubot is immense!
@mhemmings I guess this can already be done via the SlackRawMessage and by replying with attachment actions — have you tried it?
Agreed that this would be a cool feature to add! I don't have the bandwidth to implement it myself, but would love a PR ;)
+1 for this, I would love to be able to have my hubot send a response with action buttons
+1 for this.
The catch, FWIW, is that only apps can use action buttons, but Hubot is implemented as a custom integration—which is not allowed to use action buttons. I'm working to see what we can manage, but I'm going to have to ask you to hold your collective breaths for the moment :(
Is there any plan to enable custom integrations to also use these action builds?
Unfortunately, that's not something I can knowledgably comment on.
By reading https://api.slack.com/bot-users, it seems a bot can be bundled as an app? But I guess it means hosting it.
There are also bot users, and it seems they can benefit from Action Buttons if I correctly understood the content of the page.
Sorry if I'm completely misunderstanding this thread. Ideally I'd like my hubot to make use of action buttons if it's possible though I'm getting the impression it's impossible to do via hubot. Or is this more it's difficult to make direct support whilst there's still a workaround?
I have my bot configured through the hubot app on slack instead of a custom configuration.
If it's impossible to do via Hubot, I'm guessing l would still be able to do it through the generic bot custom integration? I seem to have found a few examples of people using action buttons using botkit.
So, I did manage to get action buttons working through creating my own App: https://api.slack.com/apps I've added this to my team as an App and not a custom integration.
You get a Verification Token by creating a bot this way which was successfully able to connect a Botkit bot to. I imagine you should be able to connect to it with a hubot bot as well. I will quickly check this now.
Edit: Sadly I can't seem to connect hubot as it gives me this error:
ERROR v2 services token provided, please follow the upgrade instructions
Think this is because of this: https://github.com/slackhq/hubot-slack/pull/174/files since the Verification Token doesn't begin with xoxb or xoxp.
So there's probably no way to get hubot to be able to create action buttons? :[
@angelalukic what does an App Verification Token look like? Because if it does not work solely because of this verification, it should be fairly easy to patch.
PS: by the way, how have you been able to add an app if it is not available in the App Directory? Have not found a link or button to perform this action.
@oncletom The App Verification Token is a 24 character long string using uppercase and lowercase letters and numbers. There is no punctuation or xoxb/xoxp on the front.
I was able to create my app here: https://api.slack.com/apps
I think upon creating an app you have to actively add it to the App Directory, otherwise you can just add it to your own Slack channels for private use/testing purposes.
This would be a great feature to have.
We are thinking about ways to make this happen so you don't have to jump through these hoops, FWIW. I can't say when a solution will be ready, or what it will look like, however :(
+1 for this
I would love to have this cool feature!
I would love to have this cool feature!
I would love to have this feature
+1 for this!
At the moment, this is totally impossible to add to Hubot because of the way message buttons work. But I just wanted to update this ticket to let you know that finding a way to make this happen is increasingly a priority. Thanks for hanging in there, y'all!
If anyone is interested, I have this sort of working using workarounds; the _Bot User OAuth Access Token_ provided on the _OAuth & Permissions_ page for app management can be used fine for hubot-slack access. Then, you can use hubot's built-in router in a script to dispatch the callback events via robot.emit like this sample:
// VERY IMPORTANT! If you don't verify the token against the one on the app's
// Basic Info page, anyone can trigger these actions!
let slackToken = process.env.HUBOT_SLACK_VERIFY_TOKEN;
module.exports = (robot) => {
robot.router.post('/hubot/slack-msg-callback', (req, res) => {
let data = null;
if(req.body.payload) {
try {
data = JSON.parse(req.body.payload);
} catch(e) {
robot.logger.error("Invalid JSON submitted to Slack message callback");
res
.response(422)
.send('You supplied invalid JSON to this endpoint.');
return;
}
} else {
robot.logger.error("Non-JSON submitted to Slack message callback");
res
.response(422)
.send('You supplied invalid JSON to this endpoint.');
return;
}
if(data.token === slackToken) {
robot.logger.info("Request is good");
} else {
robot.logger.error("Token mismatch on Slack message callback");
res
.response(403)
.send('You are not authorized to use this endpoint.');
return;
}
let handled = robot.emit(`slack:msg_action:${data.callback_id}`, data, res);
if (!handled) {
res
.response(500)
.send('No scripts handled the action.');
}
});
};
@ceph3us can you be more specific on how to use this script?
HUBOT_SLACK_VERIFY_TOKEN env variable.http://HUBOT_HOST/hubot/slack-msg-callback, replacing HUBOT_HOST with the hostname and port your Hubot is listening on.res.send in your own scripts with an object crafted according to https://api.slack.com/docs/message-buttons to create messages with button actions. The callback_id parameter will be used by the script to emit an event called slack:msg_action:callback_id with the HTTP request data sent by Slack. You can listen for the event in your own scripts using robot.on('slack:msg_action:callback_id', function(data, res) { ... });, where data is the JSON object sent, and res is an Express response object you can use to send a response to Slack.response_url Slack provides. The first response must be send within 3 seconds or Slack will consider the action timed out.Sorry for the wall of text. It's rather convoluted this way, since you have to deal directly with the Slack API yourself, but it does work.
@ceph3us thanks a lot i will try it!
hello @ceph3us,
Firstly, i would like to thank you once again for posting your workarounds. They really helped me to implement interactive buttons with hubot and make them work pretty well.
Secondly, i would like to point out some minor changes i had to do in your script to make it work. It might be helpful for other users as well.
In my case, i am deploying in Heroku so maybe has to do with herokus's nodejs (don't know for sure as i am really new to node.js). Anyway, here is what i've changed:
let with var. Edit: using 'use strict'; command inside your script, it's ok to use let as wellres.response(422) with res.send(422). Do this for other error numbers as well (403 and 500)robot.emit('slack:msg_action:${data.callback_id}', data, res); with robot.emit(msg + callback_id, data, res); wheremsg = 'slack:msg_action:' and callback_id='some id'. Do the exact same thing for the listener i.e.robot.on(msg+callback_id, ...)My bad - I write most of my Hubot stuff using Babel, and I forgot that most people don't follow that setup!
You are absolutely free to use your modified version of the script I posted, and to avoid any further confusion I will officially state that the snippet is in the Public Domain, or the CC0 1.0 license if your jurisdiction does not have the concept of Public Domain.
Thanks for the tips about the status codes also.
hey there! sorry for the radio silence on this issue for a few months. since @DEGoodmanWilson is no longer here at Slack (:cry:), i failed to pick up the context on the issue. i'm glad the rest of the community (@ceph3us and @andreash92) have been so helpful. :heart: this community!
so as don alluded to before, our concept of Slack Apps has changed to include Apps that get installed to a single team. therefore, the old concept of custom integrations is, shall we say, retired. everything should be an App! the docs need to be updated to reflect this, so i've made #418.
now for addressing message buttons (and message menus!), one concern is that doing so requires users of this adapter to expose an HTTP server. many security-constrained users actually use this adapter because it implements RTM and doesn't require any incoming requests, since it relies on a persistent outgoing connection. we need to make it clear that if we support interactive messages, it will require incoming connections.
next, i think we should explore reusing the new npm module @slack/interactive-messages and writing just the glue code necessary to expose the right events to the robot instance. i have to look more carefully how an adapter can augment a robot to understand if that's even possible, but if anyone wants to volunteer to own this work, i'm happy to serve as a reviewer/helper. otherwise, this will have to get prioritized, and to be frank i don't think it will get addressed for a couple months that way.
hello again,
@ceph3us in your comment you mention response_url
- You can send a response back in JSON or text to edit the message, and edit it 4 more times within 30 minutes by POSTing the text or object to the response_url Slack provides. The first response must be send within 3 seconds or Slack will consider the action timed out.
I tested it my self and it's working great but i can't find any reason to reply using response_url instead of just replying back withres.reply(..) inside my robot.on(msg+callback_id, ...) function and provide a new interactive message or just a plain text. Do i miss or misunderstood something?
thanks for the help
The response_url method allows for more complex workflows, such as a chain of interaction messages. It's also useful for when you're waiting on things (remote API calls, long running jobs) that take more than 3 seconds to run; you reply to the message immediately to provide the user with a notice that the action is happening, then hit response_url to update the message after the action is done.
just going to drop a link to the relevant docs in case someone has the chance to pick up the integration of @slack/interactive-messages work: https://hubot.github.com/docs/scripting/#http-listener. it looks like you could use @ceph3us's script above as a skeleton and just fill in the blanks. the question is how we turn this into an API in the adapter.
You need the Slack app, as descibed by @ceph3us above (see here)
You can do it like this, by using @slack/interactive-messages:
npm install --save @slack/interactive-messages
Hubot already has an express HTTP listener started (by default at port 8080)
Then your custom script can look like this:
{ createMessageAdapter } = require('@slack/interactive-messages');
slackMessages = createMessageAdapter(process.env.APP_VERIFICATION_TOKEN);
module.exports = (robot) ->
#Use the slackMessage library an bind it to the endpoint available in Hubot.
robot.router.use('/slack/actions', slackMessages.expressMiddleware())
#Attach action handlers by `callback_id`
# (See: https://api.slack.com/docs/interactive-message-field-guide#attachment_fields)
slackMessages.action 'welcome_button', (payload) ->
robot.logger.debug 'handle welcome action with payload: ' + payload
# do the tricks as described by the interactive messages module
return payload
I think there are roughly 2 ways to incorporate this in the standard Slack adapter:
This is some example code:
# (See: https://api.slack.com/docs/interactive-message-field-guide#attachment_fields)
slackMessages.action /.*/, (payload, respond) ->
robot.logger.debug "Receiving a callback with id #{payload.callback_id}"
broadcast_event = () ->
robot.emit "messsage_callback_#{payload.callback_id}", payload, respond
setTimeout(broadcast_event, 5)
return payload.original_message
An handle/listener can look like this:
robot.on "messsage_callback_button_tutorial", (payload, respond) ->
# `payload` is JSON that describes an interaction with a message.
robot.logger.debug "The user #{payload.user.name} in team #{payload.team.domain} pressed the welcome button"
# do the trick with the payload message and use the respond method to update the message in Slack
respond(replacement)
For anyone else trying to get this to work, when you create your Slack App, you should add a Bot User too ... that will then give you a xoxb token that your bot can use to connect to Slack as normal. You'll then find that posting attachments with buttons work. I'm still to get actual callbacks working, but this is progress!
@liquidstate i am not sure if i understand what's the problem here but personally i followed ceph3us' explanation and it works as it has to work.
Also, as mentioned on number 5 of ceph3us' answer i am using the follow function to respond back using the responseURL
```
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
};
})
}
So to get this working I went through all the trouble of making a whole new Slack App for my work's Enterprise Grid. It works just fine. The only problem is there's no "Add Configuration" button like there is for Hubot so I can't even make multiple instances of the bot.
Why is this a problem? Well we have a production, a qa-testing, and multiple dev instances of the bot for each of our developers on the project.
So basically I'm stuck. I do not want to make this a published app because it's not meant for public consumption. I also don't want to make a new app for every instance of our bot. That's just ridiculous.
hello,
i have added hubot to slack then i connect him with the given token
so in my code i use this :
robot.hear(/test/i, res => {
res.send({
"text": "Would you like to play a game?",
"attachments": [
{
"text": "Choose a game to play",
"fallback": "You are unable to choose a game",
"callback_id": "wopr_game",
"color": "#3AA3E3",
"attachment_type": "default",
"actions": [
{
"name": "game",
"text": "Chess",
"type": "button",
"value": "chess"
},
{
"name": "game",
"text": "Falken's Maze",
"type": "button",
"value": "maze"
},
{
"name": "game",
"text": "Thermonuclear War",
"style": "danger",
"type": "button",
"value": "war",
"confirm": {
"title": "Are you sure?",
"text": "Wouldn't you prefer a good game of chess?",
"ok_text": "Yes",
"dismiss_text": "No"
}
}
]
}
]
})
});
i try to make it work, but on click on button, slackbot say that :
Darn – that didn’t work. Only Slack Apps can add interactive elements to messages. Manage your apps here: https://api.slack.com/apps/
i have added an slack app and connected @slack/interactive-messages.
// Attach action handlers by callback_id
slackMessages.action('wopr_game', (payload) => {
console.log(payload);
});
now nothing change.
Darn – that didn’t work. Only Slack Apps can add interactive elements to messages. Manage your apps here: https://api.slack.com/apps/
same error ...
someone make it work ? wath i miss ?
thx for the help
@madbean
Do not use a "Hubot" Configuration. It has no support for "Interactive Messages".
You need to create a new Slack Application with "Interactive Messages" and "Bots" enabled as features.


thx for the quick response, one more question, i have activated the feature but now i doesn't have any token, should i create a custom bot to get a token ? https://my.slack.com/services/new/bot ?
thx.
edit : i answer to me : the token is on the install section
@madbean
Yes. You need to enable "Bots" in the new App you made. It will give you new API tokens for a bot.
Counter intuitively the bot tokens will be under OAuth & Permissions

Hubot will work just fine with these.
sorry if this is a dumb question, but is there a particular reason why @ceph3us solution can't be integrated into hubot (providing the user defines the correct HUBOT_SLACK_VERIFY_TOKEN)
@gingerlime
The hubot configuration under Slack Apps doesn't have interactive messages switched on and therefore there's no way to specify a Request URL that gets hit with a POST by Slack when someone hits a button.
@gingerlime
@hparadiz
You can set up a slack app instead of using the slack's hubot configuration and then you can use it just fine.
@andreash92
You should know that even though it does work the WebAPI client in the hubot environment won't have access to everything that a normal Hubot configuration would have.
@hparadiz oh i didnt know that. could you please give me an example of this "the WebAPI client in the hubot environment won't have access to everything that a normal Hubot configuration would have." ?
@andreash92
I referenced it in issue #439
Basically try running robot.adapter.client.web.channels.history
A Hubot configuration will work.
A stand alone Slack application using the Bot OAuth key will NOT work.
You actually need to make a second WebClient instance to get around this.
@hparadiz oh now i see what you mean. thanks for letting us know
sorry, but I'm confused. What exactly is a "Hubot Configuration"? If I have hubot running and using the slack adapter, can I then use @ceph3us solution? If so, what's blocking this being merged into the project?
@gingerlime
To setup Hubot you need to add it to your team on Slack. You do this by visiting http://TEAM.slack.com/apps, searching for Hubot, and then clicking Add Configuration like so:

A Hubot configuration is a special type of Slack application. It comes with an OAuth bot token but not much else. It does NOT support interactive messages (buttons, drop downs).
The benefit of a Hubot configuration is that the OAuth bot token provided gives you access to all of the abilities that are provided by the Slack Web API without having to use a different OAuth access token.
TLDR
Yes, you can use the solution posted by @ceph3us but be aware that the built in WebAPI client (accessible inside Hubot as robot.adapter.web) is using the same OAuth token for the WebAPI which has fewer permission scopes. If you for any reason need to run channels:history IT WILL NOT WORK.
Hi guys, I made small dumb wrapper of node-slack-interactive-messages for Hubot in here, so people can write external Hubot scripts using Slack interactive messages without conflicting with each other. I hope the module to be more than what it is right now.
Thanks a lot @hparadiz and @alFReD-NSH ! Hope I'll get a chance to play around with this soon :)
@alFReD-NSH your project is very interesting! since your goal / motivation is to standardize interactive message in the hubot robot interface, i think creating an issue in hubotio/hubot would be wise, so that all adapter authors can try to confirm to the same interfaces. i'd be happy to implement some standard interface in this adapter.
status update: i've heard the feedback that setting up Apps is quite a bit more work than using the custom bot method or using the Hubot configuration method of registering with Slack. i'm trying to work out how we can simplify the creation of Apps. if that proves to be too much work to get done quickly, then we'll go ahead with updating the docs for App creation. either way we'll be integrating the @slack/interactive-messages package into this adapter.
is there any way to get this working when having hubot behind the firewall? We connect it through a http-proxy and that works well, but buttons require a URL accessible on the internet.
@davidkarlsen you will have to allow an incoming connection from slack's servers in order to use interactive message features.
in a strict security environment, i recommend verifying requests are originating from slack by checking the verification token on an unprivileged proxy that can forward only verified requests into your trusted infrastructure. this is essentially shared secret (password) security. one step further you might want to take is to make your Request URL extremely obfuscated and difficult to guess.
@aoberoi Any updates?
@zdrummond we don't have any development for this feature planned. the maintainers are definitely open to contributions to address this need, and we'd be happy to review and give feedback to PRs.
Would it be more appropriate to add support for block kit stuff, since that exposes some interactivity components?
Or can you use the existing msg.send function with an attachments object?
See this is still open. You might want to check out slack-block-builder. It makes the process of creating interactive elements and modals more maintainable and declarative.
Most helpful comment
At the moment, this is totally impossible to add to Hubot because of the way message buttons work. But I just wanted to update this ticket to let you know that finding a way to make this happen is increasingly a priority. Thanks for hanging in there, y'all!