Is it possible to launch native apps using Microsoft bot framework? - botframework

I am creating a Cortana skill on the Cortana canvas, I have a button.
I wanted to know if it possible to have an 'imback' type of button to open a webpage.

Ye, for example
var message = context.MakeMessage() as IMessageActivity;
message.ChannelData = JObject.FromObject(new
{
action = new { type = "LaunchUri", uri = "skype:echo123?call" }
});
await context.PostAsync(message);
this code will start a call with echo123 user on skype
Reference: https://learn.microsoft.com/en-us/cortana/tutorials/bot-skills/bot-entity-channel-data

You can supply an openUrl to a card action, or even use ChannelData to send a LaunchUri command, deep linking to an application. (I haven't tried this, but I assume 'http://websitename.com' will launch in the Cortana host platform's default browser.)
activity.ChannelData = new {
action = new { type = "LaunchUri", uri = "http://websitename.com"}
};

Related

Is it possible to scope a Teams Messaging Extension?

I developed a messaging extension for Teams. I want it to only be available for the teams i specifically install the app to. Is that possible and how? I can't find any info on this, but my use-case does not seem to be far-fetched, so i would expect it to be possible.
use-case: Members of a team use an external system to register cases. I want them to be able to search and reference cases within the teams corresponding project site in the external system. I add a tab to the general channel that refers to the project site, and the messaging extension uses the contentUrl of that tab to query the right case list. I don't want the extension to be available outside the teams channels. By default it seems that the extension is available in every chat input option.
Message extensions do no have a scope defined and they are available once you install it in teams. Currently, it is no possible to restrict to show the message extension in one team
I ended up responding with a card that handles the error:
private MessagingExtensionResponse errorResponse(string title, string errorText)
{
MessagingExtensionResult composeExtensionResult = new MessagingExtensionResult
{
Type = "result",
AttachmentLayout = "list",
Attachments = new List<MessagingExtensionAttachment>(),
};
ThumbnailCard h = new ThumbnailCard()
{
Title = title,
Text = errorText,
};
composeExtensionResult.Attachments.Add(h.ToAttachment().ToMessagingExtensionAttachment());
var messagingExtensionResponse = new MessagingExtensionResponse();
messagingExtensionResponse.ComposeExtension = composeExtensionResult;
return messagingExtensionResponse;
}
Although it would be nice to be able to scope the extension, this way i can catch some more invalid usage. For example:
var currentTeam = new TeamDetails();
IList<ChannelInfo> currentTeamChannels = new List<ChannelInfo>();
try
{
currentTeam = await TeamsInfo.GetTeamDetailsAsync(turnContext, turnContext.Activity.TeamsGetTeamInfo().Id, cancellationToken);
currentTeamChannels = await TeamsInfo.GetTeamChannelsAsync(turnContext, turnContext.Activity.TeamsGetTeamInfo().Id, cancellationToken);
}
catch
{
return errorResponse("Permission error", "This app has no permissions to this team / channel. Please add the app to this team / channel.");
}
Got the suggestion from this question: Is it possible for a teams messaging extension to return a plaintext response instead of a card?

Bot Framework Adpative Forms - Submit Action not working

I am trying to create an Adaptive forms using c#. I have installed Microsoft.AdaptiveCards Nuget package with Version 0.5.1 and Bot Builder version is 3.14.1.1.
My card has rendered correctly in Skype channel. But on click of Submit button, Forms input data Json is not passing to the Bot framework Post Activity. Submit Type is "Action.Submit". But this is working in Web chat.
I am using the below code.
var Makedmessage = context.MakeMessage();
AdaptiveCards.AdaptiveCard card = new AdaptiveCards.AdaptiveCard();
Attachment attach = new Attachment();
attach.ContentType = AdaptiveCards.AdaptiveCard.ContentType;
card.Body = new List<CardElement>() { new TextBlock() { Text = "Present a form and submit it back to the originator" }, new TextInput() { Id = "firstName", Placeholder = "What is your first name?" }, new TextInput() { Id = "lastName", Placeholder = "What is your last name?" } };
card.Actions = new List<ActionBase>() { new SubmitAction() { Title = "Action.Submit" } };
attach.Content = card;
Makedmessage.AttachmentLayout = AttachmentLayoutTypes.Carousel;
Makedmessage.Attachments.Add(attach);
await context.PostAsync(Makedmessage, CancellationToken.None);
Also attached the Screenshot.
How can I resolve this?
Adaptive cards are still under development for Skype channel. You will have to look for other alternative feature like multi dialog or formflow by Bot Framework to get the details of the user.

Is it possible to detect when a user opens the chat window on Facebook?

I'm trying to create a chatbot where in order to avoid the user opening the chat window and not knowing the available options, I want to give some basic instructions when the user opens the chat window.
Is there any trigger available when the user opens a chat window? Maybe then I can check, and if there's not an ongoing conversation I could provide basic instructions.
I did some googling and found nothing about this. Is it possible to do something like this, and if not, is there a way to mitigate this problem, and provide the user with information regarding the chatbot capabilities and supported instructions?
Facebook does not allow bots to initiate a conversation, unlike Skype or other platforms.
There are still some tricks you can do :
Go on the Settings of your Facebook page, then Messaging and check "Show a Messenger Greeting" as below, and write your greeting sentence.
The result will look like this :
You can also set a "Get Started" button to trigger an event.
Here's the doc :
"https://developers.facebook.com/docs/messenger-platform/thread-settings/get-started-button"
You can monitor for two event types: ConversationUpdate and ContactRelationUpdate.
The first one (ConversationUpdate) is called when a user is added or removed from the conversation. So, there's a place where you can introduce available options. It will be each type the new conversation has started. So, it may become annoying, you may add a check - do not show it if the user has been using the bot for some time.
The second (ContactRelationUpdate) is called when a user adds or removes the bot to/from the contacts. In general, it is only called once per user action.
Here's the extract from the Bot-Frameworks examples:
For Node.Js
bot.on('conversationUpdate', function (message) {
// Check for group conversations
if (message.address.conversation.isGroup) {
// Send a hello message when bot is added
if (message.membersAdded) {
message.membersAdded.forEach(function (identity) {
if (identity.id === message.address.bot.id) {
var reply = new builder.Message()
.address(message.address)
.text("Hello everyone!");
bot.send(reply);
}
});
}
// Send a goodbye message when bot is removed
if (message.membersRemoved) {
message.membersRemoved.forEach(function (identity) {
if (identity.id === message.address.bot.id) {
var reply = new builder.Message()
.address(message.address)
.text("Goodbye");
bot.send(reply);
}
});
}
}
});
bot.on('contactRelationUpdate', function (message) {
if (message.action === 'add') {
var name = message.user ? message.user.name : null;
var reply = new builder.Message()
.address(message.address)
.text("Hello %s... Thanks for adding me. Say 'hello' to see some great demos.", name || 'there');
bot.send(reply);
} else {
// delete their data
}
});
For C#
private void HandleMessage(Activity message)
{
if (message.Type == ActivityTypes.ConversationUpdate)
{
if (activity.MembersAdded.Any(m => m.Id == activity.Recipient.Id))
{
var connector = new ConnectorClient(new Uri(activity.ServiceUrl));
var response = activity.CreateReply();
response.Text = "Hi! I am Bot. Here's what you can do...";
await connector.Conversations.ReplyToActivityAsync(response);
}
}
else if (message.Type == ActivityTypes.ContactRelationUpdate)
{
if (Activity.AsContactRelationUpdateActivity().Action == ContactRelationUpdateActionTypes.Add)
{
var connector = new ConnectorClient(new Uri(activity.ServiceUrl));
var response = activity.CreateReply();
response.Text = "Hi! I am Bot. Thanks for adding me. Here's what you can do...";
}
}
return null;
}
I think the acid answer is not.
But you can intercept the IConversationUpdateActivity type message to know if the user has added the bot to a conversation. In the C# project template you can find a code block that ask for this message type but do nothing.

How to add an Attachment to Outlook Mail from UWP App programmatically?

I am developing an UWP Application , i want to add a Attachment to outlook from UWP app programmatically
Request you to please me know if any alternatives are there.
Looking forward for your response.
You can use the share contract to send some data to the compliant applications (including outlook). It allows you to share some text and data with any compliant apps.
To activate the sharing, you just need to register to the DataRequested event and show the share UI:
DataTransferManager.GetForCurrentView().DataRequested += OnDataRequested;
DataTransferManager.ShowShareUI();
Then, in the event handler:
private async void OnDataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
var deferral = args.Request.GetDeferral();
try
{
args.Request.Data.Properties.Title = "Share Title"
args.Request.Data.Properties.Description = "Share some data/file";
var file = await ApplicationData.Current.TemporaryFolder.GetFileAsync("myFileToShare.xxx");
args.Request.Data.SetStorageItems(new IStorageItem[] { logFile });
}
catch
{
args.Request.FailWithDisplayText("Unable to share data");
}
finally
{
deferral.Complete();
sender.DataRequested -= OnDataRequested;
}
}
Once done, the system will show the share UI where the user will be able to select the app he want. This app will receive the sent data.
While #Vincent's answer is perfect when you want to use Share Contract, if you want to use Just Email and attach the File, Below is a simple Method that i use in one of my App.
internal async void ShowEmail(string body, string subject, StorageFile attachment)
{
EmailMessage email = new EmailMessage();
email.Subject = subject;
email.Body = body;
var stream = RandomAccessStreamReference.CreateFromFile(attachment);
email.SetBodyStream(EmailMessageBodyKind.Html, stream);
await EmailManager.ShowComposeNewEmailAsync(email);
}
Above method is a strip down of the example from Here

