"Invalid blocks" when updating ephemeral message via response_url webhook - slack

According to Slack's documentation, you can use blocks to update an entire ephemeral message by simply replacing the entire message by setting replace_original as true when posting to the response_url provided in the interaction payload when using buttons.
However, when I'm sending the POST request to the provided response_url after a button has been pressed and I attempt to use blocks, I get the following error: 404 : [{"ok":false,"error":"invalid_blocks"}]
Strangely enough, the payload I'm including for blocks is generated by the same method that creates the original ephemeral message which works fine without any issues.
I was able to replace the entire message with just a plain text message by using the text field indicated in the documentation and it works fine if I don't include the blocks array. I did find some documentation here for posting messages via incoming webhooks here but it looks the same as what I'm sending now.
Here's the body of the request I'm sending:
{
"blocks":
[
{
"type": "image",
"imageUrl": "https://example.com/image.jpeg",
"altText": "alt-text",
"title":
{
"type": "plain_text",
"text": "some text"
}
},
{
"type": "actions",
"elements":
[
{
"type": "button",
"text":
{
"type": "plain_text",
"text": "Send",
"emoji": false
},
"value": "send",
"style": "primary"
},
{
"type": "button",
"text":
{
"type": "plain_text",
"text": "Find new",
"emoji": false
},
"value": "some text"
},
{
"type": "button",
"text":
{
"type": "plain_text",
"text": "Cancel",
"emoji": false
},
"value": "cancel"
}
]
}
],
"replace_original": "true",
"text": "some fallback text"
}

You have two typos in your blocks: imageUrl and altText. Slack expects these to be snake case, i.e. image_url and alt_text.
You can use Slack's Block Kit Builder to debug the blocks payload.

Related

Slack Block Kit static_select behaves differently on Mac app and iPhone

I am developing a Slack app with Slack's Block Kit.
In Block Kit, I can create a list by using static_select, and I can confirm that action_id is requested when an option is selected.
However, when we checked the behavior on a smart phone, we noticed that there is no action_id response when an option is selected.
I have confirmed that this is not a problem with the Slack app on Mac and Chrome browser, but I have confirmed that the problem occurs with the Slack app on iPhone.
This problem does not occur if I place a static_select under type: actions.
As a solution, I feel that we should have a Submit button separate from the list, but I feel that it would be delicate to add more buttons due to differences in behavior in different environments.
Please let me know if you have any ideas.
# iPhone does not respond to action_id
# (I checked the access log in real time on the server that receives the action_id, but it seems that no request was generated in the first place.)
{
"blocks": [
{
"type": "input",
"element": {
"type": "static_select",
"placeholder": {
"type": "plain_text",
"text": "Select an item",
"emoji": true
},
"options": [
{
"text": {
"type": "plain_text",
"text": "*this is plain_text text*",
"emoji": true
},
"value": "value-0"
}
],
"action_id": "static_select-action"
},
"label": {
"type": "plain_text",
"text": "Label",
"emoji": true
}
}
]
}
# iPhone reacts to action_id
{
"blocks": [
{
"type": "actions",
"elements": [
{
"type": "static_select",
"placeholder": {
"type": "plain_text",
"text": "Select an item",
"emoji": true
},
"options": [
{
"text": {
"type": "plain_text",
"text": "*this is plain_text text*",
"emoji": true
},
"value": "value-0"
}
],
"action_id": "actionId-3"
}
]
}
]
}
I would like to have the same behavior between the Slack app on Mac and the Slack app on iPhone.

I would like to use Blocks instead of Attachments in my Slack App but the app fails to return the message

