c# bot is responding differently on one or more channel - c#

i have deployed my bot on azure,which is running on two channel "Skype" and "Web chat " for testing purpose i have integrated both channel in sample html file screen shot with problem description
i have used this code in ConservationUpdate , my problem domain is that webchat greet the user "welcome" whenever user has fresh start of conservation while skype bot does not greet the user
if (message.MembersAdded.Any(o => o.Id == message.Recipient.Id))
{
// var reply = message.CreateReply(Resources.RootDialog_Welcome_Message);
var reply = message.CreateReply("hello welcome to zygote");
ConnectorClient connector = new ConnectorClient(new Uri(message.ServiceUrl));
await connector.Conversations.ReplyToActivityAsync(reply);
}
can anyone explain me two different behavior on same action of bot
....suggestion and advice will be appreciated thanks ......

In web chat whenever you refresh page its create new Userid and not storing any session for user,that's why its showing welcome message. while in skype channel session store for user so its not showing welcome message, and you have to give welcome message at a time of bot registration. As per my knowledge.

Related

Bot Framework v3 SSO with Teams

I am building a chatbot for Teams where the bot needs to connect to graph on behalf of the user. I'm working in C# with BotFramework v3 (for business reasons I cannot move to v4), my BotBuilder package is on version 3.20.1.
The problem: On Webchat, no problem, the bot displays the sign in card, I get redirected to a login page. When logged in, I get the magic number, which I paste into my bot and everything is fine.
On Teams, however, I click on the button, get directed to the login page and once logged in, the tab closes, no magic number and the channel doesn't get anything.
Here is what is configured:
Permissions:
The AAD v2 connection to my Azure app:
My valid domains in the teams manifest:
I've also changed my sign in button to an open url button when in Teams channel as it is a problem mentioned here https://github.com/microsoft/botframework-sdk/issues/2104 (and indeed sign in button doesn't react).
The code:
public override async Task StartAsync(IDialogContext context)
{
var token = await context.GetUserTokenAsync(ConnectionName).ConfigureAwait(false);
var oauthToken = context.Activity.ChannelData.oauthToken?.Value as string;
if (!string.IsNullOrWhiteSpace(oauthToken))
await DoThingsWithToken(context, oauthToken);
else
context.Call(await CreateGetTokenDialog(context), DoThingsWithToken);
}
private async Task<GetTokenDialog> CreateGetTokenDialog(IDialogContext context)
{
return new GetTokenDialog(
ConnectionName,
$"Please sign in to {ConnectionName} to proceed.",
"Sign In",
2,
"Hmm. Something went wrong, let's try again.");
}
private async Task DoThingsWithToken(IDialogContext context, IAwaitable<GetTokenResponse> tokenResponse)
{
var token = (await tokenResponse).Token;
// Do stuff...
}
I've looked online, but couldn't find any doc for SDK v3 anymore, nor people having this exact issue. Could anyone point me if it's a config problem, SDK version problem, or something else? And how to fix it?
[Edit] The documentation followed to configure the Teams SSO: https://learn.microsoft.com/en-us/microsoftteams/platform/sbs-bots-with-sso
Thank you, Best regards.

conversation reference (concurrent dictionary become blank) after IIS pool recycle

