Starting a conversation with Microsoft bot builder and microsoft bot framework - bots

I tried to have my bot start a conversation with the user but I don't know where in the code I should send the message from. The documentation for starting a convo is here, but it's not super helpful: http://docs.botframework.com/connector/new-conversations/#navtitle. I also tried replying in the HandleSystemMessages (which works with the emulator if I change the message type) but it still won't send the first message.
I'm using Microsoft Bot Connector and C#.
// Idk how to do syntax highlighting in stackoverflow
// This is my code from the MessageController Class
public async Task<Message> Post([FromBody]Message message)
{
if (message.Type == "Message")
{
return message.CreateReplyMessage($"You said:{message.Text}");
}
else
{
return HandleSystemMessage(message);
}
}

I spent a lot of time researching this issue. As a result, I managed to initiate sending a message on behalf of the bot. My example sends a message to a group conversation. The code below - is rough draft but it works:
class Program
{
static void Main(string[] args)
{
var connector = new ConnectorClient(new Uri("https://skype.botframework.com"));
var conversationId = "19:ConversationAccountId#thread.skype";
var conversation = new ConversationAccount(true, conversationId);
var botAccount = new ChannelAccount("28:74a05skypeBotChannelAccountId", "your bot name");
IMessageActivity message = Activity.CreateMessageActivity();
message.From = botAccount;
message.Conversation = conversation;
message.ChannelId = "skype";
message.Text = "some text";
message.Locale = "en-En";
connector.Conversations.SendToConversation((Activity)message);
}
}

Related

How to receive response from Zoho Sign Webhook

I am able to hit my call back function from Zoho Sign webhook. But I am not able to figure out how can I receive the response that Zoho Sign sends to my callback URL. Their documentation: https://www.zoho.com/sign/api/#webhook-management
Below is my sample code that I am using to confirm that callback function is hit. It saves a sample data to DB to confirm it is being hit. But the response I am not being able to catch hold of. This is their help documentation that guides on the same, but that misses a working sample. https://help.zoho.com/portal/en/community/topic/webhooks-for-zoho-sign
[HttpPost]
public ActionResult Callback()
{
using (var context = new ZohoApiTestEntities())
{
var rowDetails = new tblWebhook();
rowDetails.PhoneNo = "7978704767";
//rowDetails.Notes1 = jsonObj.ToString();
context.tblWebhooks.Add(rowDetails);
context.SaveChanges();
}
return new HttpStatusCodeResult(HttpStatusCode.OK);
}
Finally, after a lot of hits and trials, this code worked for me. It's bad that after a lot of follow-up and calls with the Zoho team, I did not receive any help from them for many days.
[HttpPost]
public ActionResult Callback()
{
string rawBody = GetDocumentContents(Request);
dynamic eventObj = JsonConvert.DeserializeObject(rawBody);
using (var context = new ZohoApiTestEntities())
{
var rowDetails = new tblWebhook();
rowDetails.PhoneNo = "*********";
//eventObj comes in JSOn format with two keys, "requests" and "notifications" each containing a JSON object https://www.zoho.com/sign/api/#webhook-management
//you can get your required details like this
string recipientName = eventObj.notifications.performed_by_name.ToString();
rowDetails.Notes1 = recipientName;
context.tblWebhooks.Add(rowDetails);
context.SaveChanges();
}
return new HttpStatusCodeResult(HttpStatusCode.OK);
}
private string GetDocumentContents(HttpRequestBase Request)
{
string documentContents;
using (Stream receiveStream = Request.InputStream)
{
using (StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8))
{
documentContents = readStream.ReadToEnd();
}
}
return documentContents;
}

How to communicate single Bot with two differnet QnA Data sets based on user requrest?

