I have build a bot using bot framework and integrated into my website through directline. I have also started with creating a admin portal, where admin can have a look at bot analytics.
The requirement i currently have is the admin should be able to find all the users who are currently have chat with the send and push a notification to all those users if needed , if any body has already implemented such scenario please guide me in a proper direction
Thanks.
Proactive Messages is the terminology for 'push notifications' within the Bot Framework space. Some documentation can be found here: https://learn.microsoft.com/en-us/azure/bot-service/dotnet/bot-builder-dotnet-proactive-messages?view=azure-bot-service-3.0
Conceptually, the bot developer persists a ConversationReference somewhere and that is later used to send a Proactive Message
Save conversationReference somewhere (memory cache, database, etc.):
var conversationReference = message.ToConversationReference();
Use that conversation reference to send the user a Proactive Message:
var message = JsonConvert.DeserializeObject<ConversationReference>(conversationReference).GetPostToBotMessage();
var client = new ConnectorClient(new Uri(message.ServiceUrl));
// Create a scope that can be used to work with state from bot framework.
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
{
var botData = scope.Resolve<IBotData>();
await botData.LoadAsync(CancellationToken.None);
// This is our dialog stack.
var task = scope.Resolve<IDialogTask>();
// Create the new dialog and add it to the stack.
var dialog = new WhateverDialog();
// interrupt the stack. This means that we're stopping whatever conversation that is currently happening with the user
// Then adding this stack to run and once it's finished, we will be back to the original conversation
task.Call(dialog.Void<object, IMessageActivity>(), null);
await task.PollAsync(CancellationToken.None);
// Flush the dialog stack back to its state store.
await botData.FlushAsync(CancellationToken.None);
}
Related
I need to update my SQLite database with details sent via an online MVC application which sends a firebase data message to the Xamarin Application linked to the specific user's profile
While the app is in the foreground I can update the database directly with the details contained within the firebase data message.
The problem is that I need the database to be updated whilst the application is in a closed state so when they open it the UI and data states are already built and ready for the user (Without having to then do an HTTP request to get any new information)
Through my workings, I have seen that I must use a Firebase.Jobdispatcher...however I see that it seems to have been deprecated.
public override void OnMessageReceived(RemoteMessage message)
{
base.OnMessageReceived(message);
//Custom message received
if (IsApplicationInTheBackground())
{
//The send notification sends the push notification no problem
SendNotification(message.GetNotification().Body, message.Data);
//I wish to add specific code to write to the SQLite here
} else
{
//Notify within the application using snackbar
var mA = new MessageAndroid();
mA.ShortAlert(message.GetNotification().Body);
var uti = new FindMyDriver(); //Location pin pointing request
uti.ReturnLocationAsync(message.GetNotification().Body);
}
}
In the block where it states "I wish to add specific code .." I would like to save specific details about the loads that have been sent from the MVC application to the linked user App on a registered phone.
I would like to call a specific void to run whilst the App is offline/background.
Is this at all possible with all the controls on services etc lately?
The big issue above was that the FCM didn't actually fire the OnMessageReceived event.
This was due to the FCM being received as a notification and not as a data payload. Once I changed the payload to data it worked 100% allowing me to initialize a foreground service and run from there.
My scenario: Website hosted on the cloud, where each instance creates a subscription to a Service Bus Topic for itself to listen for messages.
My question: How do I programmatically create subscriptions?
Microsoft.Azure.ServiceBus.3.1.0 allows to create a ManagementClient using the ConnectionString.
private async Task CreateTopicSubscriptions()
{
var client = new ManagementClient(ServiceBusConnectionString);
for (int i = 0; i < Subscriptions.Length; i++)
{
if (!await client.SubscriptionExistsAsync(TopicName, Subscriptions[i]))
{
await client.CreateSubscriptionAsync(new SubscriptionDescription(TopicName, Subscriptions[i]));
}
}
}
Original plan for the new Azure Service Bus client was not to include management plane at all and use Azure Active Directory route instead. This has proven to be too problematic, just like you've pointed out. Microsoft messaging team has put together a sample to demonstrate the basic operations.
Note that there's a pending PR to get it working with .NET Core 2.0
Moving forward, it was recognized that developers prefer to access Service Bass using a connection string like they used to over Azure Active Directory option. Management Operations issue is raised to track requests. Current plan is to provide a light weight management library for the .NET Standard client.
For now, the options are either to leverage the old client to create entities or use Microsoft.Azure.Management.ServiceBus (or Fluent) until the management package is available.
Update
Management operations were released as part of 3.1.0 version of the client.
Microsoft.Azure.ServiceBus has been deprecated. The new option is Azure.Messaging.ServiceBus and ManagementClient has been replaced by ServiceBusAdministrationClient.
string connectionString = "<connection_string>";
ServiceBusAdministrationClient client = new ServiceBusAdministrationClient(connectionString);
This new package also supports ManagedIdentity:
string fullyQualifiedNamespace = "yournamespace.servicebus.windows.net";
ServiceBusAdministrationClient client = new ServiceBusAdministrationClient(fullyQualifiedNamespace, new DefaultAzureCredential());
A little example:
var queueExists = await _administrationClient.QueueExistsAsync(queueName);
if(!queueExists)
await _administrationClient.CreateQueueAsync(queueName);
More info here.
I have written a small chat bot using the MS bot framework. I added the Skype and Web channels, and host the bot on Azure with the smallest pay-as-you-go plan. The bot itself is working nicely, both through the web chat and in Skype conversations, both directly (1on1 chat) as well as in groups, when I'm using the Skype desktop app.
Unfortunately, when using the Skype app installed from the Microsoft store, nothing works anymore... Sending a message to the bot (in direct chats and groups) always produces HTTP 500 responses from my bot. Digging into it a bit releaved a simple NullReferenceException being thrown, apparently in the very first line in my dialog handler (see below): The call stack pointed at this line, but the error happened later, see below:
namespace MyBot.Dialogs {
[Serializable]
public class RootDialog: IDialog<IMessageActivity> {
public Task StartAsync(IDialogContext context) {
context.Wait(MessageReceivedAsync);
return Task.CompletedTask;
}
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result) {
// call stack pointed to next line
Activity activity = await result as Activity;
//... some unproblematic stuff
string username = activity.From.Name;
// the next line was the actual problem:
if(username.Contains(" "))
//...
}
}
}
This part of the code, as well as the full MessagesController are taken without changed from the bot framework examples, and as mentioned before, the bot is working fine from web chat and the "regular" Skype desktop app. Even in a group chat with some users on the desktop app and some on the store app, the users with the desktop app can interact with the bot as expected, while the store app users only trigger errors.
The obvious questions here are of course: how (and why) do the two Skype apps differ from a bot perspective, and how can I handle this?
Edit: As it turns out, the Skype desktop app sets the activity.From.Name property to the user's name, while the Skype store app does not. The mean part is, the channelid's for both are the same ("skype", obviously).
Thanks to the comment of #EricDahlvang, I noticed that the error was not the line mentioned above at first, despite the call stack specifically giving this line number. The error happened later, when I tried to work with "activity.From.Name". As it turns out, the regular Skype sets this property to match the users display name, while the Skype store app does not, and returns null.
i've another strange question on BOT Framework and Bot Account.
View image.
Why in simple welcome message bot answer with my custom bot account,
new ChannelAccount(id: "test.id", name: "testBot");
but in
[Microsoft.Bot.Builder.Dialogs] PromptDialog.Choice
the from name and id is different?
My example code is:
public virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var message = await result;
message.From = new ChannelAccount(id: "id-bot", name: "BotName");
PromptDialog.Choice(context, this.OnOptionSelected, new List<string>() { FlightsOption, HotelsOption }, "Are you looking for a flight or a hotel?", "Not a valid option", 3);
}
My questions are:
It's possible custom PromptDialog.Choice From Name and Id?
It's possible set bot account globally (for any reply message)?
Based on your screenshot, it looks like you're running your bot locally from Visual Studio and then using the Bot Channel Emulator tool to test your bot.
The bot's actual name is automatically set for you when you have deployed your bot into a real environment (not your dev), based what you have registered in the Bot Framework Portal. In dev, when using the emulator, it's simply always displayed as "Bot".
So don't bother trying to set your bot's name in code as you are doing now because it's unnecessary. And as a result, there is no need for you to customise PromptDialog.Choice either.
I've made a chat bot using Microsoft Bot Framework which answers a user's questions. When the bot is unable to answer the user's questions, I want to be able to redirect the user question to a customer rep on Skype.
The person on Skype will see the messages posted by the user, and his answers will be sent to the user.
I need some advice on how to achieve this connection (from user<->chatbot<->SkypecustomerRep)
Edit:
I'm toying with the idea of using the commands in http://docs.botframework.com/connector/new-conversations/#navtitle
I figured when the LuisIntent would turn out to be None, I'd message a skype id with:
var connector = new ConnectorClient();
var message = new Message
{
From = new ChannelAccount(channelId: ""),
To = new ChannelAccount() {ChannelId = "Skype", Address = "xyz#abc.com"},
Text = result.Query,
Language = "en"
};
where the email is the Skype id. I'm not able to figure out what should be in the From field (what's the channelId, Address of my bot)
EDIT:
I'm able to pass one message to Skype now, but when the Skype user replies, I observe that the reply is not immediately presented to the bot framework user. In other words, when the user types something into the chat window, he gets a response from the bot (as expected) and the skype user's delayed message.
If you want the customer support representative to have sufficient context (i.e. see more than just the most recent text posted by the user) you are going to need to build your own customer support interface to both record conversations as well as highlight those that need attention from a human. Usually folks do this building their own client with DirectLine or connecting up their existing customer support client (also with DirectLine). The bot then directly passes the support reps replies back to the end users.
Some additional detail can be seen in this previous answer.