We have a bot design in Bot framework-4 using .Net c# sdk. This bot is hosted on IIS and available
on different channel such as Directline, MS Teams etc. We want to send proactive messages to all the user in MS teams to notify them irrespective of if they communicated with bot or not. The Proactive messages will be 1:1 message.
After doing lot of R&D we found that we will be only able to send Proactive message to user only when there conversation reference is present. (let me know if other way is also possible.)
Using below link and Sample to send Proactive message to user:
Proactive Message Sample
Document Referred
We are using cosmos DB container and auto save middleware for bot conversation state and user state management.
Code in ConfigureServices method of Startup.cs file:
var blobDbService = botConfig.Services.FirstOrDefault(s => s.Type == ServiceTypes.BlobStorage) ?? throw new Exception("Please configure your Blob service in your .bot file.");
var BlobDb = blobDbService as BlobStorageService;
var dataStore = new AzureBlobStorage(BlobDb.ConnectionString, BlobDb.Container);
var userState = new UserState(dataStore);
var conversationState = new ConversationState(dataStore);
services.AddSingleton(dataStore);
services.AddSingleton(userState);
services.AddSingleton(conversationState);
services.AddSingleton<ConcurrentDictionary<string, ConversationReference>>();
services.AddSingleton(new BotStateSet(userState, conversationState));
services.AddBot<EnterpriseTiBOT>(options =>
{
// Autosave State Middleware (saves bot state after each turn)
options.Middleware.Add(new AutoSaveStateMiddleware(userState, conversationState));
}
Code to Store Conversation Reference for each user:
private void AddConversationReference(Activity activity)
{
var conversationReference = activity.GetConversationReference();
_conversationReferences.AddOrUpdate(conversationReference.User.Id, conversationReference, (key, newValue) => conversationReference);
}
protected override async Task OnStartAsync(DialogContext dc, CancellationToken cancellationToken = default(CancellationToken))
{
AddConversationReference(dc.Context, cancellationToken);
}
Code in notifyContoller is same as the code from GitHub Sample. There are 2 issues we are facing :
The concurrent dictionary having conversation reference become blank when the IIS pool is recycled and we are not able to send the proactive message to the user, how to store it in Blob storage and access the same in Notify controller?
We want to send proactive message to all the user whether they have communicated with bot or not, any way to achieve this? Tried 3rd approach from this article. But the challenge is, we are not able to send message to user based on User ID or user principle name.
There are multiple ways to store the conversation and user info. You should store these details in more persistent place rather than in memory. Here is a sample app code which stores user detail and along with the conversation Id in cosmos DB at the time of installation of the app. You could look into the implementation part. It can be any storage (blob, SQL).
For sending proactive message, User must have access to your app. You could make your app install for everyone in the tenant from Teams admin portal. Here is a reference documentation for managing the app from admin portal.
You need to have the conversation ID (between a bot and user) for sending a proactive message. And the conversation Id is created when the bot is installed for an user Or in team/group where user is part of.
I want to add comment to the answer but I do not have enough reputation to do so. Just to eleborate point 1 , if you want to ask where can we get and save the conversation refences, you can get it via method named: OnConversationUpdateActivityAsync.
It took me some time to get to this, so I think it is useful to share.
You can get a lot of information eg user ID, channel ID from the activity, here is some sample code:
public class ProactiveBot : ActivityHandler
{
...
...
protected override Task OnConversationUpdateActivityAsync(ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
var conversationReferences = turnContext.Activity.GetConversationReference();
//this is your user's ID
string userId = conversationReference.User.Id;
//this is the bot's ID and will be the same for all activities under same bot.
string botId = conversationReference.Bot.Id;
...
...
...
}
}

how to greet user whenever they interact with chat bot, chat bot should greet the user without waiting for any response from user

i want to greet user without giving any input to chat bot, usually the chat bot interact with user after getting first response from user, i have integrated the Skype bot in my website, what i actually want is whenever user click on Skype Bubble button , the chat bot should greet the user without waiting for any response from user, any suggestion or advice will be appreciated.
screen shot of chat bot
i have used this code in conservationUpdate it did work in emulator but did not work when i deployed it
IConversationUpdateActivity update = message;
var client = new ConnectorClient(new Uri(message.ServiceUrl), new MicrosoftAppCredentials());
if (update.MembersAdded != null && update.MembersAdded.Any())
{
foreach (var newMember in update.MembersAdded)
{
if (newMember.Id != message.Recipient.Id)
{
var reply = message.CreateReply();
reply.Text = $"Hi, Welcome!";
client.Conversations.ReplyToActivityAsync(reply);
}
}
}

Microsoft Bot Framework, How to authenticate user to login in web app

how can I ask user to login to my web from bot, and later when user ask bot something to check first if user is authenticated in my web, if not to redirect to web to login. I've made the login using sign-in card in bot and I pass the activity.user.id, but I don't know how to retrieve the information if the user is logged in or not either.
ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
Activity reply = activity.CreateReply($"Well hello there. What can I do for you today?");
await connector.Conversations.ReplyToActivityAsync(reply);
var id = activity.From.Id;
reply.Attachments = new List<Attachment>();
List<CardAction> cardButtons = new List<CardAction>();
CardAction plButton = new CardAction()
{
Value = $"http://myapp.azurewebsites.net/Account/Login?userid='{id}'",
Type = "signin",
Title = "Connect"
};
cardButtons.Add(plButton);
SigninCard plCard = new SigninCard("You need to authorize me", new List<CardAction>()
{ plButton });
Attachment plAttachment = plCard.ToAttachment();
reply.Attachments.Add(plAttachment);
var replyt = await connector.Conversations.SendToConversationAsync(reply);
You can go through this article https://tsmatz.wordpress.com/2016/09/06/microsoft-bot-framework-bot-with-authentication-and-signin-login/
and sample github code
https://github.com/tsmatsuz/AuthDemoBot
when your web application (web site) is opened in the browser, the page is redirected to the login url.
After the user log-in (login succeeded), your web application might get some authenticated security token. Using Bot Framework api, your web application stores the given token as user state into the bot state service. (At this time, the user id is used for identifier.)
The user can close your web application (web browser).
Finally, when the user inputs some chat in your bot, your bot (in server side) can retrieve the previous token from bot state service. (From now, this bot can call some api using this retrieved token.)
Credit: Tsuyoshi Matsuzaki

Microsoft Bot Framework DirectLine Can't Access Conversations

I am trying to use the Microsoft Bot Framework DirectLine API to read and add messages to existing conversations between other users and my bot. From what I've read I believe this should be possible when using the master-secret but it's just not working for me. I'm using a WebAPI to try and access two of my existing conversations (on Facebook & Skype) as follows:
[HttpPost]
[Route("remind")]
public string Remind()
{
var secret = System.Configuration.ConfigurationManager.AppSettings["secret"];
var uri = new Uri("https://directline.botframework.com/");
var creds = new DirectLineClientCredentials(secret);
DirectLineClient client = new DirectLineClient(uri, creds);
Conversations convs = new Conversations(client);
var conversationIDs = new string[] { "0000000000000000-0000000000000000", "00:0123456789abcdefghijklmnopqrstuvwxyz0123456789-A-_0123456798ABCDEF" }; // Existing Facebook & Skype conversations
// Send a message to each conversation:
foreach (var conversationID in conversationIDs)
{
Message message = new Message(conversationId: conversationID, fromProperty: "My Bot", text: "Hey dude, remember that thing!");
Console.WriteLine(message.Text);
convs.PostMessage(conversationID, message); // FAILS - This executes but doesn't do anything.
}
// Try reading the messages from a conversation (just to test if it's working):
string waterMark = null;
var set = convs.GetMessages(conversationIDs[0], waterMark); // FAILS - This fails with a 404 not found.
waterMark = set.Watermark;
return "Done :-)";
}
It fails silently calling PostMessage() and fails with a 404 for the GetMessages(). I seem to be doing the right thing, the bot is live etc and works very well in Facebook & Skype separately from the DirectLine API. It only works if I create a new conversation using the DirectLine API, I can then access its messages and post new messages to it.
This question sort of helps but doesn't quite tell me what to do to fix it:
Difficulty accessing messages in an existing conversation in Microsoft Bot Framework
Any help would be much appreciated.
Thanks
For security reasons, you can't use DirectLine to spy on messages from another conversation. For the scenario you describe (escalating to a human) there a number of different ways to approach this. One is to have your bot broker conversations between the accounts (i.e. Facebook End User <-> Your Bot <-> Facebook Support Person). Each is talking to the bot, and the bot passes the message through to the other user. (Could also be Facebook User <-> Your Bot <-> Skype User) Your bot would have to store last n messages to provide context. Alternatively, I've seen folks build their own customer support chat interface using direct line that sits on the far side. Hope this helps

Categories

Resources