I've been playing around with proactive messaging, but I'm not sure how to achieve something like this. I've got a service that messages users products on a daily basis. Using a resumption cookie I call an end point, build a response by setting the .Text property and create the carousel of products by populating the .Attachments property. I want to add buttons to this message to allow a user to stop the alerts, but the only event a CardAction button allows is opening an URL in a web browser. Is there a way of creating a button which can trigger a method, or call a new dialog?
Any help will be greatly appreciated.
You can just use the ImBack or PostBack ActionTypes on the CardAction. Clicking on a button when using any of those, will send a message to the conversation with the Value of the action that will end up arriving to the method you are "waiting" (by doing context.Wait(...));
Then, in that method you can do whatever you want: call a new dialog or any other logic you want to trigger.
In the ContosoFlowers sample you can see how a card with buttons is used in that way.
Related
Problem statement:
I want to call dialogs from MessageController when custom events are sent to the bot.
Setup:
I have a bot build using Microsoft Bot Framework [v3.15.3]
I have a set of custom events that are sent to the bot from external systems to notify the bot adn ask it to perform actions.
[ Example, MarkUserAsOfflineInBackEndStore ShowExternalActionCompletedMessageToUser]
My users connect to the bot using a web portal that has a webchat connect. This also sends custom events to the bot to notify the bot about user actions
[Example UserClickedOnLogoutFromSite , userNavigatedToDifferentPage]
For these events also the bot has to take some actions.
Problem Statement:
From my message controller I have to redirect to different dialog based on different events that come in.
My current setup is below:
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity))
{
if (activity.Type == ActivityTypes.Event)
{
var eventDialog = GetEventDialog(scope, activity);
if (eventDialog != null)
{
await Conversation.SendAsync(activity, () => eventDialog).ConfigureAwait(false);
}
}
else
{
await Conversation.SendAsync(activity, () => scope.Resolve<RootDialog>()).ConfigureAwait(false);
}
}
I want the user ot be able to talk to the bot without error irrespective of the events that are happening. This means that If the bot is waiting for user input using context.Wait(...) the events should not cause unexpected behavior.
I explored calling dialogs using context.Call but could not find a recommended way to get the context reference in messagecontroller.
Looking for suggestion on how to setup the code here.
In my basic scenario,when i send messages one at a time and one event at a time with no waits, it seems to be working correctly. But with complex dialog i get "Sorry my bot code is having an error".
Your issue seems to be based on a common misunderstanding of the MakeRoot delegate in Conversation.SendAsync. The delegate cannot be used to control which dialog the activity is sent to. The reason you have to pass a delegate to begin with instead of just a dialog is because in most cases no new dialog should be constructed. The idea behind Conversation.SendAsync is to send the activity to whatever dialog is on top of the stack. From the documentation:
The MakeRoot factory method is invoked for new conversations only, because existing conversations have the dialog stack and state serialized in the IMessageActivity data.
While I don't know the details of what you're trying to do, I presume you should be able to respond to most events in a way that does not require the use of a dialog. If you're sure you want to send those events to a dialog, you need to keep in mind that there's only one dialog stack and only one dialog on top of the stack, which means you'd need to make sure all of your dialogs are able to handle all possible events gracefully. Please have a look at the documentation to better understand dialogs and dialog flow: https://learn.microsoft.com/en-us/azure/bot-service/dotnet/bot-builder-dotnet-manage-conversation-flow?view=azure-bot-service-3.0
Is it possible to pass data through a markdown link? So for example:
var html = "[link1](test1) [link2](test2)";
var reply = message.CreateReply();
reply.Text = $"Welcome {newMember.Name + html}!";
client.Conversations.ReplyToActivityAsync(reply);
Is there a way to pick up the click event that would let me know which link was clicked?
In bot framework, if you are trying to collect data off of link click (or button of the OpenUrl type). The recommended way is by using a 302 redirect. This is because you generally do not have access to anything from the front end as stuartd is pointing out. For example, if you have a facebook bot how would you capture what the user clicks since nothing is sent to the bot? This is the problem you are running into. You would essentially have to send an activity to the bot when the user clicks a link, but without access to the Facebook front end how do you send that on click?
If you would like to see an example of a 302 redirect in a bot, I have made this example which has both Node and C# versions. This project shows how to do this with a button using the OpenUrl action type but can be applied to a link as well.
Basically, I want to have my bot on different pages using iframes and Bot Framework Web Chat.
Depending on what page the user opens the bot, a different dialog is called.
Without Direct Line, this is as simple as adding a query parameter to api/messages and adjust the controller. But with Direct Line, I can only specify one endpoint in the portal.
I tried to change user.id in the JavaScript BotChat.App call to a different identifier and then select the correct dialog in my MessagesController based on that.
BUT: my custom id doesn't seem to be available as early as the activity "ConversationUpdate" occures where I send my welcome message. I need to send a dialog-specific welcome message though (so I need to navigate there as soon as possible and not only when the user types his first message).
Take a look at the backchannel. In your scenario you can pass a parameter from the Javascript via the back channel to set some value in UserData. Now your parameter will exist in state (in this case the IDataBag UserData) when your user first hits the bot.
Here is a C# sample of a 2-way backchannel
another C# sample using a 1 way backchannel
I am creating an Email Sending Software. So far i am able to open chrome and fill the details of the email (subject,body,attachments and all) but i wanted to know is there any way i can click Send button of G-Mail programmatically too?
Code for filling details in chrome
Process ps = Process.Start("chrome.exe", "https://mail.google.com/mail/u/0/?view=cm&fs=1&tf=1&to=a#gmail.com&bcc=b#gmail.com);
Note I haven't used SmtpClient to send email because it was not fulfilling my customized requirement (sorry cannot disclose the reason).
The way you want this, is not possible. Process.Start opens a new Process. In this case it opens Google Chrome, with the URL you sent with it. This URL contains a querystring containing the subject and the body of the email. This is possible, because Google reads this on the server-side, and puts it in the right fields. There is no way to enter the send button though. This is a POST action, which can not be triggered by a URL.
C# form, does have a WebBrowser class. From here you can access buttons and click them, but I don't think Google will allow this, and most likely send you a captcha. (That is, if you manage to login in the first place.)
I can't help with the simulated button press you're looking for, but I can suggest that you rather try to use the Gmail API to do what you're trying to do:
https://developers.google.com/gmail/api/?hl=en
This would be a more reliable and stable way to send gmail programmatically, and you still don't have to use the smtp object directly.
You should probably use Selenium (WebDriver). It allows you to control browser from c# code, navigates pages, traversing DOM etc..
I am developing a relay chat application , divided into 2 panes.
right pane - > The Chat responses of users (this uses a ASP.NET Multiline Label control placed inside the update panel , so when any user types the responses and submits it is added to this control)
left panes -> the list of users currently online(this uses ASP.NET list control which is also placed inside the update panel).
below this is the textbox for the user to enter text and a send button to post his response.
everything works fine. But when user closes the browser window instead of clicking the log out button. the list on the left pane is not getting refreshed.
It happens properly , when the user logs out.
IS there any way to knock of the users name from the list if the user closes the browser?(even before his session is expired on the server side).?
sorry i couldn expose the screen shot.
can any one suggest an idea along with a sample code snippet.?
thanks
vijay
You can do it the other way around: ping the server from the browser with an ajax call periodically. If no ping received, remove the user.
You can use Javascript to detect when the browser has been closed, and then kick-off an AJAX request back to the server notifying that the user left.