I can't send layout blocks using python slack API - python

I used the latest bot kit builder by slack to generate the following buttons for my message attachment. The message is getting sent without any problem and but I don't see the attachment. I have been trying to figure this out and appreciate some help. My attachment is a list as required by slack api.
attachment_json = [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "Hello, Please select your environment"
}
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": "production"
},
"value": "production"
},
{
"type": "button",
"text": {
"type": "plain_text",
"text": "staging"
},
"value": "staging"
},
{
"type": "button",
"text": {
"type": "plain_text",
"text": "demo"
},
"value": "demo"
}
]
}
]
I am using slackclient SDK to send the message.
slack_client.api_call("chat.postMessage", channel="D4KU1DGUB", text='Hello World',
attachments=json.dumps(attachment_json))
Currently I am not seeing any buttons. Any help will be appreciated. Thank you.
Even sending this attachment from the example is not working
{
"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"
}
}
]
}
]
}
This attachment is working for me
attachment_json = [
{
"fallback": "Upgrade your Slack client to use messages like these.",
"color": "#CC0000",
"actions": [
{
"type": "button",
"text": ":red_circle: Complete Task: ",
"url": "https://roach.ngrok.io/workflow/",
}
]
}
]
But I am can't figure out why the first example is not working.

The reason the first example is not working is that you are mixing the syntax for attachments and layout blocks in your method call. Those are different features and therefore each have their own parameter in the call to chat.postMessage.
(Secondary) attachments are passed with the attachments parameter.
Layout blocks are passed with the blocks parameter.
So the corrected version of your code from the first example would be:
slack_client.api_call("chat.postMessage", channel="D4KU1DGUB", text='Hello World',
blocks=json.dumps(attachment_json))
You may also want to rename the variable to blocks_json to avoid any confusion.

Related

Slack Bolt (Python) get values from modal and datepicker errors

I am creating a Slack app in Bolt framework for Python. I successfully created new command, which open new modal window with text input and datepicker.
The problem is, that when trying to submit I receive error: We had some trouble connecting. Try again?
Code:
#app.command("/echo")
def handle_command(body, ack, client, logger):
logger.info(body)
ack()
res = client.views_open(
trigger_id=body["trigger_id"],
view={
"title": {
"type": "plain_text",
"text": "Add info to feedback",
"emoji": True
},
"submit": {
"type": "plain_text",
"text": "Save",
"emoji": True
},
"type": "modal",
"callback_id": "view123",
"blocks": [
{
"type": "input",
"element": {
"type": "plain_text_input"
},
"label": {
"type": "plain_text",
"text": "Label",
"emoji": True
}
},
{
"type": "actions",
"elements": [
{
"type": "datepicker",
"initial_date": "1990-04-28",
"placeholder": {
"type": "plain_text",
"text": "Select a date",
"emoji": True
},
"action_id": "actionId-0"
},
{
"type": "datepicker",
"initial_date": "1990-04-28",
"placeholder": {
"type": "plain_text",
"text": "Select a date",
"emoji": True
},
"action_id": "actionId-1"
}
]
}
]
},
)
logger.info(res)
I figured out, that I have to listen to view submission, but don't know how to do it.
It doesn't work:
#app.view("view123")
def handle_submission(ack, body, client, view, logger):
ack()
Any ideas / suggestions what I am doing wrong?

Not receiving block_action payload when interacting with a Slack Block Kit modal

I've been working on a Slack bot to help handle emergency engagement for my team. It works really well, but all the configuration is in JSON files and it's time to make it "more interactive."
The other day we ended up with an email storm that triggered the bot over and over and over again, so I thought that a great and relatively simple place to start with the "more interactive" would be to add a "Snooze" button to our bot (as opposed to killing the running process).
I successfully display the modal, and the UI functions correctly, but I do not receive a payload on interaction. I expect my Flask App to receive a POST request containing payload data for an interaction, but I don't see any arrive not at the "/" endpoint that handles the majority of my interactions with Slack or the /911_snooze endpoint which is the one directly connected to the Slash Command.
I get a little warning triangle with the following error:
The JSON below is mostly created by Block Kit Builder, with some hand-cut, and the drop-down is created programmatically, based on an external list. Block Kit Builder reports no errors.
{
"title": {
"type": "plain_text",
"text": "911 Snooze Alerts",
"emoji": true
},
"submit": {
"type": "plain_text",
"text": "Submit",
"emoji": true
},
"type": "modal",
"callback_id": "snooze_911_alerts",
"close": {
"type": "plain_text",
"text": "Cancel",
"emoji": true
},
"blocks": [
{
"type": "divider"
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "Application to Snooze"
},
"accessory": {
"type": "static_select",
"placeholder": {
"type": "plain_text",
"text": "Application",
"emoji": true
},
"options": [
{
"text": {
"type": "plain_text",
"text": "APP1",
"emoji": true
},
"value": "BOE"
},
{
"text": {
"type": "plain_text",
"text": "APP2",
"emoji": true
},
"value": "IBOE"
},
{
"text": {
"type": "plain_text",
"text": "APP3",
"emoji": true
},
"value": "GBOE"
},
{
"text": {
"type": "plain_text",
"text": "APP4",
"emoji": true
},
"value": "Swift"
}
],
"action_id": "application_select_action"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "How long do you want to snooze for:"
},
"accessory": {
"type": "radio_buttons",
"options": [
{
"text": {
"type": "plain_text",
"text": "5 minutes",
"emoji": true
},
"value": "minutes-5"
},
{
"text": {
"type": "plain_text",
"text": "30 minutes",
"emoji": true
},
"value": "minutes-30"
},
{
"text": {
"type": "plain_text",
"text": "60 minutes",
"emoji": true
},
"value": "minutes-60"
},
{
"text": {
"type": "plain_text",
"text": "90 minutes",
"emoji": true
},
"value": "minutes-90"
}
],
"action_id": "radio_buttons-action"
}
}
]
}
The element block needs to be inside an action block, or input block with dispatch_action: true.
See https://api.slack.com/reference/block-kit/blocks#actions and https://api.slack.com/reference/block-kit/blocks#input