I recently made my first Slack app - a sort of Tech Support FAQs tool for my workplace workspace.
I originally wanted the responses to be much more complex using the Slack Block Kit, and having trawled the documentation on the Slack API site it looked like I could simply exchange Attachments for Blocks:
function respondWithFaq(text, callbackId, respond, choice) {
frequentlyAskedQuestions.callback_id = callbackId
frequentlyAskedQuestions.text = 'What are you trying to do?'
respond({
text: text,
attachments: [frequentlyAskedQuestions[choice]], //All different choices are saved in a .json array and then saved at the top in a variable called frequentlyAskedQuestions
replace_original: true
})
}
However, when I swap that tag out the messages never print. I have used the Block Kit builder to try and construct more complex and useful responses using multiple sections but it doesn't seem to like more than 1 section in it's responses.
My .json files are structured in arrays depending on which choice was made in the previous select menu like so:
[
{
"fallback": "Upgrade your Slack client to use messages like these.",
"color": "#3AA3E3",
"attachment_type": "default",
"callback_id" : "slack_help",
"actions": [
{
"name": "subject_list",
"text": "Select one",
"type": "select",
"options": [
{
"text": "Add somebody to a channel",
"value": "addToChannel"
},
{
"text": "Find an old message",
"value": "oldMessageThread"
},
{
"text": "Fix my camera",
"value": "cameraBroken"
},
{
"text": "Fix my audio",
"value": "audioBroken"
},
{
"text": "Add a new workspace",
"value": "addWorkspace"
},
{
"text": "Submit a support ticket",
"value": "submitTicket"
}
]
}
]
},
{
"fallback": "Upgrade your Slack client to use messages like these.",
"color": "#3AA3E3",
"attachment_type": "default",
"callback_id" : "box_help",
"actions": [
{
"name": "subject_list",
"text": "Select one",
"type": "select",
"options": [
{
"text": "Fix Box Tools",
"value": "boxTools"
},
{
"text": "Unable to open a file from Box",
"value": "microsoftOnline"
},
{
"text": "Find a file or folder",
"value": "findFile"
},
{
"text": "Edit a file that has been shared with me",
"value": "editFile"
},
{
"text": "Merge my Box accounts",
"value": "accountMerge"
},
{
"text": "Submit a support ticket",
"value": "submitTicket"
}
]
}
]
},
and so on...
I wondered if this was something to do with the Response URL formatting but having read that documentation it appears that Blocks can be used within that.
Any advice or documentation that could help me with this?
I recognise that I am quite new to coding and perhaps I've done something really obvious - please point it out so I can learn!
I followed this tutorial online to create the app, and as they used attachments so did I. Then I tried to adapt from there.

How to create a teams card using external webservice and post data in power automate(Part 2)

This is a continuation of my other question:
My first question
What I am trying to accomplish:
User enters a mention
My web service creates an adaptive card form with custom data (same schema)
presents the card to my user
user enters some data
Submit sends this form data to my web service for processing
Here is the card (the result of the 1st http) I am sending in reply to mention
$var = '{
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.2",
"msTeams": {
"width": "full"
},
"body": [
{
"type": "TextBlock",
"text": "Adaptive Card Example",
"wrap": true,
"size": "large",
"weight": "bolder",
"id": "title"
},
{
"type": "Input.Text",
"placeholder": "Provide your thoughts",
"separator": true,
"isMultiline": true,
"id": "thoughts"
},
{
"type": "ActionSet",
"separator": true,
"actions": [
{
"type": "Action.Submit",
"title": "Submit",
"style": "positive",
"id": "submit"
}
]
}
]
}
';
How do i get to the value of input.text with the id of thoughts? everything i see, it ends up blank.
I am not sure what else you need to help, i can edit/post anything else.
*EDIT
this is my dynamic dropdown.
You should be able to make use of the dynamic content presented to you that is taken directly from your adaptive card definition ...
If the dynamic property doesn't exist, the easiest way to get the result is to simply refer to it using an expression ...
body('Post_adaptive_card_and_wait_for_a_response')?['data']?['thoughts']
... you could do the work to fully qualify the dynamic properties but in this case, it seems like overkill.
This is the output after I completed the card in my Teams channel ...

Dynamic ChoiceSet in Adaptive Cards "Post an Adaptive Card to a Teams user and wait for a response"

I have the following JSON code for an Adaptive Card. I put this into a "Compose" Data operation, and then used the "Post your own adaptive card as the Flow bot to a user" and it successfully works. However, using this REST API doesn't work when you want to wait for a response. So I tried to use "Post an Adaptive Card to a Teams user and wait for a response", but when I try to use the following JSON code below, it is giving me an error of... "[Validation] An Input.ChoiceSet must have at least one choice defined."
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.2",
"body": [
{
"type": "TextBlock",
"size": "Medium",
"weight": "Bolder",
"text": "Input.Text elements",
"horizontalAlignment": "Center",
"wrap": true
},
{
"type": "TextBlock",
"text": "Part #",
"wrap": true
},
{
"type": "Input.ChoiceSet",
"id": "choiceSelect",
"choices": #{variables('ArrayTest')}
},
{
"type": "TextBlock",
"text": "Due Date",
"wrap": true
},
{
"type": "Input.Date",
"id": "DateVal"
},
{
"type": "TextBlock",
"text": "Start time",
"wrap": true
},
{
"type": "Input.Time",
"id": "TimeVal"
}
],
"actions": [
{
"type": "Action.Submit",
"title": "Submit"
}
]
}
So after receiving this error, I tried to manipulate the code and I ended up changing the ChoiceSet to this
{
"type": "Input.ChoiceSet",
"id": "choiceSelect",
"choices": [
{
"title": "#{variables('ArrayTest')}",
"value": "#{variables('ArrayTest')}"
}
]
}
And I did not receive in a error in the Adaptive Card, but rather a Power Automate error of...
"The request failed. Error code: 'InvalidJsonInBotAdaptiveCard'. Error Message: 'Microsoft.Azure.ProcessSimple.Data.Entities.Exceptions.ProcessSimpleDataException: The specified Teams flowbot adaptive card request is missing or invalid. The tracking Id is '{0}'. ---> Newtonsoft.Json.JsonReaderException: After parsing a value an unexpected character was encountered: t. Path 'body[2].choices[0].title', line 1, position 356."
My question is... How can I use a dynamic ChoiceSet while also utilizing the "wait for a response"? I successfully can get it in a "Post your own adaptive card as the Flow bot to a user" but not a "Post an Adaptive Card to a Teams user and wait for a response"

