C# BOT Framework - PromptDialog Bot Account - c#

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.

Related

Teams UpdateActivity events difference when you test in newly created teams

We have a Teams bot that posts messages in MS Teams. The first activity of a new conversation is always an adaptive card and once in a while, we update that with a new card. This worked OK until I made a new Team with this bot.
The update we are trying with UpdateActivityAsync, return NotFound.
After some troubleshooting, I noticed the following:
The new team has a different name: 19:...#thread.tacv2 as opposed to 19:...#thread.skype.
When I use an older team, it works as expected.
When I update the activity with text only (so no adaptive card as attachment) it will always update as expected.
After an update with a text, we are able to update with an adaptive card ONCE. After one update with an adaptive card, any subsequent updates with adaptive cards will return NotFound.
So, as a workaround, I now first update with text and immediately after that I send the update with the card. Which is a bad UI thing (flickering) but it works for now.
We use the old bot framework version 3, which I know is not maintained anymore, but as far as I can find, it should still work (no plans to discontinue operation). Also given the above points (specifically point 4) I would expect it uses the same calls under the hood.
So, this works for older teams, but not for a team with #thread.tacv2
await connector.Conversations.UpdateActivityAsync(
teamsConversationId,
activityId,
(Activity)messageWithCard);
And for teams with #thread.tacv2 we now have to use this
var messageWithText = Activity.CreateMessageActivity();
messageWithText.ChannelId = teamsConversationId;
messageWithText.Id = activityId;
messageWithText.Type = ActivityTypes.Message;
messageWithText.Text = "Updated";
await connector.Conversations.UpdateActivityAsync(
teamsConversationId,
activityId,
(Activity)messageWithText);
await connector.Conversations.UpdateActivityAsync(
teamsConversationId,
activityId,
(Activity)messageWithCard);
The exception does not provide too many details:
Operation returned an invalid status code 'NotFound'
Conversation not found.
Does anyone know how to avoid this change between teams and allow updates of activity with cards?
Also (and this is much less important, but I think it's useful to add) I noticed that sometimes (I've seen it twice now) Teams seems unable to render the adaptive card and displays URIObject XML instead, containing error: cards.unsupported. However, if I exit the client and restart it, it renders fine... I have never seen this so far in the old channels.
Teams client version 1.3.00.362 (64-bit) (no dev mode).
Normal Azure tenant (no preview/trial)
EDIT 11/05/2020 It seems that this also happens on teams with the 'old' name (#thread.skype). So the '#thread.tacv2' seems unrelated.
We weren't able to find logs at the exact timestamps that you provided, but did find logs for the conversation ids on those dates and see 404s with the same minute and seconds in UTC. We assume the time stamps that were provided are represented in a different timezone.
From the logs we are seeing the following pattern:
Bot sends PUT activity with card - 404 returned
Bot sends PUT activity with text - 200 returned
Bot sends PUT activity with card - 200 returned
This looks like the same pattern that you shared in your original post.
There is a scenario that's causing 404s to be returned on PUTS whenever the bot tries to update an existing card message with the exact same card after new messages have been sent to a reply chain
These are the repo steps:
Bot send card to reply chain (can be root message or reply message)
Any user sends a message to the chain
Bot attempts to update message with the exact same card
Is it possible that your bot is encountering this? Is there a way to check whether the card your bot is sending in the first PUT request is the same card that is already in the original message

How to bring the Bot Activity Message from database in Bot Framework?

I am working on a mini-project for self-development on Bot Framework. Need some help here on my requirement. I want the Bot Conversation (Only bot NOT the user) to be fetched from database. I know how to send an activity and get the user response using static text as I have done below.
I have this code:
private static async Task<DialogTurnResult> NameConfirmStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
var promptOptions = new PromptOptions
{
Prompt = MessageFactory.Text($"Hello ! My name is XYZ and I am the Manager of ABC Dept.")
};
return await stepContext.PromptAsync(nameof(TextPrompt), promptOptions, cancellationToken);
}
private static async Task<DialogTurnResult> NameStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
stepContext.Values["intro"] = ((FoundChoice)stepContext.Result);
return await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions { Prompt = MessageFactory.Text("What is your name?") }, cancellationToken);
}
The above code is for the Bot's activity once User says something
However, I was wondering if there is a way we can read the Bot Turn Activity from database?
For example:
Bot: Hello!
Me: Hello
Bot: What is your name?
Me: XYZ
So what I want is the activity Texts of Bot like Hello, What is your name?, ... should come from database (preferably SQL). Is this possible?
I am using Bot Framework v4.0 Emulator for local testing.
The first thing to understand is that bots are just web apps. The question of how to get data into a bot from a database is just the question of how to read data from a database and it has nothing to do with bots. Your question fundamentally cannot be answered since you have not chosen a specific database management system. If your data is in a database that your bot has access to somehow (like with a REST API) then the answer is yes.
Storing data in databases like Cosmos DB is a feature that's already built into the Bot Framework, but that has to do with bot state which is data that helps the bot keep track of specific users and conversations. It sounds like what you want is static data that defines the bot and isn't specific to any particular user or conversation. It's common for C# apps to store strings in resource files, and the Bot Framework has an upcoming language generation feature that you might be interested in, but if you really want to pull strings from a database then go ahead. It's up to you to figure out how to do this since you haven't even decided what DBMS you want to use, but I can tell you that the way you do it won't be bot-specific in any case.
As far as the Bot Framework side of things goes, please review the Azure Bot Service documentation for more information.

Bot Framework Directline Send Notification C#

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);
}

Bot can handle request from Skype desktop app, but not from Skype store app

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.

Connecting a MS bot framework user to someone on Skype

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.

Categories

Resources