slack unfurling link with attachment blocks included

So my goal is to include an image, with buttons, in a message. However, the file is not public and files_upload method takes away the functionality of the buttons, issue similar to this https://github.com/slackapi/bolt-python/issues/411.
While working on the solution to 1. upload the file, 2. unfurl the permalink, I managed to make it work but the output is not what I would like:
I would like the unfurled link image to appear under the blocks while keeping the blocks in the attachment section. Is this achievable? Also, the only time I can unfurl is to include the link within the test section, can this be changed?
Sourcecode:
upload_resp = slack_client.files_upload(
initial_comment=uploadfiles["initial_comment"],
file=uploadfiles["file"],
filename=uploadfiles["filename"],
filetype=uploadfiles["filetype"],
title=uploadfiles["title"]
)
attachments = [
{
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Hi !*" ,
}
},
{
"type": "divider"
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Title*"
}
}
,{
"type": "actions",
"block_id": "actionblock",
"elements": [
{
"type": "button",
"action_id" : "rerun_action",
"text": {
"type": "plain_text",
"text": "Rerun",
"emoji": True
},
"style": "primary",
"value": "rerun"
},
{
"type": "button",
"action_id" : "launch_wizard",
"text": {
"type": "plain_text",
"text": "Launch Wizard",
"emoji": True
},
"style": "primary",
"value": "launch"
}
]
}
]
}
]
resp = slack_client.chat_postMessage(
channel=message["channel_id"],
text=upload_resp['file']['permalink'],
attachments = attachments,
blocks=[],
unfurl_links=True,
unfurl_media=True
)

Slack Application, pushing new modal based on selected option

I currently have my application to open a modal when a global shortcut is used. The modal opens and I am presented with 3 options. I was able to get it to push a new modal when any of the options were selected, but now I am stuck on how to open different modals based on the user response. Right now the code does not interpret which was selected, and just that an actionId-0 took place. I guess I am not really sure at the next steps. Do I need to utilize #app.view in order to read the submission payload?
Open on shortcut:
def open_modal(ack, shortcut, client):
# Acknowledge the shortcut request
ack()
# Call the views_open method using the built-in WebClient
client.views_open(
trigger_id=shortcut["trigger_id"],
# A simple view payload for a modal
view={
"title": {
"type": "plain_text",
"text": "#Tech Request"
},
"submit": {
"type": "plain_text",
"text": "Submit"
},
"type": "modal",
"close": {
"type": "plain_text",
"text": "Cancel"
},
"blocks": [
{
"type": "actions",
"elements": [
{
"type": "static_select",
"placeholder": {
"type": "plain_text",
"text": "Select an issue type"
},
"options": [
{
"text": {
"type": "plain_text",
"text": "Account Issues"
},
"value": "value-0"
},
{
"text": {
"type": "plain_text",
"text": "M1"
},
"value": "value-1"
},
{
"text": {
"type": "plain_text",
"text": "M2"
},
"value": "value-2"
}
],
"action_id": "actionId-0"
}
]
}
]
}
)
Open when any option is selected:
def update_modal(ack, body, client):
# Acknowledge the button request
ack()
# Call views_update with the built-in client
client.views_update(
# Pass the view_id
view_id=body["view"]["id"],
# String that represents view state to protect against race conditions
hash=body["view"]["hash"],
# View payload with updated blocks
view={
"title": {
"type": "plain_text",
"text": "Account Issue Request"
},
"submit": {
"type": "plain_text",
"text": "Submit"
},
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "This is a link to a confluence page"
},
"accessory": {
"type": "button",
"text": {
"type": "plain_text",
"text": "Click Me",
},
"value": "click_me_123",
"url": "https://google.com",
"action_id": "button-action"
}
},
{
"type": "input",
"element": {
"type": "plain_text_input",
"action_id": "plain_text_input-action"
},
"label": {
"type": "plain_text",
"text": "SFDC Contact ID:",
}
},
{
"type": "input",
"element": {
"type": "plain_text_input",
"action_id": "plain_text_input-action"
},
"label": {
"type": "plain_text",
"text": "Describe the issue",
}
},
{
"type": "input",
"element": {
"type": "multi_users_select",
"placeholder": {
"type": "plain_text",
"text": "Tag related people",
},
"action_id": "multi_users_select-action"
},
"label": {
"type": "plain_text",
"text": "Tag related people",
}
}
],
"type": "modal"
}
)
This is something that you have to take care of on the backend. I found that the easiest way to do this is to parse the payload received and send back a modal based on that