How to display validation errors about non-input blocks in Slack modals

Question
I have a Slack modal with a section block containing an input element. When a user submits my modal without entering a value in this input, how do I communicate that error to the user?
My attempt #1: respond with a validation error
Slack's documentation describes how to validate input blocks when I receive a view_submission event (https://api.slack.com/surfaces/modals/using#displaying_errors). But if I return an error for a section block containing a static_select, then Slack does not display an error message (nor does it close the modal).
My attempt #2: set the optional field to false
input blocks have an optional field that can be used for validation. But a static_select in a section block does not have an optional field: https://api.slack.com/reference/block-kit/block-elements#select
My attempt #3: use input blocks
I can not use input blocks because they do not trigger block_actions messages (documented at https://api.slack.com/surfaces/modals/using#interactions). I need to update the modal as the users answer questions.
My attempt #4: the desperation solution that works
I could reply to the view_submission event with a "response_action": "update" response. In that response include an error message like this above the input with the missing value:
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Please provide a start time:*"
}
}
I do not like this solution because I doubt I can duplicate the nice error messaging UX that Slack provides for input block validation.
Details
Here is a simplified version of the view parameter that I am passing to the views.open call:
{
"blocks": [
{
"block_id": "start_times",
"type": "section",
"text": {
"type": "plain_text",
"text": "Choose a start time"
},
"accessory": {
"action_id": "start_times",
"type": "static_select",
"placeholder": {
"type": "plain_text",
"text": "Choose start"
},
"options": [
{
"text": {
"type": "plain_text",
"text": "10:27 pm"
},
"value":
"{\"path\":\"bookings/new\",\"date\":\"2020-02-14 04:27:22 UTC\"}"
},
{
"text": {
"type": "plain_text",
"text": "10:45 pm"
},
"value":
"{\"path\":\"bookings/new\",\"date\":\"2020-02-14 04:45:00 UTC\"}"
}
]
}
}
],
"callback_id": "create booking",
"private_metadata":
"{\"channel_id\":\"C6M2A4690\",\"min_start_time\":\"2020-02-14 04:27:22 UTC\",\"path\":\"bookings/create\",\"room_id\":175128,\"selected_end_time\":null,\"selected_start_time\":null}",
"type": "modal",
"submit": {
"type": "plain_text",
"text": "Book"
},
"title": {
"type": "plain_text",
"text": "Booking room"
}
}
If the user immediately clicks submit, this is my response to the view_submission event:
{
"response_action": "errors",
"errors": {
"start_times": "Please complete this required field"
}
}
Upon receipt of my response, Slack turns off the spinner, leaves the modal open, but does not display an error message. The modal looks exactly the same as when it was first opened via views.open.
Since you posted your question, the functionality of input blocks has changed. Earlier this month, the ability for input blocks to emit block_actions payloads was introduced.
In the Block Kit reference docs for the input block you can see a new dispatch_action parameter. This is a boolean which, when set to true, causes the interactive element inside the input block to emit a block_actions payload when changed.
Therefore, to answer your question more directly, your #3 solution should now be possible without the caveat that you included. Place the static_select inside of an input block, and set dispatch_action to true, like so:
{
"type": "input",
"dispatch_action": true,
"element": {
"type": "static_select",
"placeholder": {
"type": "plain_text",
"text": "Select an item",
"emoji": true
},
"options": [
{
"text": {
"type": "plain_text",
"text": "*this is plain_text text*",
"emoji": true
},
"value": "value-0"
},
{
"text": {
"type": "plain_text",
"text": "*this is plain_text text*",
"emoji": true
},
"value": "value-1"
},
{
"text": {
"type": "plain_text",
"text": "*this is plain_text text*",
"emoji": true
},
"value": "value-2"
}
],
"action_id": "static_select-action"
},
"label": {
"type": "plain_text",
"text": "Label",
"emoji": true
}
}
Upon receiving a view_submission payload, you'll now be able to respond with the correct validation errors and display them to a user. And you can still receive block_actions payloads as needed too.
Set the response's "content_type" to "application/json" before returning response.
If you are using Django as backend then you can do this.
error_object = {
"response_action": "errors",
"errors": {
"start_times": "Please complete this required field"
}
}
return HttpResponse(json.dumps(error_object), content_type="application/json")
===OR===
return JsonResponse(error_object)
don't forget to import JsonReponse if you are using it:
from django.http import JsonResponse

Resources