Handling user interaction - Click Button message is not like documented - slack-api

I'm experimenting ways to allow users to interact with my app through Slack.
So far, I was able to create a Home App, so that when the user clicks on the app it displays a neat page, with formatted text, images, and some action buttons (built with Block Kit).
What I am not being able to do is handling the user interactions, specifically when the user clicks one of the buttons. I got Slack to invoke my app's API, but the message I receive is absolutely nothing to do with the documentation.
On Slack, I set up Interactivity & Shortcuts, sending all requests to https://slack-interaction-sample.xpto.com/slack/v1/actions.
I then send a message to Slack, using Block Kit, containing a simple button:
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": `*JT*\nBackend Developer # ${ currentTime }`
},
"accessory": {
"type": "image",
"image_url": "https://i.pinimg.com/474x/fb/b5/b6/fbb5b6798f31538f2497e7ceb2b52674.jpg",
"alt_text": "JT"
}
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": "Do Stuff",
"emoji": true
},
"style": "primary",
"value": "doStuff"
}
]
}
]
This message is correctly displayed on Slack. When I click the button, Slacks sends a request to the configured URL and, on my nodejs instance, the following code is executed:
app.post("/slack/v1/actions", function(req, res) {
console.log("**********************************************************");
console.log("/slack/v1/actions");
console.log("**********************************************************");
console.log("Request: %s",req);
res.status(200);
res.json({});
console.log("**********************************************************");
});
According to Slack's documentation (https://api.slack.com/interactivity/handling), I should be getting a payload parameter with something like this:
[
{
"action_id": "action-id-0",
"block_id": "/RXP",
"text": {
"type": "plain_text",
"text": "Ask",
"emoji": true
},
"value": "approve",
"style": "primary",
"type": "button",
"action_ts": "1588254893.249857"
}
]
Instead, what I get is this:
IncomingMessage {
_readableState: [ReadableState],
readable: true,
_events: [Object: null prototype],
_eventsCount: 1,
_maxListeners: undefined,
socket: [Socket],
connection: [Socket],
httpVersionMajor: 1,
httpVersionMinor: 1,
httpVersion: '1.1',
complete: false,
headers: [Object],
rawHeaders: [Array],
trailers: {},
rawTrailers: [],
aborted: false,
upgrade: false,
url: '/slack/v1/actions',
method: 'POST',
statusCode: null,
statusMessage: null,
client: [Socket],
_consuming: false,
_dumped: false,
next: [Function: next],
baseUrl: '',
originalUrl: '/slack/v1/actions',
_parsedUrl: [Url],
params: {},
query: {},
res: [ServerResponse],
body: {},
route: [Route],
[Symbol(kCapture)]: false
}:
ยดยดยด
Any ideas on what I am doing wrong?
Thank you!

Related

How to make multipart/form-data multiples propreties required in swagger

Swagger execution works but it displays "unvalid" for multiple required propreties.
this is the error message:
{"messages":["attribute paths.'/smile_video'(post).requestBody.content.'multipart/form-data'.schema.required is not of type `array`"],"schemaValidationMessages":[{"level":"error","domain":"validation","keyword":"oneOf","message":"instance failed to match exactly one schema (matched 0 out of 2)","schema":{"loadingURI":"#","pointer":"/definitions/Operation/properties/requestBody"},"instance":{"pointer":"/paths/~1smile_video/post/requestBody"}}]}
This is the request body definition:
"requestBody": {
"required": true,
"content": {
"multipart/form-data": {
"schema": {
"type": "object",
"required": [
"video",
"encodings"
],
"properties": {
"video": {
"type": "string",
"format": "binary",
"description": "Upload video file"
},
"encodings": {
"type": "string",
"format": "binary",
"description": "Upload video file "
}
}
}
}
}
}
This is the swagger screenshot
The solution is to disable validation by adding validatorUrl : false
const ui = SwaggerUIBundle({
url: "***",
dom_id: '#swagger-ui',
deepLinking: true,
validatorUrl : false,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
]
});

Time Series Insights not showing sub-object properties of a key/value pair