How to communicate Single ChatBot with different QnA data sets(JSON)..
Ex :
QnA1 (JSON file)
QnA2 (JSON file)
and Single Bot application.
when I launch the with site1, Bot will communicate to QnA1 data.
when I launch the with site2, Bot will communicate to QnA2 data.
Here I have only one Bot.
please let me know how to pass KNOWLEDGE_BASE_ID to Bot.
when I launch the with site1, Bot will communicate to QnA1 data. when I launch the with site2, Bot will communicate to QnA2 data.
The UI of BotFramework are based on Dialog, so I can only guess that your site 1 and site 2 means two dialogs and each dialog are built based on QnA.
please let me know how to pass KNOWLEDGE_BASE_ID to Bot.
Then to pass KNOWLEDGE_BASE_ID to your bot, you can use QnAMakerAttribute for your dialog. In .Net SDK for example:
[QnAMakerAttribute("Your-subscription-key", "Your-Qna-KnowledgeBase-ID", "No Answer in Knowledgebase.", 0.5)]
[Serializable]
public class QnADialog1 : QnAMakerDialog
{
}
And if you're using node.js SDK for development, you can pass the id like this:
var recognizer = new builder_cognitiveservices.QnAMakerRecognizer({
knowledgeBaseId: 'Your-Qna-KnowledgeBase-ID', // process.env.QnAKnowledgebaseId,
subscriptionKey: 'Your-Qna-KnowledgeBase-Password'}); //process.env.QnASubscriptionKey});
For more information, you can refer to the Blog samples, there're both C# and node.js version of demos.
If you still want to ask how to use two knowledge-bases in one bot, please leave a comment and tell me which sdk are you using for development, .net or node.js? I will come back and update my answer.
UPDATE:
You can code for example like this:
[Serializable]
public class RootDialog : IDialog<object>
{
private string currentKB;
public Task StartAsync(IDialogContext context)
{
context.Wait(MessageReceivedAsync);
return Task.CompletedTask;
}
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
var activity = await result as Activity;
if (activity.Text == "reset") //handle reset
currentKB = null;
else if (activity.Text == "qna1" || currentKB == "qna1")
{
currentKB = "qna1";
if (activity.Text == "qna1")
await context.PostAsync("this is qna 1");
else
await context.Forward(new Dialogs.QnADialog1(), this.QnAReceivedAsync, activity, CancellationToken.None);
}
else if (activity.Text == "qna2" || currentKB == "qna2")
{
currentKB = "qna2";
if (activity.Text == "qna2")
await context.PostAsync("this is qna 2");
else
await context.Forward(new Dialogs.QnADialog2(), this.QnAReceivedAsync, activity, CancellationToken.None);
}
else
{
var reply = activity.CreateReply("Please choose a knowledge base...");
var heroCard = new HeroCard
{
Title = "Knowledge bases",
Text = "Which one do you want to choose?",
Buttons = new List<CardAction>
{
new CardAction(ActionTypes.ImBack, "QnA base 1", value:"qna1"),
new CardAction(ActionTypes.ImBack, "QnA base 2", value:"qna2")
}
};
Attachment attachment = heroCard.ToAttachment();
reply.Attachments.Add(attachment);
await context.PostAsync(reply);
context.Wait(MessageReceivedAsync);
}
}
public async Task QnAReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
context.Wait(MessageReceivedAsync);
}
}
And in the MessagesController make the RootDialog as the root of dialog stack:
if (activity.Type == ActivityTypes.Message)
{
await Conversation.SendAsync(activity, () => new Dialogs.RootDialog());
}
Finally by QnADialog1 and QnADialog2, I only passed knowledge base ID and key there.

Microsoft Bot Emulator throws "An error occurred while sending the request" when sending a message that expects a Herocard as a response

I am developing a chat bot using QnAMakerServices and an emulator to train the bot.
In my QnaDialog.cs, I override one method from the QnAMakerDialog which is the RespondFromQnAMakerResultAsync.
This is for me to customize the method and create a Herocard as a response. My code goes like this:
namespace IMPBot.Dialogs
{
[Serializable]
public class QnaDialog : QnAMakerDialog
{
public QnaDialog() : base(new QnAMakerService(new QnAMakerAttribute(ConfigurationManager.AppSettings["QnaSubscriptionKey"], ConfigurationManager.AppSettings["QnaKnowledgebaseId"], "Sorry, I couldn't find an answer for that. Please rephrase your question and make sure to ask questions only related to Insights Marketplace.", 0.5)))
{
}
protected override async Task RespondFromQnAMakerResultAsync(IDialogContext context, IMessageActivity message, QnAMakerResults result)
{
// answer is a string
var answer = result.Answers.First().Answer;
if (answer.Contains(';'))
{
Activity reply = ((Activity)context.Activity).CreateReply();
string[] qnaAnswerData = answer.Split(';');
string title = qnaAnswerData[0];
string description = qnaAnswerData[1];
string url = qnaAnswerData[2];
string imageURL = qnaAnswerData[3];
HeroCard card = new HeroCard
{
Title = title,
Subtitle = description,
};
card.Buttons = new List<CardAction>
{
new CardAction(ActionTypes.OpenUrl, "See more", value: url)
};
card.Images = new List<CardImage>
{
new CardImage( url = imageURL)
};
reply.Attachments.Add(card.ToAttachment());
//await context.PostAsync(reply);
}
else
{
await context.PostAsync(answer);
context.Wait(MessageReceivedAsync);
}
}
}
}
However, when I run the Bot Emulator it throws the following error:
Exception: An error occurred while sending the request. [File of type 'text/plain']
And it did not show any card.
On the other hand, the log says,
Warning: The latest bot SDK version is 3.13.0 but the bot is running
SDK version 3.12.2. Consider upgrading the bot to the latest SDK.
Is there any connection with the error to what the log says?
Or did I miss something in the code?

Implementation of push notification using oracle maf

