Support Slack Message Buttons
Slack recently introduced the concept of message buttons.

Blog post: https://slackhq.com/get-more-done-with-message-buttons-5fa5b283a59 Developer documentation: https://api.slack.com/docs/message-buttons
Here's their summary of the interaction model:
- Your application produces a message containing buttons. Maybe the message originated in response to an invoked slash command, or in response to a bot user's trigger phrase. Or maybe your app posted the message manually using an incoming webhook or chat.postMessage. In any case, your Slack app produced a message with buttons, offering users a chance to interact with it.
- Users encounter your message and, inspired by its call to action, clicks one of your buttons. This triggers an invocation of your application's associated Action URL.
- Slack sends a request to your Action URL, sending all the context needed to identify the originating message, the user that executed the action, and the specific values you've associated with the button. This request also contains a response_url you can use to continue interacting with the user or channel.
- Your application responds to the action. If you respond directly to the incoming invocation request, your provided message will replace the existing message. It's also possible to respond with an ephemeral message, visible only to the invoking user. Or you can just respond with HTTP 200 OK and wait to continue the interaction until later using the response_url provided as part of the action.
- Meanwhile: Your application does whatever it does as a result of the intended action to be taken: enqueue a process, save a database row, or continue interacting with users through additional message buttons.
- By using the response_url, your app can continue interacting with users up to 5 times within 30 minutes of the action invocation. Use this to continue through a workflow until it is complete.
- Messages can evolve. By using chat.update and your created message's message_ts field, you can modify the original interactive message (including all of its attachments) to add or remove buttons based on user interactions.
I opened this issue so there would be a place for conversation about if and how errbot could support message buttons.
We are considering this. But we will have to emulate that for the other backends that don't support it probably like what we did for the cards with some markdown.
Any idea when could this feature be implemented for Slack ?
Nothing concrete is currently being worked on (to the best of my knowledge) so don't get your hopes up too much.
Any news or progress on this?
@i-nikolov I am using Slack's API to make use of this feature instead of relying on any functions from errbot.
@ab9-er Will you be willing to share some code examples with us?
@eran-totango check this out https://gist.github.com/ab9-er/e47695429262f8274d1b0a9b19114db0
(I have initiated a variable with a mutable value which is not the best of the practices but it was a dirty quick example) 😈
The function should also return something, which it doesn't in the basic example, best would be to return the result of the API call which should be a 200 OK along with the ts value of the message and other details as per Slack's API documentation.
@ab9-er cool, I'd really love to integrate that to flows: they basically match this with button answers being fed to the context and unlocking steps. I don't have much time for myself at the moment but I can guide anyone willing to do that.
@gbin-argo I could help chip in but sporadically.
I'm a bit keen on this too, but I also see authentication being "fun" (not). @ab9-er how did you handle that?
@ab9-er @gbin-argo Is there any update regarding this feature? if not then I would like to take up the task of implementing this feature :smile:
You guys may want to take a quick glance at https://api.slack.com/changelog/2018-12-a-bric-a-brac-of-broadcasts-built-with-blocks before starting any work. I don't know if it impacts buttons, but it might.
Blocks also introduce more interactive options for app developers. They provide visually cleaner ways to incorporate buttons or menus, as well as new interactive elements like date pickers or overflow menus.
I guess this is more meant to be provided by Slack Events errbotio/errbot#1451 . The way I implemented it in my custom Slack Event Backend was by parsing the button event (interactive message) as a text message with extra fields.
def _interactive_message_event_handler(self, event):
"""
Event handler for the 'interactive' event, used in attachments / buttons.
"""
msg = Message(
frm=SlackPerson(event['user']['id'], event['channel']['id'], bot=self),
to=self.bot_identifier,
extras={
'actions': [{x['name']: x} for x in event['actions']],
'url': event['response_url'],
'trigger_id': event.get('trigger_id', None),
'callback_id': event.get('callback_id', None),
'slack_event': event
}
)
flow, _ = self.flow_executor.check_inflight_flow_triggered(msg.extras['callback_id'], msg.frm)
if flow:
log.debug("Reattach context from flow %s to the message", flow._root.name)
msg.ctx = flow.ctx
self.callback_message(msg)
Then on callback_message of the plugin:
def callback_message(self, msg):
callback = msg.extras.get('callback_id', None)
if (
callback and callback in dir(self) and
callable(getattr(self, callback))
):
self.log.info(f'Calling function {callback}')
return getattr(self, callback)(msg)
Finally on the command:
@botcmd
def approval_request(self, msg, args=None):
""" Check response of a request. """
if msg.extras.get('callback_id', None) == 'approval_request':
answer = msg.extras.get('actions')[0]['question']['value']
answer = True if answer == 'Approve' else False