I have an application that is pushing data into IoT Hub which is being used as a data source for TSI. Below is an example message:
{
"EnqueuedTimeUtc": "2021-06-17T22:00:47.2170000Z",
"Properties": {},
"SystemProperties": {
"connectionDeviceId": "Device1",
"connectionAuthMethod": "{\"scope\":\"device\",\"type\":\"sas\",\"issuer\":\"iothub\",\"acceptingIpFilterRule\":null}",
"connectionDeviceGenerationId": "637425408342887985",
"contentType": "application/json",
"contentEncoding": "utf-8",
"enqueuedTime": "2021-06-17T22:00:47.2170000Z"
},
"Body": {
"topic": {
"namespace": "spBv1.0",
"edgeNodeDescriptor": "Routed Group/E2",
"groupId": "Routed Group",
"edgeNodeId": "E2",
"deviceId": "D2",
"type": "DBIRTH"
},
"payload": {
"timestamp": "2021-06-17T22:00:47.082Z",
"metrics": [{
"name": "Ramp1",
"timestamp": "2021-06-17T22:00:47.082Z",
"dataType": "Int32",
"metaData": {},
"properties": {
"Quality": {
"type": "Int32",
"value": 192
},
"My Property": {
"type": "String",
"value": "{\"\":\"\"}"
}
},
"value": 77
}],
"seq": 1
}
}
}
I found documentation showing that my array of 'metrics' is supported as shown here:
https://learn.microsoft.com/en-us/azure/time-series-insights/concepts-json-flattening-escaping-rules
With this message, I can see 'Ramp1' show up in TSI with a value and timestamp as expected. However, the 'properties' under each metric do not show up. In this example that is 'Quality' and 'My Property'. Is there a way to get this data into TSI with an association to 'Ramp1'?

Slack API invalid_block

I'm building a simple slack bot and I am playing with the checkboxes element.
When I return the following from my API in a JSON response to a slash-command I get an error failed with the error "invalid_blocks", however, when I put this in the block-kit-builder it works perfectly (including "sending to slack" button)
Any ideas why this is failing when I run my slash command - and is it possible to see more detailed error messages from slack?
{
"blocks": [
{
"elements": [
{
"style": "primary",
"text": {
"emoji": true,
"text": "Create new TODO list",
"type": "plain_text"
},
"type": "button",
"value": "value"
},
{
"style": "primary",
"text": {
"emoji": true,
"text": "Help",
"type": "plain_text"
},
"type": "button",
"value": "value"
}
],
"type": "actions"
},
{
"text": {
"text": "Today",
"type": "mrkdwn"
},
"type": "section"
},
{
"elements": [
{
"initial_options": [
{
"text": {
"text": "Get Into the garden",
"type": "mrkdwn"
},
"value": "foo"
}
],
"options": [
{
"text": {
"text": "Get Into the garden",
"type": "mrkdwn"
},
"value": "foo"
}
],
"type": "checkboxes"
},
{
"style": "primary",
"text": {
"emoji": true,
"text": "Add new Task",
"type": "plain_text"
},
"type": "button",
"value": "value"
}
],
"type": "actions"
}
],
"type": "home"
}
I am using the Slack Web API. I was getting the similar error. After a lot of looking around, here's how I solved it.
import json
blocks = [{...}]
payload = {
"blocks": json.dumps(blocks)
}
You will then send this payload.
in the api, the "blocks" parameter need to be string type. Did you convert it to string or you use it as a JSON ?
https://api.slack.com/methods/chat.postMessage
In the Block Kit Builder, the data is a JSON with a blocks key.
In the Slack API, the blocks param is only the list of JSON objects.
blocks = [
{
"text": {
"text": "Its the list of your blocks",
"type": "mrkdwn"
},
"type": "section"
}
]
text = 'Alternative data in text'
client.chat_postMessage(channel=channel_id, blocks=blocks, text=text)
Another cause of this problem seems to be too many blocks being returned. I can't find any documentation about this whatsoever, but personal experience seems to indicate about 20 blocks is the maximum.
An alternative is to return fewer blocks, with paging actions -- paging works well with the "replace" message so that the content being paged through does not result in many separate messages.
It appears that not all valid elements in block kit tool can be posted as a message, despite the fact that message preview works fine in the Block Tool.
In my case, the code failed when I included an input block and passed when i removed it. The input block was generated by the Block Kit tool.
{
"type": "input",
"element": {
"type": "plain_text_input",
"action_id": "plain_text_input-action"
},
"label": {
"type": "plain_text",
"text": "Feedback",
"emoji": true
}
}
The error was
{'ok': False, 'error': 'invalid_blocks'}
Also, although the documentation for python says you need to urlEncode the JSON-based array, there is no example, and it is incorrect. https://api.slack.com/methods/chat.postMessage
You can see on line 29 in the SDK test code below that blocks= takes a regular list of dicts not a string.
https://github.com/slackapi/python-slack-sdk/blob/c9dc6aa0907a72c16cf36aa15e7e80031a9fdce2/integration_tests/samples/basic_usage/sending_a_message.py

