Slack View_submission not posting to Current Window - python

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

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
)

How to add condition to add a mandatory input field for the user in slack bot using python?

I am creating a slack bot in python using slack bolt. I have created a form like structure for the user to provide input values but I need to specify some inputs as mandatory. I tried using the "optional":true field but did not get any result
I need to give the datepicker input and multi select input as mandatory fields for the user where input is necessary.
Below is the block I have created:
blocks = [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "Title"
}
},
{
"type": "header",
"text": {
"type": "plain_text",
"text": "Date Duration"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "_Required Field_"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "Start Date"
}
},
{
"type": "input",
"element": {
"type": "datepicker",
"placeholder": {
"type": "plain_text",
"text": "Select Start date"
},
"action_id": "start_date_action"
},
"label": {
"type": "plain_text",
"text": " "
},
"hint": {
"type": "plain_text",
"text": "Please ensure start date should be greater than current date "
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "End Date"
}
},
{
"type": "input",
"element": {
"type": "datepicker",
"placeholder": {
"type": "plain_text",
"text": "Select End date"
},
"action_id": "end_date_action"
},
"label": {
"type": "plain_text",
"text": " "
},
"hint": {
"type": "plain_text",
"text": "Please ensure end date should be greater than start date "
}
},
{
"type": "divider"
},
{
"type": "header",
"text": {
"type": "plain_text",
"text": "Field1"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "_Required Field_"
}
},
{
"type": "input",
"hint": {
"type": "plain_text",
"text": "Multiple inputs are accepted"
},
"element": {
"type": "multi_static_select",
"placeholder": {
"type": "plain_text",
"text": "Select field"
},
"options": [
{
"text": {
"type": "plain_text",
"text": "11111"
},
"value": "value-0"
},
{
"text": {
"type": "plain_text",
"text": "22222"
},
"value": "value-1"
}
],
"action_id": "1_multi_select-action"
},
"label": {
"type": "plain_text",
"text": " "
}
},
{
"type": "divider"
},
{
"type": "divider"
},
{
"type": "header",
"text": {
"type": "plain_text",
"text": "Field3"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "_Optional Field_"
}
},
{
"type": "input",
"hint": {
"type": "plain_text",
"text": "Multiple inputs are accepted"
},
"element": {
"type": "multi_static_select",
"placeholder": {
"type": "plain_text",
"text": "Select Categories"
},
"options": [
{
"text": {
"type": "plain_text",
"text": "adventure"
},
"value": "value-0"
},
{
"text": {
"type": "plain_text",
"text": "biking"
},
"value": "value-2"
}
],
"action_id": "categories_multi_select-action"
},
"label": {
"type": "plain_text",
"text": " "
}
},
{
"type": "divider"
},
{
"type": "header",
"text": {
"type": "plain_text",
"text": "Number"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "_Optional Field_"
}
},
{
"type": "input",
"hint": {
"type": "plain_text",
"text": "Numeric values only"
},
"element": {
"type": "plain_text_input",
"action_id": "plain_text_input-action",
"placeholder": {
"type": "plain_text",
"text": "Enter Numeric Value"
}
},
"label": {
"type": "plain_text",
"text": " "
}
},
{
"type": "divider"
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": "Submit"
},
"value": "submit_form",
"action_id": "submit_action"
}
]
}
]
And passing the black to post a message like this
app.client.chat_postEphemeral(
channel=body["channel"]["id"],
user=body['user']['id'],
blocks=param_block,
text="text_msg",
)
Is there a way to consider text input field with just numerical values?
I'm also attaching the screenshot of the block

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

Categories