FWIW, using my hacked in to_json
and from_json
filters, I now have actionable notifications working in Slack.
First, here’s the rest_command
for the slack API that I use.
rest_command:
slack_api:
url: https://slack.com/api/{{ api }}
content_type: 'application/json; charset=utf-8'
verify_ssl: true
method: 'post'
timeout: 20
headers:
Authorization: !secret slackbot_token
payload: '{{ payload }}'
Now an example of sending a notification message that would offer choices. I know I can do all this with YAML rather than JSON, but in some cases I use template logic to offer different options in the attachments. I haven’t figured out how to do this with YAML. Note the “callback_id” and the “name” values of the actions. They’ll be used later on.
- service: rest_command.slack_api
data_template:
api: 'chat.postMessage'
payload: >
{
"text": "Garage left open",
"channel": "<channel ID for your notification>",
"attachments": [
{
"fallback": "(options for closing the garage door)",
"title": "Close the garage door?",
"callback_id": "cover_left_open_callback",
"color": "#3AA3E3",
"attachment_type": "default",
"actions": [
{
"text": "Close it",
"name": "cover.garagedoor",
"type": "button",
"value": "Close it"
},
{
"text": "Leave it",
"name": "",
"type": "button",
"value": "Leave it"
}
]
}
]
}
Next comes the webhook trigger that gets hit when slack calls you back after clicking on one of the buttons:
automation:
- alias: slack_webhook
trigger:
- platform: webhook
webhook_id: <YOUR WEBHOOK ID>
condition:
- condition: template
value_template: >
{% set payload = trigger.data.payload | from_json %}
{{ (payload.token == '<YOUR SLACK VERIFICATION TOKEN>') and (payload.type == 'interactive_message') }}
action:
# I set my 'callback_id' to be the last part of the script entity
# I want to run when the callback is called
- service_template: >
{%- set payload = trigger.data.payload | from_json -%}
script.{{ payload.callback_id }}
data_template:
payload: '{{ trigger.data.payload }}'
# Then I delete the original message with the buttons and post
# another message saying that the original message was handled
# with the choice that the Slack user made.
- service: rest_command.slack_api
data_template:
api: 'chat.delete'
payload: >
{%- set payload = trigger.data.payload | from_json -%}
{
"channel": "{{ payload.channel.id }}",
"ts": "{{ payload.message_ts }}"
}
- service: rest_command.slack_api
data_template:
api: 'chat.postMessage'
payload: >
{%- set payload = trigger.data.payload | from_json -%}
{
"channel": "{{ payload.channel.id }}",
"text": "{{ payload.original_message.text }}\nHandled with '{{ payload.actions[0].value }}' by <@{{ payload.user.id }}>"
}
Lastly, here’s an example of one of my callback scripts. This would be the part that actually performs the action that the user chose:
script:
cover_left_open_callback:
sequence:
# Ensure that the value is not an empty string
# I use empty strings to mean "don't do anything".
# Otherwise, this value will be the entity_id of the cover that
# was left open.
- condition: template
value_template: >
{%- set pl = payload | from_json -%}
{{ not (pl.actions[0].name == "") }}
- service: cover.close_cover
data_template:
entity_id: >
{%- set pl = payload | from_json -%}
{{ pl.actions[0].name }}