I created a bot (nodejs server) for teams - through bot framework.
I'm trying to send adaptive card that I created through: adaptive cards designer
and I get error :
{"code":"BadArgument","message":"ContentType of an attachment is not set"}
The request body :
{
"type": "message",
"from": {
"id": "xxxxxx"
},
"conversation": {
"id": "xxxxxx"
},
"recipient": {
"id": "xxxxx"
},
"replyToId": "xxxxx",
"text": "some text",
"attachments": [
{
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.2",
"body": [
{
"type": "TextBlock",
"text": "some text"
},
{
"type": "Input.Date",
"separator": true
}
]
}
]
}
I would appreciate help
When adding attachments you'll want to set the contentType and content properties of the attachment object.
https://learn.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-connector-api-reference?view=azure-bot-service-4.0#attachment-object
{
"type": "message",
"from": {
"id": "xxxxxx"
},
"conversation": {
"id": "xxxxxx"
},
"recipient": {
"id": "xxxxx"
},
"replyToId": "xxxxx",
"text": "some text",
"attachments": [
{
"contentType": "application/vnd.microsoft.card.adaptive",
"content": {
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.2",
"body": [
{
"type": "TextBlock",
"text": "some text"
},
{
"type": "Input.Date",
"separator": true
}
]
}
}
]
}
As per the comments above, this is a pro-active message, but using the Bot Framework libraries are a much better approach than trying to call the bot endpoints directly (I wondered if, by "REST", you meant the Bot Framework endpoint or the Graph Api, but in either case the Bot Framework is easier to work with for proactive messages).
Please see specifically this sample for how to do this in Node.
Related
I am trying to post a message to slack using node.js but I got invalid_blocks_format error. In the slack API reference says that: this error occurs because of invalid JSON or wrong Block KIT syntax. I have checked both and everything seems correct. An example of my payload:
{
"channel": "CHANNELID",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Someone* just replied"
}
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": "*Email:*\n<https://example.com/some-url?query-param=value|someone#email.com>"
},
{
"type": "mrkdwn",
"text": "*Campaign:*\n<https://example.com/some-url|Name - Some value>"
},
{
"type": "mrkdwn",
"text": "*Replying To:*\nanotheremail.com"
},
{
"type": "mrkdwn",
"text": "*Assigned To:*\nName Surname"
}
]
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": ">Stop\n>\n>On Aug 8, 2022, at 6:40 PM, Sender <sender#email.com> wrote:\n>\n> Hi Someone,\n>\n>My name is Name from A company.\n>\n>Some content\n> \n>Content continues(https://blog.example.com/ulr?query-param=value) Content. \n>Would you like to book a demo?(https://example.com/url) \n>Let me know and I’ll schedule it.\n>\n>\n>Name Surname\n>Customer Success Manager\n>Company Name\n>\n> \n>\n>\n>\n>CONFIDENTIALITY NOTICE: This message, including any attachments, is the property of Company name Ltd., its affiliates and/or subs"
}
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": "View Recipient"
},
"action_id": "view",
"url": "https://example.com/view?query=asd",
"style": "primary"
},
{
"type": "static_select",
"placeholder": {
"type": "plain_text",
"text": "Set lead status"
},
"action_id": "set-lead-status",
"options": [
{
"text": {
"type": "plain_text",
"text": "Open Lead"
},
"value": "env=prod;recipientID=1234567;leadStatus=Open"
},
{
"text": {
"type": "plain_text",
"text": "Ignore Lead"
},
"value": "env=prod;recipientID=1234567;leadStatus=Ignored"
},
{
"text": {
"type": "plain_text",
"text": "Lost Lead"
},
"value": "env=prod;recipientID=1234567;leadStatus=Lost"
},
{
"text": {
"type": "plain_text",
"text": "Won Lead"
},
"value": "env=prod;recipientID=1234567;leadStatus=Closed"
}
]
},
{
"type": "button",
"text": {
"type": "plain_text",
"text": "Pause Recipient"
},
"action_id": "pause",
"value": "env=prod;recipientID=1234567;"
},
{
"type": "button",
"text": {
"type": "plain_text",
"text": "Unsubscribe"
},
"action_id": "unsubscribe",
"value": "env=prod;recipientID=1234567;",
"style": "danger",
"confirm": {
"title": {
"type": "plain_text",
"text": "Unsubscribe recipient"
},
"text": {
"type": "plain_text",
"text": "Are you sure you want to unsubscribe email#address.com?"
},
"confirm": {
"type": "plain_text",
"text": "Yes"
},
"deny": {
"type": "plain_text",
"text": "Cancel"
}
}
}
]
}
],
"token": "token-value"
}
Also when I try to post this over https://app.slack.com/block-kit-builder, message posted without any problem. What can be the problem and how can I fix it?
Thanks for any help/suggestion.
UPDATE
I figured out the problem but not the solution.
Problem is url's with more than one query parameters. If any text has a link like;
https://example.com/url?param1=value1¶m2=value2
Sources suggested to encode texts but if I do that, slack prints it without decode it. So sent message is not readable. I am still open to suggestions.
Channel should not be inside the block but as a property while using the Slack API.
Exemple using Slack WebClient in node.js:
client.chat.postMessage({
channel: 'channelId',
blocks: 'yourBlock',
});
I was using an old version of slack lib on node and messages contain ampersand (&) caused the problem like links with more than one query parameters. Updating library solved my problem.
I am displaying some data in using adaptive card in BOT emulator,I want to add one comment section there.I tried this way:
{
"type": "Action.ShowCard",
"title": "Comment",
"card": {
"type": "AdaptiveCard",
"body": [
{
"type": "Input.Text",
"id": "test",
"isMultiline": true,
"placeholder": "Enter your comment",
}
],
"actions": [
{
"type": "Action.Submit",
"id":"submit",
"title": "OK",
"data":
{
"test":""
}
}
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json"
}
}
]
but not getting any output when click on OK action.How can we do it?
Next steps in the waterfall dialog flow are not getting called while using Action.Submit in Adaptive cards of Microsoft bot framework SDK V4 (Only when integrated with Microsoft teams)
This is nodejs code in Microsoft framework SDK v4. The problem exists only when integrated with Microsoft teams.
I have tried this in web chat and chat emulator. Action.Submit is calling the next steps on the waterfall dialog flow.
** Bot Code in NodeJS **
async endConversation(stepContext){
console.log("on endConversation")
await stepContext.context.sendActivity({
attachments: [CardFactory.adaptiveCard(RatingCard)]
});
return await stepContext.prompt(TEXT_PROMPT, { prompt: '' });
}
async feedback(stepContext){
console.log("on feedback == "+stepContext.result)
}
** Adaptive Card json **
{
"type": "AdaptiveCard",
"body": [
{
"type": "TextBlock",
"size": "medium",
"weight": "bolder",
"color": "accent",
"text": "Rate your experience!"
},
{
"type": "TextBlock",
"separator": true,
"text": "Please rate your experience! Your feedback is very appreciated and will help improve your experience in the future. ",
"wrap": true
},
{
"type": "ColumnSet",
"spacing": "Medium",
"columns": [
{
"type": "Column",
"selectAction": {
"type": "Action.Submit",
"data": "bad"
},
"items": [
{
"type": "Image",
"horizontalAlignment": "Center",
"url": "https://upload.wikimedia.org/wikipedia/commons/e/ed/StarRatingGraphic.jpg",
"size": "auto"
},
{
"type": "TextBlock",
"horizontalAlignment": "Center",
"text": "Bad"
}
],
"width": "auto"
},
{
"type": "Column",
"selectAction": {
"type": "Action.Submit",
"data": "ok"
},
"items": [
{
"type": "Image",
"horizontalAlignment": "Center",
"url": "https://upload.wikimedia.org/wikipedia/commons/e/ed/StarRatingGraphic.jpg",
"size": "auto"
},
{
"type": "TextBlock",
"horizontalAlignment": "Center",
"text": "Ok"
}
],
"width": "auto"
},
{
"type": "Column",
"selectAction": {
"type": "Action.Submit",
"data": "good"
},
"items": [
{
"type": "Image",
"horizontalAlignment": "Center",
"url": "https://upload.wikimedia.org/wikipedia/commons/e/ed/StarRatingGraphic.jpg",
"size": "auto"
},
{
"type": "TextBlock",
"horizontalAlignment": "Center",
"text": "Good"
}
],
"width": "auto"
}
]
}
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.0"
}
Expected :
async method feedback is the next step on the flow which should be called when the user clicks on a star image in adaptive cards.
Actual :
The next step is not getting called. But its going to onMessage method in ActivityHandler base class.
The Interface Looks like
It looks like Teams isn't handling string submit actions very well. I don't know if this is a new problem or if it always worked that way. Try making your submit action data an object instead of a string:
"selectAction": {
"type": "Action.Submit",
"data": {
"rating": "bad"
}
}
This will generate a textless message, so you'll need to extract the rating from the activity's value property. See this post for instructions on transferring a string from an activity's value property to its text property. See my latest blog post for more information about using Adaptive Cards with the Bot Framework.
EDIT: I've discovered that you can simulate an imBack in Teams using the format in this document:
{
"type": "Action.Submit",
"title": "Click me for imBack",
"data": {
"msteams": {
"type": "imBack",
"value": "Text to reply in chat"
}
}
}
I have a simple adaptive card which works well in the web chat app, this is the card
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{
"type": "Container",
"items": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "Hello!",
"weight": "bolder",
"isSubtle": true
},
{
"type": "TextBlock",
"text": "What can I do for you?",
"wrap": true
}
]
}
]
}
]
}
],
"actions": [
{
"type": "Action.ShowCard",
"title": "Buy",
"card": {
"type": "AdaptiveCard",
"body": [
{
"type": "TextBlock",
"text": "What do you want to buy?",
"weight": "bolder"
}
],
"actions": [
{
"type": "Action.Submit",
"title": "Ticket",
"data": {
"action_button": "buy_ticket"
}
}
]
}
},
{
"type": "Action.ShowCard",
"title": "Check",
"card": {
"type": "AdaptiveCard",
"body": [
{
"type": "TextBlock",
"text": "Nothing to check",
"weight": "bolder"
}
]
}
}
]
}
you can see it in this link http://adaptivecards.io/visualizer/index.html?hostApp=Skype by pasting the code there.
The webchat works fine as you can see here:
but the skype does not even render the Action.Submit button.
It is supposed to work as Skype is supported for this card type.
I've also tested it on Android and it has the same bug.
UPDATE:
How can I create a card like this? this is a skype bot.
Skype does not currently fully support adaptive cards so this behavior is expected. While some features of adaptive cards may work in skype they are not fully supported so strange behaviors such as these are expected. You can find a list of channels that do and do not support adaptive cards here.
In an app, I'm returning messages of type list_card with option key for an intent.
Here is the json of a sample query:
{
"id": "275212ef-cf97-4576-afa7-facfbc044ada",
"timestamp": "2017-07-17T17:36:03.655Z",
"lang": "en",
"result": {
"source": "agent",
"resolvedQuery": "who is Sneha",
"action": "cp.name_search",
"actionIncomplete": false,
"parameters": {
"keyword": "Sneha"
},
"contexts": [
{
"name": "cpname_search-followup",
"parameters": {
"keyword.original": "Sneha",
"keyword": "Sneha"
},
"lifespan": 2
},
{
"name": "cpuid_search-followup",
"parameters": {
"keyword.original": "Sneha",
"keyword": "Sneha"
},
"lifespan": 1
}
],
"metadata": {
"intentId": "86bd1a17-8e9a-4956-b270-5fb4ac952f5f",
"webhookUsed": "true",
"webhookForSlotFillingUsed": "false",
"webhookResponseTime": 135,
"intentName": "cp.name_search"
},
"fulfillment": {
"speech": "Searching...",
"source": "agent",
"messages": [
{
"type": "simple_response",
"platform": "google",
"textToSpeech": "Here are the search results. \nWant anything else?"
},
{
"type": "list_card",
"platform": "google",
"title": "Search results",
"items": [
{
"optionInfo": {
"key": "uid 72",
"synonyms": []
},
"title": "Sneha Vasista",
"description": "Srinivas Institute of Technology",
"image": {
"url": "//www.curlpad.com/assets/img/custom_images/user.png"
}
},
{
"optionInfo": {
"key": "uid 2053",
"synonyms": []
},
"title": "Sneha Bhat",
"description": "Canara Engineering College",
"image": {
"url": "//www.curlpad.com/assets/img/custom_images/user.png"
}
},
{
"optionInfo": {
"key": "uid 2114",
"synonyms": []
},
"title": "Sneha Sajan",
"description": "P.A College of Engineering",
"image": {
"url": "//www.curlpad.com/assets/img/custom_images/user.png"
}
},
{
"optionInfo": {
"key": "uid 2320",
"synonyms": []
},
"title": "Sneha ",
"description": "sdit",
"image": {
"url": "//www.curlpad.com/assets/img/custom_images/user.png"
}
},
{
"optionInfo": {
"key": "uid 2363",
"synonyms": []
},
"title": "Sneha ",
"description": "Srinivas School of Engineering, Mukka",
"image": {
"url": "//www.curlpad.com/assets/img/custom_images/user.png"
}
}
]
},
{
"type": "0",
"speech": "Here are the search results."
}
]
},
"score": 1
},
"status": {
"code": 200,
"errorType": "success"
},
"sessionId": "e6aa9e52-a9e1-481a-adb5-476c5b386e02"
}
Now the problem is, when I tap the list item in AoG simulator, it passes title of item to next query.
But while testing in Api.ai simulator, it behaves well and passes that key to the next query.
What can be the problem here?
Any hints?
If you're using API.AI, then it will appear in the Intent as an actions_intent_OPTION Event.
One good solution is to have the Intent that sends the list with an OutputContext. Then create a particular Fallback Intent with actions_intent_OPTION as Event and your desired action for that Context which should handle both the voice and press responses.
And you will find your option_key at ["originalRequest"]["data"]["inputs"][0]["arguments"][0]["textValue"] instead of parameter.
You can also see the response value in the actions_intent_option context.
What you need to do is set up a fallback intent directly under your current intent.
For example, if you display the list from the default welcome intent, you can do the following.
Click "Add follow-up intent" and choose fallback.
Don't forget to set the action and enable webhook in the fallback intent.
Now, you should be able to retrieve your answer from the fallback intent using the following code.
const param = app.getContextArgument('actions_intent_option','OPTION').value;