I’m designing a bot using Microsoft botframework in C# which will be deployed on messenger.
On of the features I’m trying to include is displaying attractions around the users location. I’ve found this curl request on facebooks development site.
curl -X POST -H "Content-Type: application/json" -d '{
"recipient":{
"id":"USER_ID"
},
"message":{
"text":"Please share your location:",
"quick_replies":[
{
"content_type":"location",
}
]
}
}' "https://graph.facebook.com/v2.6/me/messages?access_token=PAGE_ACCESS_TOKEN"
Appart from this I haven’t found a way to specify when to send a request for the users location as well as a way to store the location so i can use it to do the nearby search.
If anyone could point me in the correct direction I’d be greatly appreciative.
Here’s a nice example of something i’m trying to replicate.
This is an example of what I’m trying to replicate.
[LuisIntent("Stores")]
public async Task Stores(IDialogContext context, LuisResult result)
{
var msg = "location";
if (msg == "location")
{
Lresult = result;
await context.Forward(new FacebookLocationDialog(), ResumeAfter, msg, CancellationToken.None);
}
else
{
await Stores(context, result);
}
}
public async Task ResumeAfter(IDialogContext context, IAwaitable<Place> result)
{
var place = await result;
if (place != default(Place))
{
var geo = (place.Geo as JObject)?.ToObject<GeoCoordinates>();
if (geo != null)
{
var reply = context.MakeMessage();
reply.Attachments.Add(new HeroCard
{
Title = "Open your location in bing maps!",
Buttons = new List<CardAction> {
new CardAction
{
Title = "Your location",
Type = ActionTypes.OpenUrl,
Value = $"https://www.bing.com/maps/?v=2&cp={geo.Latitude}~{geo.Longitude}&lvl=16&dir=0&sty=c&sp=point.{geo.Latitude}_{geo.Longitude}_You%20are%20here&ignoreoptin=1"
}
}
}.ToAttachment());
await context.PostAsync(reply);
}
else
{
await context.PostAsync("No GeoCoordinates!");
}
}
else
{
await context.PostAsync("No location extracted!");
}
context.Wait(Stores);
}
}
[Serializable]
public class FacebookLocationDialog : IDialog<Place>
{
public async Task StartAsync(IDialogContext context)
{
context.Wait(MessageReceivedAsync);
}
public virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
var msg = await argument;
if (msg.ChannelId == "facebook")
{
var reply = context.MakeMessage();
reply.ChannelData = new FacebookMessage
(
text: "Please share your location with me.",
quickReplies: new List<FacebookQuickReply>
{
// If content_type is location, title and payload are not used
// see https://developers.facebook.com/docs/messenger-platform/send-api-reference/quick-replies#fields
// for more information.
new FacebookQuickReply(
contentType: FacebookQuickReply.ContentTypes.Location,
title: default(string),
payload: default(string)
)
}
);
await context.PostAsync(reply);
context.Wait(LocationReceivedAsync);
}
else
{
context.Done(default(Place));
}
}
public virtual async Task LocationReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
var msg = await argument;
var location = msg.Entities?.Where(t => t.Type == "Place").Select(t => t.GetAs<Place>()).FirstOrDefault();
context.Done(location);
}
}
The “context.Wait(Stores);” in the ResumeAfter Task is throwing a “The type arguments for method IDialogStack.Wait cannot be inferred from the usage”.
2
Answers
How to get Location from Facebook Messenger
Have a look to
BotBuilder-Location
project on GitHub: https://github.com/Microsoft/BotBuilder-LocationIt seems that it may be the one used in your sample (based on the sample provided: https://github.com/Microsoft/BotBuilder-Location#address-selection-using-fb-messengers-location-picker-gui-dialog)
You may be interested in particular in the
FacebookNativeLocationRetrieverDialog.cs
:By the way that was also on the
EchoBot
sample provided in theBotBuilder
(https://github.com/Microsoft/BotBuilder/blob/master/CSharp/Samples/EchoBot/EchoLocationDialog.cs)Implementation
Image of the demo:
A location which is sent as a message can be accessed from the message’s Entities list:
And in the controller: