How do you implement Azure bot adaptive card? - node.js

My understanding for creating an adaptive card in azure bot is by hard coding it. Is there a better to create an Adaptive card? Because imagine if we have to create 120 cards. We have to hard code files that is like the codes below which is not a good practice. Please help! Thanks
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{
"type": "Image",
"url":"google.image.com",
"size": "small"
}
],
"actions": [
{
"type": "Action.OpenUrl",
"title": "Google",
"url": "google.com"
}
]
}

There's a couple of different ways you can do this. Given the card:
{
"type": "AdaptiveCard",
"body": [
{
"type": "Image",
"id": "img",
"selectAction": {
"type": "Action.OpenUrl",
"title": "Google",
"url": "http://www.google.com"
},
"url": "https://imgplaceholder.com/420x320/ff7f7f/333333/fa-image"
}
],
"actions": [
{
"type": "Action.OpenUrl",
"title": "Google",
"url": "http://www.google.com"
}
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.0"
}
Which will render as:
And given that we're importing it with:
import * as cardJson from './adaptiveCard.json';
And then our code looks something like this:
const card = CardFactory.adaptiveCard(cardJson);
const msg = MessageFactory.text('');
msg.attachments = [card];
await context.sendActivity(msg);
1. Edit the JSON directly
If we use this to change the image:
cardJson.body[0].url = 'https://skillbotbuilder.gallerycdn.vsassets.io/extensions/skillbotbuilder/skillbotbuilder/1.0/1546976085901/Microsoft.VisualStudio.Services.Icons.Default';
we get:
So, you can use your .json as more of a template and then build off of it with javascript. Or:
2. Use a different type of card
Here's a link to other card types
You can then use CardFactory to build the cards.
A Hero Card similar to the above would look something like this:
const hero = CardFactory.heroCard(
null,
CardFactory.images(['https://imgplaceholder.com/420x320/ff7f7f/333333/fa-image']),
CardFactory.actions([{
type: 'Action.OpenUrl',
title: 'Google',
value: 'Google.com'
}])
);

Related

Build a simple ("static") message extension that just returns a button with a link

I need to build an extremely simple message extension, that once it's clicked (in a teams channel conversation, the same way the "gif" button is clicked) just shows a card with a text and a button (and then when enter is pressed, it's just sent).
I'm a beginner when it comes to message extensions development, I used the instructions from this Microsoft page, and now I'm trying to scrap what I don't need from the generated project and just leave / add what I need.
What I have until now (relevant parts)
in the manifest file
"composeExtensions": [
{
"botId": "{botId}",
"commands": [
{
"id": "createCard",
"context": [
"compose"
],
"description": "Command to run action to create a Card from Compose Box",
"title": "Create Card",
"type": "action",
"parameters": [
{
"name": "title",
"title": "Card title",
"description": "Title for the card",
"inputType": "text"
},
{
"name": "subTitle",
"title": "Subtitle",
"description": "Subtitle for the card",
"inputType": "text"
},
{
"name": "text",
"title": "Text",
"description": "Text for the card",
"inputType": "textarea"
}
]
}
],
"messageHandlers": [
{
"type": "link",
"value": {
"domains": [
"*.botframework.com"
]
}
}
]
}
],
in the bot implementation
export class MessageExtensionBot extends TeamsActivityHandler {
public async handleTeamsMessagingExtensionSubmitAction(
context: TurnContext,
action: any
): Promise<any> {
switch (action.commandId) {
case "createCard":
return createCardCommand(context, action);
default:
throw new Error("NotImplemented");
}
}
}
async function createCardCommand(context: TurnContext, action: any): Promise<any> {
const cardJson = {
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{
"type": "TextBlock",
"text": "Click the button below to launch Custom Link"
}
],
"actions": [
{
"type": "Action.OpenUrl",
"title": "Launch Custom Link",
"url": "https://google.com"
}
]
};
const adaptiveCard = CardFactory.adaptiveCard(cardJson);
const attachment = {
contentType: adaptiveCard.contentType,
content: adaptiveCard.content,
preview: adaptiveCard,
};
return {
composeExtension: {
type: "result",
attachmentLayout: "list",
attachments: [attachment],
},
};
}
What I have working: when I click the message extension button, I get prompted to enter those three properties (title, subtitle, text), and only after that, I do get my dummy card displayed.
What I need to do:
eliminate that properties prompt completely, I don't need those. I would only need to directly display the adaptive card, without prompting/waiting any other user action
I tried clearing that section from the manifest, but then the app does not work at all: after redeployment I still get prompted for the properties and I get an error no matter if/what I enter
How can I achieve that ?
what do I need to remove/add to the manifest ?
what method do I need to implement in the bot class ?
Can anybody help somehow ?
Thank you.
So if you want to make something like GIF messaging extension in Teams then you should try template - Custom Stickers App Template (C#). If you refer this template you will also get manifest, which you just need to configure with your bot Id.
Explanation of manifest -
The part that you need in manifest is only simple composeExtensions with command type query
"composeExtensions": [
{
"botId": "<bot id>",
"canUpdateConfiguration": false,
"commands": [
{
"id": "Search",
"type": "query",
"title": "Search",
"description": "",
"initialRun": true,
"parameters": [
{
"name": "keyword",
"title": "keyword",
"description": "search for a sticker"
}
]
}
]
}
]
As I understand from the question you asked, you want something like this https://i.stack.imgur.com/vSJ8y.png
In the bot handler -
You need to implement handleTeamsMessagingExtensionQuery(context, query). Here you can use argument query to search for the image you want to send. If you want to see how to implement, we have a sample ready for it(not in context of GIF but you will get general idea)- Sample link.
In this method you need to return messaging extension response. In it you will return all the results(attachment).
Attachment is consist of preview and content. Preview get renders in the messaging extension. Once you click on the preview, its content get render in compose box.
Refer this on how to return messaging extension response having preview as thumbnail card and content as adaptive card - link
You can use this Adaptive card JSON as you just want to show image in it
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{
"type": "Image",
"url": "https://adaptivecards.io/content/cats/1.png"
}
]
}
Refer this for more image related samples.

Images hosted in share point aren't displaying when posted to team via webhook

I'm trying to migrate some of our reports from slack to Microsoft Teams.
We are currently posting images and csv files to slack from an Azure Function.
Early on I noticed that I cannot post images directly but I can mention their URLs in the card and a preview displays and clicking on it should take me to the actual image.
I started out thinking it would be pretty straightforward. And i went ahead and started with the webhooks option. The only problem is that the it supports only 2 types of cards and i have virtually no control over the image size and other properties. And if I'm to use the Adaptive Card(any other card), then I would have to ditch webhooks and make use of the Graph API, which I've already started.
Then I started noticing that the images disappear, as in they just not get displayed anymore. I believe that this could be an authentication issue between sharepoint/ teams as mentioned in this answer -
Adaptive cards for MS Teams - images displaying in web interface but not desktop application
Teams in browser shows the images but the desktop app doesn't. Also they aren't displaying in my mobile app for teams too.
I have already modified my existing application to send a copy of the image/file (whatever it creates) to a folder inside the sharepoint which is the back end to this channel in teams (used sharepoint API v1)
And I intend to post a thumbnail card with a url to the images/file in Sharepoint.
It would really help if someone could help me with the below :
Anyway to fix the authentication issue between Sharepoint ~ Teams
Alternate options to send an image, if 1. is not feasible.
Please help :)
Edit :
Adding card JSON :
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{
"type": "Container",
"items": [
{
"type": "TextBlock",
"text": "Sample Heading",
"weight": "bolder",
"size": "medium"
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "auto",
"items": [
{
"type": "Image",
"url": "https://upload.wikimedia.org/wikipedia/en/e/ea/FlowersForAlgernon.jpg",
"size": "medium"
}
]
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "Report1",
"text": "Matt Hidinger",
"weight": "bolder",
"wrap": true
},
{
"type": "TextBlock",
"spacing": "none",
"text": "Created {{DATE(2020-02-14T06:08:39Z,SHORT)}}",
"isSubtle": true,
"wrap": true
}
]
}
]
}
]
}
]
}
Adaptive cards are now supported on Incoming webhook. For sending adaptive cards using Incoming Webhooks, You need to follow the Bot Activity Message Type format: format. where you can add the card json to the content field.
Example:
Post Web-hook URL
Request Body:
{
"type": "message",
"attachments": [
{
"contentType": "application/vnd.microsoft.card.adaptive",
"content": {
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{
"type": "Container",
"items": [
{
"type": "TextBlock",
"text": "Sample Heading",
"weight": "bolder",
"size": "medium"
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "auto",
"items": [
{
"type": "Image",
"url": "https://upload.wikimedia.org/wikipedia/en/e/ea/FlowersForAlgernon.jpg",
"size": "medium"
}
]
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "Matt Hidinger",
"weight": "bolder",
"wrap": true
},
{
"type": "TextBlock",
"spacing": "none",
"text": "Created {{DATE(2020-02-14T06:08:39Z,SHORT)}}",
"isSubtle": true,
"wrap": true
}
]
}
]
}
]
}
]
}
}
]
}
Result:

teams adaptive cards with jpg image

I send adaptive card to teams.
When I use png image it works fine, when I use jpg the image is not displayed properly in teams:
Below is the code (I created it using https://adaptivecards.io/designer/, and the image does show up correctly there):
{
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.2",
"body": [
{
"type": "Image",
"url": "https://he.wikipedia.org/wiki/PNG#/media/%D7%A7%D7%95%D7%91%D7%A5:PNG_transparency_demonstration_1.png"
},
{
"type": "ActionSet",
"actions": [
{
"type": "Action.Submit",
"title": "someText",
"data": {
"text": "someText"
}
}
]
}
]
}
What is the problem?

Adaptive card in teams not workig - REST API

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.

carouselSelect in V2 - everything like in doc but it doesn't work

I read a documentation and saw the format of carousel Select (API V2)
"fulfillmentMessages": [
{
"platform": "FACEBOOK",
"carouselSelect": {
"items": [
{
"info": {
"key": "Pologne"
},
"title": "Varsovie",
"description": "Prices are starting from 204",
"image": {
"imageUri": "https://bucketeer-2aea38ff-6103-4b82-a7e2-760c5feac625.s3.amazonaws.com/public/url_z/PL-sky/WARS-sky/1.jpg"
}
},
{
"info": {
"key": "Turquie"
},
"title": "Istanbul",
"description": "Prices are starting from 229",
"image": {
"imageUri": "https://bucketeer-2aea38ff-6103-4b82-a7e2-760c5feac625.s3.amazonaws.com/public/url_z/TR-sky/ISTA-sky/1.jpg"
}
}
]
}
},
{
"platform": "SLACK",
"carouselSelect": {
"items": [
{
"info": {
"key": "Pologne"
},
"title": "Varsovie",
"description": "Prices are starting from 204",
"image": {
"imageUri": "https://bucketeer-2aea38ff-6103-4b82-a7e2-760c5feac625.s3.amazonaws.com/public/url_z/PL-sky/WARS-sky/1.jpg"
}
},
{
"info": {
"key": "Turquie"
},
"title": "Istanbul",
"description": "Prices are starting from 229",
"image": {
"imageUri": "https://bucketeer-2aea38ff-6103-4b82-a7e2-760c5feac625.s3.amazonaws.com/public/url_z/TR-sky/ISTA-sky/1.jpg"
}
}
]
}
}
],
But it, unfortunately doesn't work. Do you have any ideas why? When I use Card object from the doc is worked fine. Also if I add fulfillmentText the bot displays text
You can read more about what types of rich messages Dialogflow supports here in the docs. Dialogflow supports Text, Cards, Images, Suggestion Chips (Quick Replies), and Payloads (Platform-specific responses).
For the content of the custom payload please see the target platform documentation (Google Assistant, Slack, Facebook messenger, etc.)
Actions on Google, however, supports more rich responses, such as carousels, etc.

Resources