Sending message from bot to a Skype User using Botframework Version 3

Updated
I am developing a Skype bot with 1:1 conversation with Bot Framework.
In that I have a WebHook method which will call from an external service and sends message to my bot, then my bot will send that message to a skype user.
The following code is for v1 in message controller along with api/messages post method
public async Task<Message> Post([FromBody]Message message){}
[Route("~/api/messages/hook")]
[HttpPost]
public async Task<IHttpActionResult> WebHook([FromBody]WebHookMessage message)
{
if (message.Type == "EmotionUpdate")
{
const string fromBotAddress = "<Skype Bot ID here>";
const string toBotAddress = "<Destination Skype name here>";
var text = resolveEmoji(message.Data);
using (var client = new ConnectorClient())
{
var outMessage = new Message
{
To = new ChannelAccount("skype", address: toBotAddress , isBot: false),
From = new ChannelAccount("skype", address: $"8:{fromBotAddress}", isBot: true),
Text = text,
Language = "en",
};
await client.Messages.SendMessageAsync(outMessage);
}
}
return Ok();
}
I will call above WebHook from another service, so that my bot will send messages to the respective skype user.
Can anyone please help me how can I achieve the same in V3 bot framework?
I tried the following but not working
const string fromBotAddress = "Microsoft App ID of my bot";
const string toBotAddress = "skype username";
WebHookMessage processedData = JsonConvert.DeserializeObject<WebHookMessage>(message);
var text = resolveEmoji(processedData.Data);
using (var client = new ConnectorClient(new Uri("https://botname.azurewebsites.net/")
, "Bot Microsoft App Id", "Bot Microsoft App secret",null))
{
var outMessage = new Activity
{
ReplyToId = toBotAddress,
From = new ChannelAccount("skype", $"8:{fromBotAddress}"),
Text = text
};
await client.Conversations.SendToConversationAsync(outMessage);
}
But it is not working, finally what I want to achieve is I want my bot send a message to a user any time how we will send message to a person in skype.
The following code works, but there are some things that are not that obvious that I figured out (tested on Skype channel)
When a user interacts with the bot the user is allocated an id that can only be used from a specific bot..for example: I have multiple bots each using a skype channel. When I send a message from my skype user to bot A the id is different than for bot B. In the previous version of the bot framework I could just send a message to my real skype user id, but not anymore. In a way it simplifies the whole process because you only need the recipient's id and the framework takes care of the rest, so you don't have to specify a sender or bot Id (I guessed all that is linked behind the scenes)
[Route("OutboundMessages/Skype")]
[HttpPost]
public async Task<HttpResponseMessage> SendSkypeMessage(SkypePayload payload)
{
using (var client = new ConnectorClient(new Uri("https://skype.botframework.com")))
{
var conversation = await client.Conversations.CreateDirectConversationAsync(new ChannelAccount(), new ChannelAccount(payload.ToSkypeId));
IMessageActivity message = Activity.CreateMessageActivity();
message.From = new ChannelAccount();
message.Recipient = new ChannelAccount(payload.ToSkypeId);
message.Conversation = new ConversationAccount { Id= conversation.Id };
message.Text = payload.MessageBody;
await client.Conversations.SendToConversationAsync((Activity)message);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
I'm not sure I understand what you're trying to do. If you'd like to answer a message (activity), try something like this:
ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
var reply = activity.createReply(text, "en");
await connector.Conversations.ReplyToActivityAsync(reply);
Activity.createReply switches the From and Recipient fields from the incoming activity. You can also try setting these field manually.
UPDATE
You need to create a ConnectorClient to the Skype Connector Service, not to your bot! So try with the Uri http://skype.botframework.com it might work.
However, I don't think you can message a user on Skype without receiving a message from it in the first place (i.e. your bot needs to be added to the user's contacts). Once you have an incoming message from the user, you can use it the create replies, just as described above.
WebHookMessage processedData = JsonConvert.DeserializeObject<WebHookMessage>(message);
var text = resolveEmoji(processedData.Data);
var client = new ConnectorClient(new Uri(activity.serviceUrl));
var outMessage = activity.createReply(text);
await client.Conversations.SendToConversationAsync(outMessage);
activity is a message received from the given user earlier. In this case, activity.serviceUrl should be http://skype.botframework.com, but generally you should not rely on this.
You can try to create the activity (outMessage) manually; for that, I'd recommend inspecting the From and Recipient fields of a message coming from a Skype user and setting these fields accordingly. However, as mentioned before, your bot needs to be added to the user's contacts, so at this point it will have received a message from the user.

Resources