How to do downloadable file in response from the bot - node.js

Hello there :)
Challenge Skype; Bot Framework; receive downloadable files
I have an issue. My project is to ask something to the bot (using Bot Framework Emulator currently but later I will use Skype) and the bot answers with an attached image/chart.
I can display through the interface the answer and the image. However, the user cannot download this image.
How can I do that ?
There is an option in an AdaptiveCard message to be able to download the attached image thanks to a Button ?
I tried with HeroCard, ThumbnailCard, AdaptiveCard and a simple attachment but it did not solve my problem.
Thanks in advance :)

There's a couple of different ways you can go about this.
Using Cards
First, cards don't allow you to directly download an attachment. At best, they can link you to the image (or other file) you want your user to download. Example json for an Adaptive Card that can do this:
{
"type": "AdaptiveCard",
"body": [
{
"type": "Image",
"selectAction": {
"type": "Action.OpenUrl",
"url": "https://dev.botframework.com/Client/Images/ChatBot-BotFramework.png"
},
"url": "https://dev.botframework.com/Client/Images/ChatBot-BotFramework.png"
},
{
"type": "TextBlock",
"text": "This card's action will open an image"
}
],
"actions": [
{
"type": "Action.OpenUrl",
"title": "Open Image",
"url": "https://dev.botframework.com/Client/Images/ChatBot-BotFramework.png"
}
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.0"
}
And looks like this:
This card displays an image and includes a link for a user to open and download it. Because I added an Action.OpenUrl directly to the image, the user can click the image to open and then download it--the "Open Image" button is just to show another method.
Here's a great website for Adaptive Card Documentation, Schema, and a user-friendly Designer. Note that the Designer doesn't allow you to easily add Actions at this time. You have to manually add them in the JSON portion.
Sending Attachments
You can, however, directly send a message that includes the ability to download files.
You can define an attachment with:
const attachment = {
name: 'PDF',
contentType: 'application/pdf',
contentUrl: 'https://media.readthedocs.org/pdf/microsoftbotframework/latest/microsoftbotframework.pdf',
}
And then send it to the user with:
await step.context.sendActivity({
text: 'Attachment',
attachments: [attachment],
});
Two important notes:
This method works well for sending files. If you use an image, it will display an unclickable image. This means Adaptive Cards would be better for sending downloadable images.
Your code might use something other than step.context. This is for sending it as part of a Waterfall Dialog. You may need some other version of context.sendActivity for your bot.
If you found this answered your question, please mark it as "Answered" and I can clear it off of my support ticket tracker. Otherwise, feel free to comment and I can help you further.

Related

How to send rich text with image using Microsoft Bot Framework

Recently we are building a application which send message through Microsoft BotFramework API
We are using the API as below
https://learn.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-connector-api-reference?view=azure-bot-service-4.0#send-to-conversation
The following API allow us to send text or attachments by passing activities as parameters.
https://learn.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-connector-api-reference?view=azure-bot-service-4.0#activity-object
Everything works well, and on our client side, text and attachments can be received normally as below.
However, recently we have to send rich text which contains text and image info. For example, admin user want to send text and pasted image together to client user.
So we are considering sending text with markdown style with image info like this
text:aaaaa![test](https://ichef.bbci.co.uk/news/976/cpsprodpb/C448/production/_117684205_lotus.jpg "test")
however, client user can only get the info as below. On our client side who use Microsoft Teams App, the image info could not be parsed normally, although image src is a public link.
I know by using attachment image can be send successfully, but what we need is to send a rich text which has ordered text and image as below
Could someone tell me how to find a solution?
I have tested the given markdown syntax in MS Team and it's rendering the correct output. Here through QnA maker I have verified & tested the flow instead of the API that you have given. The issue is not related to Teams APP and look like the markdown has one extra text in the url probably that creating the problem while posting attachment in the MS Teams through request body.
Your Markdown Syntax
Remove the extra "test" content from url.
text:aaaaa![test](https://ichef.bbci.co.uk/news/976/cpsprodpb/C448/production/_117684205_lotus.jpg "test")
Markdown Syntax
text:aaaaa![test](https://ichef.bbci.co.uk/news/976/cpsprodpb/C448/production/_117684205_lotus.jpg)
Output
Note: QnA maker will automatically remove this kind of extra content from the url during the build & test process.
This is possible using Language Generation file in your project and using Adaptive cards. You can find samples here https://adaptivecards.io/samples/
You can design your own adaptive card in your designer https://adaptivecards.io/designer/
and create a json file which you will have to place inside your project Template folder. (or respective folder directory that you have registered)
Once you are done creating and placing the files, follow the code to call the adaptive card
await dc.Context.SendActivityAsync(ActivityFactory.FromObject(_templates.Evaluate("yourlgintent"))).ConfigureAwait(false);
in your filename.lg file
# yourlgintent
[Activity
Attachments = ${ActivityAttachment(json(fromFile('yourfilename.json')), 'adaptiveCard')}
]
OR
You can directly call it in a method
# yourlgintent
[Activity
Attachments = ${ActivityAttachment(json(yourlgintentJson()), 'adaptiveCard')}
]
#yourlgintentJson
- ```
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.3",
"body": [
{
"type": "Container",
"items": [
{
"type": "TextBlock",
"wrap": true,
"text": "As your virtual assistant, I love answering your questions. Having said that, I am learning continuously to expand my knowledge.",
"height": "stretch"
}
],
"spacing": "Large"
}
]
}
And yes, If you are looking to get image from your QnA, then follow the below code
Inside your QnAMaker portal ,
Your Answer. [Image](https://URLTotheimage.com/Images/image.png)
This should give image within your answer.
Finally I found the sollution
https://github.com/microsoft/AdaptiveCards/issues/4121

Update message card in Teams via webhook connector

I have a build machine from which I want to post updates in Microsoft Teams. I created a webhook connector for my channel in Teams and I can send a simple POST request to the webhook url to post a message card in Teams with this json payload:
{
"#type": "MessageCard",
"#context": "http://schema.org/extensions",
"summary": "Build Status",
"sections": [{
"facts": [{
"name": "Status",
"value": "<build status>"
}]
}]
}
Now I want to update the <build status> value as the build progresses and maybe add another fact with download link when the build is finished. Is it possible to update an existing card once it is posted? It seems like a common use case to me, but I was not able to find an answer to it. There are some blogs about updating card as a result of an action, but I don't have or want to have any actions. And obviously I don't want to keep adding cards for the same build process.
Currently update card via web-hook is supported in teams. Could you please Raise a user voice
Sorry, I jumped the gun on that. It appears it isn't supported from webhooks.
https://techcommunity.microsoft.com/t5/microsoft-teams/refresh-cards-not-working-in-teams/m-p/93282

How To Create A Hyperlink For My Dialogflow Chatbot In Responses

I created a chatbot using dialogflow and I added a website link to the response, I have integrated the bot in Telegram and the website link is working perfectly, but on the web demo, it is not. Is it possible that when I integrate the chatbot on a website using Kommunicate, the hyperlink will work?
Kommunicate has a link button template, create a Dialogflow intent using below metadata.
{
"message": "click on the buttons",
"platform":"kommunicate",
"metadata": {
"contentType": "300",
"templateId": "3",
"payload": [{
"type": "link",
"url": "https://www.google.com",
"name": "Go To Google"
},
{
"type": "link",
"url": "https://www.facebook.com",
"name": "Go To Facebook",
"openLinkInNewTab": false
}
]
}
}
The openLinkInNewTab: false to open any link in the same tab. Default value is true, which will open the links in the new tab.
Here is more information about the same.
Also, you can render HTML content as a message and Kommunicate will render the HTML in the UI. Here is the metadata for that.
Sadly the web demo only supports plain text responses, so adding an clickable url within your chatbot for the webdemo isn't possible. Luckily, this is a limitation for web demo, so any other integration that do support URL's in their chats will work as you have seen with Telegram.

How can users upload images to a Slack app?

To provide context i have a Slack bot that allows users to create ads, i am able to use a dialog to fetch the listing title, description and price. What am looking for is a way to allow users to also add images.
The file.upload seems to allow the bot to upload files but what i want is lo be able to allow users to select the files locally and upload them, the bot will then be able to capture this and respond accordingly.
This is what i have so far
#app.route('/new', methods=['POST'])
def new_listing():
# Get payload
api_url = 'https://slack.com/api/dialog.open'
trigger_id = request.form.get('trigger_id')
dialog = {
"callback_id": "marketplace",
"title": "Create a new listing",
"submit_label": "Create",
"notify_on_cancel": True,
"state": "Item",
"elements": [
{
"type": "text",
"label": "Listing Title",
"name": "listing_title"
},
{
"type": "text",
"label": "Listing description",
"name": "listing_description"
},
{
"type": "text",
"label": "Listing Price",
"name": "listing_price"
}
]
}
api_data = {
"token": oauth_token,
"trigger_id": trigger_id,
"dialog": json.dumps(dialog)
}
res = requests.post(api_url, data=api_data)
print(res.content)
return make_response()
#app.route('/message_actions', methods=['POST'])
def message_actions():
user_id = request.form['user']['id']
submission = request.form['submission']
title = submission['listing_title']
description = submission['listing_description']
price = submission['listing_price']
# Add the listing to the database
return make_response()
There is no straight forward approach, since the Slack API (currently) does not offer a filer picker.
However, here are 3 workarounds to address this requirement:
A - Image URLs
Instead of uploading images to Slack directly, users only provide the URL of image hosted on the Internet (e.g. uploading to imgur.com). The image URL can be queried with a simple plain-text input field in your dialog.
If you can expect your users to be tech savvy enough to handle image URLs and uploads to imgur.com (or other image hosters) I think think approach works pretty well.
B - External web page
You redirect users to an external web page of your app that has a file picker. That file picker allows uploading images from the user local machine to your app.
This approach also works well. However users need to switch to a browser (and back to Slack again), so it can break the input flow a bit. It also is a lot more effort to implement, e.g. you need to maintain context between Slack and your web page in a secure way, which can be a challenge.
C - Manual upload to Slack
Users upload images manual to Slack, e.g. in the app channel. You app detects every image upload and asks them to which item of your app to attach it to.
This approach allows you to stay within the Slack eco-system, but might be confusing for users and ensuring correct linking between user uploads and your items might be a challenge.
P.S.: I had the same requirement with one of my Slack apps (Rafflebot) and went with approach A.
You don't show how you are invoking /new (with the trigger id). However - while dialogues and the new modals don't seem to have file pickers - the slack app certainly does. So what I do is start my flow off with a message to my app - THAT message can have files attached. So for example my app looks that the message 'new report' - the user, prior to sending that can attach images - and my app will both get the message AND get a "files" attributes as part of the message event.

how to open url in other browser using adaptive card in microsoft teams bot?

I am using microsoft teams bot framework and I want a adaptive card with a button to open url in popout(other browser)
By using (Actions.openUrl) it Opens a URL in the default browser.
and want it to open in other browser
This is what i have tried and I am using node.js
var card = {
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.0",
"body": [{
"type": "Container",
"items": [{
"type": "TextBlock",
"text": `${session.message.text}`,
"weight": "bolder",
"size": "medium"
}
]
},
{
"type": "Image",
"url": `${bodyData.img}`
},
{
"type": "Container",
"items": [{
"type": "TextBlock",
"text": `${bodyData.calendar}`,
"wrap": true
}]
}
],
"actions": [
{
"type": "Action.openUrl",
"title": "Open in Popout",
"url": `${bodyData.url}`
}
]};
Like paul cheung said, you cannot specify the browser in an openUrl button. Not only that, you cannot specify the URL's "target" in an openUrl button. You can see here that the only thing you can specify is the URL itself. The details of how the URL gets opened are the responsibility of the client and the bot has no control over them.
I think you have a few options.
Option 1
If you really want to open a browser window like a popup, you can try creating a sort of redirect page that the card would link to. When the user clicks the button, your redirect page would open in a new tab of the current browser window and then whatever client-side code you've set up would open the target page in a new window and close the redirect page's tab.
Option 2
The conventional way to do what you're talking about in Teams is to use a task module. Depending on what your URL contains, you might even consider putting a card in your task module instead of a web page.
This action type specifies a URL to launch in the default browser, You can NOT specify the browser at moment. BTW, the default browser is a system level setting(default program) as you know.
Update:
like Kyle said, if task module is your option, Here is a repository you can take a quick look, it includes all necessary code. popout window was triggered in javascript and adaptive card.

Resources