Iam able to register using device token.but I didn't receive message from my server.I have registered my project with GCM and got project Id ,server key.
enter code here
public void onMessage(Event event) {
String msg;
msg = event.getPayload();
System.out.println("#### Message from the Server :" + msg);
String one="";
AdfmfContainerUtilities.invokeContainerJavaScriptFunction(AdfmfJavaUtilities.getFeatureId(), "usercheck", new Object[]{msg});
// Parse the payload of the push notification
HashMap payload = null;
String pushMsg = "No message received";
try
{
payload = (HashMap)JSONBeanSerializationHelper.fromJSON(HashMap.class, msg);
pushMsg = (String)payload.get("alert");
}
catch(Exception e) {
e.printStackTrace();
}
// Write the push message to app scope to display to the user
AdfmfJavaUtilities.setELValue("#{applicationScope.pushMessage}", pushMsg);
}
public void onError(AdfException adfException) {
System.out.println("#### Error: " + adfException.toString());
// Write the error into app scope
AdfmfJavaUtilities.setELValue("#{applicationScope.errorMessage}", adfException.toString());
}
public void onOpen(String token) {
System.out.println("#### Registration token:" + token);
// Clear error in app scope
AdfmfJavaUtilities.setELValue("#{applicationScope.errorMessage}", null);
// Write the token into app scope
AdfmfJavaUtilities.setELValue("#{applicationScope.deviceToken}", token);
}
}
I think this article will help you. I was able to get them done for GCM but not for APN yet.
For registering with Google Cloud Messaging, go to this link, then click on "Get configuration" button.
In the server application, set your device token and sender id properly. The message is sent using these.
Since you got the deviceId from the server then i think the issue is not with the code. Did you enable PushPlugin in maf-application.xml ?

.Net Mobile Service Back-End for Notification Hub

I am currently writing a mobile application with Xamarin for Android and will be adding iOS once my company purchases a Mac so that I can start developing the iOS portion. I am currently trying to write a .Net Mobile Services back-end for Azure Notification Hub that will allow me to register the devices from the back end as well as send push notification to a specific user, and/or all users.
I have followed the Azure documentation all the way through Getting Started With Notification Hub and have successfully performed a single platform push. Moving beyond this example however is where I get stuck. Every example beyond this point completely drops Android support and only focuses on Windows Phone and iOS. I have watched a few Channel 9 videos regarding this subject and again it's all Windows Phone, Windows 8, and iOS based.
Does anyone have an example of a .Net Mobile Service back-end for Azure Notification Hub that will register the device to the notification hub from the back-end? Thank you for your time.
I don't have sample code on GitHub yet, but here's a gist of how to get NotificationHub working on Android.
using Microsoft.ServiceBus.Notifications;
using Newtonsoft.Json;
public class AndroidNotificationHub
{
private readonly NotificationHubClient _hubClient;
public AndroidNotificationHub()
{
const string cn = "YourConnectionStringHere";
const string hubPath = "YourHubPathHere";
_hubClient = NotificationHubClient.CreateClientFromConnectionString(cn, hubPath);
}
public async Task<RegistrationDescription> Register(string platform, string installationId, string registrationId, string userName)
{
// Get registrations for the current installation ID.
var regsForInstId = await _hubClient.GetRegistrationsByTagAsync(installationId, 100);
var updated = false;
var firstRegistration = true;
RegistrationDescription registration = null;
// Check for existing registrations.
foreach (var registrationDescription in regsForInstId)
{
if (firstRegistration)
{
// Update the tags.
registrationDescription.Tags = new HashSet<string>() { installationId, userName };
// We need to handle each platform separately.
switch (platform)
{
case "android":
var gcmReg = registrationDescription as GcmRegistrationDescription;
gcmReg.GcmRegistrationId = registrationId;
registration = await _hubClient.UpdateRegistrationAsync(gcmReg);
break;
}
updated = true;
firstRegistration = false;
}
else
{
// We shouldn't have any extra registrations; delete if we do.
await _hubClient.DeleteRegistrationAsync(registrationDescription);
}
}
// Create a new registration.
if (!updated)
{
switch (platform)
{
case "android":
registration = await _hubClient.CreateGcmNativeRegistrationAsync(registrationId, new[] { installationId, userName });
break;
}
}
return registration;
}
// Basic implementation that sends a notification to Android clients
public async Task<bool> SendNotification(int id, string from, string text, string tag)
{
try
{
var payload = new
{
data = new
{
message = new
{
// these properties can be whatever you want
id,
from,
text,
when = DateTime.UtcNow.ToString("s") + "Z"
}
}
};
var json = JsonConvert.SerializeObject(payload);
await _hubClient.SendGcmNativeNotificationAsync(json, tag);
return true;
}
catch (ArgumentException ex)
{
// This is expected when an APNS registration doesn't exist.
return false;
}
}
public async Task<bool> ClearRegistrations(string userName)
{
// Get registrations for the current installation ID.
var regsForInstId = await _hubClient.GetRegistrationsByTagAsync(userName, 100);
// Check for existing registrations.
foreach (var registrationDescription in regsForInstId)
{
// We shouldn't have any extra registrations; delete if we do.
await _hubClient.DeleteRegistrationAsync(registrationDescription);
}
return true;
}
}
Your Android client will need to call your backend's registration API during startup. I have an MVC action for this.
[HttpPost]
public async Task<ActionResult> Register(string platform, string installationId, string registrationId, string userName)
{
try
{
var hub = new AndroidNotificationHub();
var registration = await hub.Register(platform, installationId, registrationId, userName);
return Json(registration);
}
catch (Exception ex)
{
return Content(ex.ToString());
}
}
Once the mobile client has registered, you can then start sending notifications from your backend, by calling the SendNotification method.
Hope this points you in the right direction.

Resources