Jenkins: Get job name from an item in queue (through API)

I cannot seem to find the job name of an item in the queue through the API. Am I missing something (obvious)?
I created two dummy jobs that require a machine named "build1" that is offline.
When I access http://JENKINS_URL:8080/queue/api/json I get this:
{
"_class": "hudson.model.Queue",
"discoverableItems": [],
"items": [
{
"_class": "hudson.model.Queue$BuildableItem",
"actions": [
{}
],
"blocked": false,
"buildable": true,
"id": 262,
"inQueueSince": 1529331225093,
"params": "",
"stuck": true,
"task": {
"_class": "org.jenkinsci.plugins.workflow.support.steps.ExecutorStepExecution$PlaceholderTask"
},
"url": "queue/item/262/",
"why": "build1 is offline",
"buildableStartMilliseconds": 1529331225094,
"pending": false
},
{
"_class": "hudson.model.Queue$BuildableItem",
"actions": [
{}
],
"blocked": false,
"buildable": true,
"id": 260,
"inQueueSince": 1529331219128,
"params": "",
"stuck": true,
"task": {
"_class": "org.jenkinsci.plugins.workflow.support.steps.ExecutorStepExecution$PlaceholderTask"
},
"url": "queue/item/260/",
"why": "build1 is offline",
"buildableStartMilliseconds": 1529331219128,
"pending": false
}
]
}
And if I access http://JENKINS_URL:8080/queue/item/262/api/json I get nothing more (just the item itself).
However, if I create an item that is put on hold because crontab-created and there's the previous one still in execution, it's no longer a hudson.model.Queue$BuildableItem but a hudson.model.Queue$BlockedItem and there, the task key has a full object with more details... and the name.
Any idea as to where I can find the job name of any item in the queue (and not a specific queue, btw)?
Thanks!

Webhook input not available in scripting step?

I have an internal app that uses a webhook listener and some scripting to manipulate the input data. I'm posting this to it:
curl -X POST -d '{
"assignment_id": 12345,
"updated_custom_fields": [{
"name": "RNVIDAYEBB",
"value": "updated!"
},
{
"name": "QUFTXSIBYA",
"value": "and me too"
}
],
"custom_fields": [{
"id": 981,
"name": "RDEXDPVKRD",
"fields": [
{
"id": 4096,
"name": "RNVIDAYEBB",
"default": "EDJEAJICYW",
"required": true,
"value": "Blah"
},
{
"id": 4097,
"name": "QUFTXSIBYA",
"default": "",
"required": true,
"value": ""
}]
}]
}' "https://hooks.zapier.com/hooks/catch/......"
My script is as follows:
update_custom_fields_by_name_pre_write: function(bundle) {
var updatedFields = _.map(bundle.request.data.custom_fields, function(group) {
return _.map(group.fields, function(field) {
return _.extend(field, _.findWhere(bundle.request.data.updated_custom_fields, { name: field.name} ));
});
});
bundle.request.data = updatedFields;
return bundle.request;
}
I know that the merging logic is good, but it appears that the custom_fields and updated_custom_fields arrays are not present in the bundle.request.data object. Anyone know how to get access to them in the script?
It seems like you should be using update_custom_fields_by_name_catch_hook to capture the incoming static webhook data (instead of _pre_write). If you use that, you can capture the data within bundle.cleaned_request.custom_fields and bundle.cleaned_request.updated_custom_fields.

Resources