Slack View_submission not posting to Current Window

I am using the below code, to define Modal blocks and then submit the Modal via flask to slack. The slack command works fine and brings up the Modal UI. When I submit the Modal, it takes me to view_submission() method. In this method, I am calling client.chat_postMessage() to post a response to the current window, but this does not happen. If I pass in a Slack ChannelID, it posts the message to the channel, but when I pass in a Slack User_Id of the User I am interacting with via a DM, the message gets posted to the bots home screen. How do I post a response to the same window that the slash command was executed/requested from? I am looking for functionality similar to the /remind app in slack.
Response from /reminder command within same window
import os, logging
logging.basicConfig(level=logging.DEBUG)
from slack_bolt import App
app = App(
token="",
signing_secret="",
)
#app.middleware # or app.use(log_request)
def log_request(logger, body, next):
logger.debug(body)
next()
# Step 5: Payload is sent to this endpoint, we extract the `trigger_id` and call views.open
#app.command("/jarvis")
def handle_command(body, ack, client, logger):
logger.info(body)
ack(text="Accepted!",
blocks=[
{
"type": "section",
"block_id": "b",
"text": {
"type": "mrkdwn",
"text": ":white_check_mark: Accepting New Request!",
},
}
],
)
modal_block = open("modal.json", "r").read()
res = client.views_open(
trigger_id=body["trigger_id"],
view={
"type": "modal",
"callback_id": "settings-modal",
"title": {"type": "plain_text", "text": "Settings Form"},
"submit": {"type": "plain_text", "text": "Submit"},
"close": {"type": "plain_text", "text": "Cancel"},
"blocks": modal_block,
"private_metadata": "what is gona come here?"
},
)
logger.info(res)
# Step 4: The path that allows for your server to receive information from the modal sent in Slack
#app.view("settings-modal")
def view_submission(ack, body, client, logger):
ack()
logger.info(body["view"]["state"]["values"])
user_Id = body["user"]["id"]
client.chat_postMessage(channel=user_Id, text="submitted, wait please!!!")
if __name__ == "__main__":
app.start(5000)
modal.json
[
{
"type": "section",
"text": {
"type": "plain_text",
"text": ":wave: Hello!\n\nUse this tool wisely!!!"
}
},
{
"type": "divider"
},
{
"type": "input",
"block_id": "source_block",
"label": {
"type": "plain_text",
"text": "Source Tenant Name",
"emoji": true
},
"element": {
"type": "plain_text_input"
}
},
{
"type": "divider"
},
{
"type": "input",
"block_id": "dest_block",
"label": {
"type": "plain_text",
"text": "Destination Tenant Name",
"emoji": true
},
"element": {
"type": "plain_text_input"
}
},
{
"type": "input",
"block_id": "settings_block",
"label": {
"type": "plain_text",
"text": "Choose Settings"
},
"element": {
"type": "multi_static_select",
"placeholder": {
"type": "plain_text",
"text": "Select 1 or more Settings from the list below"
},
"initial_options": [
{
"value": "value-0",
"text": {
"type": "plain_text",
"text": "BU"
}
},
{
"value": "value-1",
"text": {
"type": "plain_text",
"text": "JT"
}
}
],
"options": [
{
"text": {
"type": "plain_text",
"text": "BU",
"emoji": true
},
"value": "value-0"
},
{
"text": {
"type": "plain_text",
"text": "JT",
"emoji": true
},
"value": "value-1"
},
{
"text": {
"type": "plain_text",
"text": ":desert_island: Hawaiian",
"emoji": true
},
"value": "value-2"
},
{
"text": {
"type": "plain_text",
"text": "Camp",
"emoji": true
},
"value": "value-3"
},
{
"text": {
"type": "plain_text",
"text": "TenMgmt",
"emoji": true
},
"value": "value-4"
},
{
"text": {
"type": "plain_text",
"text": ":taco: Tacos",
"emoji": true
},
"value": "value-5"
},
{
"text": {
"type": "plain_text",
"text": ":green_salad: Salad",
"emoji": true
},
"value": "value-6"
},
{
"text": {
"type": "plain_text",
"text": ":stew: Indian",
"emoji": true
},
"value": "value-7"
}
]
}
}
]
Ideally you should use response_url to post response to the same window .
Details:
Depending on the source, the interaction payload your app receives may
contain a response_url. This response_url is unique to each payload,
and can be used to publish messages back to the place where the
interaction happened.
https://api.slack.com/interactivity/handling#message_responses
Also, about using chat.postMessage for DM
You need to use conversations.open to get the DMId which will be passed as channel in chhat.PostMessage.
https://api.slack.com/methods/conversations.open

Categories