Build-in Facebook Messenger channel.

This commit is contained in:
Oceania2018 2018-11-02 07:53:27 -05:00
parent 221f8134b8
commit 4958da5c21
14 changed files with 307 additions and 1 deletions

View file

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Folder Include="ViewModels\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.1.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BotSharp.Platform.Dialogflow\BotSharp.Platform.Dialogflow.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,114 @@
using BotSharp.Channel.FacebookMessenger.Models;
using BotSharp.Platform.Models;
using EntityFrameworkCore.BootKit;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using RestSharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BotSharp.Channel.FacebookMessenger.Controllers
{
[Route("v1/[controller]")]
public class FacebookMessengerController : ControllerBase
{
[HttpGet("{agentId}")]
public ActionResult Verify([FromRoute] string agentId)
{
var mode = Request.Query.ContainsKey("hub.mode") ? Request.Query["hub.mode"].ToString() : String.Empty;
var token = Request.Query.ContainsKey("hub.verify_token") ? Request.Query["hub.verify_token"].ToString() : String.Empty;
var challenge = Request.Query.ContainsKey("hub.challenge") ? Request.Query["hub.challenge"].ToString() : String.Empty;
if (mode == "subscribe")
{
var dc = new DefaultDataContextLoader().GetDefaultDc();
var config = dc.Table<AgentIntegration>().FirstOrDefault(x => x.AgentId == agentId && x.Platform == "Facebook Messenger");
return config.VerifyToken == token ? Ok(challenge) : Ok(agentId);
}
return BadRequest();
}
[HttpPost("{agentId}")]
public async Task<ActionResult> CallbackAsync([FromRoute] string agentId)
{
WebhookEvent body;
IWebhookMessageBody response = null;
using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
{
var json = await reader.ReadToEndAsync();
body = JsonConvert.DeserializeObject<WebhookEvent>(json);
}
body.Entry.ForEach(entry =>
{
entry.Messaging.ForEach(msg =>
{
// received text message
if (msg.Message.ContainsKey("text"))
{
OnTextMessaged(agentId, new WebhookMessage<WebhookTextMessage>
{
Sender = msg.Sender,
Recipient = msg.Recipient,
Timestamp = msg.Timestamp,
Message = msg.Message.ToObject<WebhookTextMessage>()
});
}
});
});
return Ok();
}
private void OnTextMessaged(string agentId, WebhookMessage<WebhookTextMessage> message)
{
Console.WriteLine($"OnTextMessaged: {message.Message.Text}");
/*var ai = new ApiAi();
var agent = ai.LoadAgent(agentId);
ai.AiConfig = new AIConfiguration(agent.ClientAccessToken, SupportedLanguage.English) { AgentId = agentId };
ai.AiConfig.SessionId = message.Sender.Id;
var aiResponse = ai.TextRequest(new AIRequest { Query = new String[] { message.Message.Text } });
var dc = new DefaultDataContextLoader().GetDefaultDc();
var config = dc.Table<AgentIntegration>().FirstOrDefault(x => x.AgentId == agentId && x.Platform == "Facebook Messenger");
SendTextMessage(config.AccessToken, new WebhookMessage<WebhookTextMessage>
{
Recipient = message.Sender.ToObject<WebhookMessageRecipient>(),
Message = new WebhookTextMessage
{
Text = String.IsNullOrEmpty(aiResponse.Result.Fulfillment.Speech) ? aiResponse.Result.Action : aiResponse.Result.Fulfillment.Speech
}
});*/
}
private void SendTextMessage(string accessToken, WebhookMessage<WebhookTextMessage> body)
{
var client = new RestClient("https://graph.facebook.com");
var rest = new RestRequest("v2.6/me/messages", Method.POST);
string json = JsonConvert.SerializeObject(body,
new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore
});
rest.AddParameter("application/json", json, ParameterType.RequestBody);
rest.AddQueryParameter("access_token", accessToken);
var response = client.Execute(rest);
}
}
}

View file

@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Channel.FacebookMessenger
{
public interface IWebhookMessageBody
{
}
}

View file

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Channel.FacebookMessenger.Models
{
public class WebhookEvent
{
public string Object { get; set; }
public List<WebhookEventEntry> Entry { get; set; }
}
}

View file

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Channel.FacebookMessenger.Models
{
public class WebhookEventEntry
{
public string Id { get; set; }
public long Time { get; set; }
public List<WebhookMessage> Messaging { get; set; }
}
}

View file

@ -0,0 +1,29 @@
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Channel.FacebookMessenger.Models
{
public class WebhookMessage
{
public WebhookMessageSender Sender { get; set; }
public WebhookMessageRecipient Recipient { get; set; }
public long Timestamp { get; set; }
public JObject Message { get; set; }
}
public class WebhookMessage<TWebhookMessage> where TWebhookMessage : IWebhookMessageBody
{
public WebhookMessageSender Sender { get; set; }
public WebhookMessageRecipient Recipient { get; set; }
public long Timestamp { get; set; }
public TWebhookMessage Message { get; set; }
}
}

View file

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Channel.FacebookMessenger.Models
{
public class WebhookMessageQuickReply
{
public String Payload { get; set; }
}
}

View file

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Channel.FacebookMessenger.Models
{
public class WebhookMessageRecipient
{
/// <summary>
/// PAGE_ID
/// </summary>
public String Id { get; set; }
}
}

View file

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Channel.FacebookMessenger.Models
{
public class WebhookMessageSender
{
/// <summary>
/// PSID
/// </summary>
public String Id { get; set; }
}
}

View file

@ -0,0 +1,15 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Channel.FacebookMessenger.Models
{
public class WebhookTextMessage : IWebhookMessageBody
{
public string Mid { get; set; }
public String Text { get; set; }
[JsonProperty("quick_reply")]
public WebhookMessageQuickReply QuickReply { get; set; }
}
}

View file

@ -0,0 +1,22 @@
using BotSharp.Core.Modules;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
namespace BotSharp.Channel.FacebookMessenger
{
public class ModuleInjector : IModule
{
public void ConfigureServices(IServiceCollection services, IConfiguration config)
{
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env/*, IOptions<SenparcSetting> senparcSetting, IOptions<SenparcWeixinSetting> senparcWeixinSetting*/)
{
}
}
}

View file

@ -84,6 +84,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\BotSharp.Channel.FacebookMessenger\BotSharp.Channel.FacebookMessenger.csproj" />
<ProjectReference Include="..\BotSharp.Channel.Weixin\BotSharp.Channel.Weixin.csproj" /> <ProjectReference Include="..\BotSharp.Channel.Weixin\BotSharp.Channel.Weixin.csproj" />
<ProjectReference Include="..\BotSharp.Platform.Dialogflow\BotSharp.Platform.Dialogflow.csproj" /> <ProjectReference Include="..\BotSharp.Platform.Dialogflow\BotSharp.Platform.Dialogflow.csproj" />
</ItemGroup> </ItemGroup>

View file

@ -1,5 +1,5 @@
{ {
"version": "0.1.0", "version": "0.2.0",
"assemblies": "BotSharp.Core", "assemblies": "BotSharp.Core",
"platformModuleName": "DialogflowAi", "platformModuleName": "DialogflowAi",
@ -13,6 +13,10 @@
{ {
"Name": "WeixinChannel", "Name": "WeixinChannel",
"Type": "BotSharp.Channel.Weixin" "Type": "BotSharp.Channel.Weixin"
},
{
"Name": "FacebookMessengerChannel",
"Type": "BotSharp.Channel.FacebookMessenger"
} }
] ]
} }

View file

@ -21,6 +21,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Platform.Dialogflo
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Channel.Weixin", "BotSharp.Channel.Weixin\BotSharp.Channel.Weixin.csproj", "{D93BD270-10A6-4EFB-938D-508FD2EAC1E0}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Channel.Weixin", "BotSharp.Channel.Weixin\BotSharp.Channel.Weixin.csproj", "{D93BD270-10A6-4EFB-938D-508FD2EAC1E0}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Channel.FacebookMessenger", "BotSharp.Channel.FacebookMessenger\BotSharp.Channel.FacebookMessenger.csproj", "{22C52A04-581B-4186-8C04-0CD359FA568A}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
ARTICULATE|Any CPU = ARTICULATE|Any CPU ARTICULATE|Any CPU = ARTICULATE|Any CPU
@ -205,6 +207,30 @@ Global
{D93BD270-10A6-4EFB-938D-508FD2EAC1E0}.Test|Any CPU.Build.0 = Debug|Any CPU {D93BD270-10A6-4EFB-938D-508FD2EAC1E0}.Test|Any CPU.Build.0 = Debug|Any CPU
{D93BD270-10A6-4EFB-938D-508FD2EAC1E0}.Test|x64.ActiveCfg = Debug|Any CPU {D93BD270-10A6-4EFB-938D-508FD2EAC1E0}.Test|x64.ActiveCfg = Debug|Any CPU
{D93BD270-10A6-4EFB-938D-508FD2EAC1E0}.Test|x64.Build.0 = Debug|Any CPU {D93BD270-10A6-4EFB-938D-508FD2EAC1E0}.Test|x64.Build.0 = Debug|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.ARTICULATE|Any CPU.ActiveCfg = Debug|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.ARTICULATE|Any CPU.Build.0 = Debug|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.ARTICULATE|x64.ActiveCfg = Debug|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.ARTICULATE|x64.Build.0 = Debug|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.Debug|x64.ActiveCfg = Debug|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.Debug|x64.Build.0 = Debug|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.DIALOGFLOW|Any CPU.ActiveCfg = Debug|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.DIALOGFLOW|Any CPU.Build.0 = Debug|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.DIALOGFLOW|x64.ActiveCfg = Debug|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.DIALOGFLOW|x64.Build.0 = Debug|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.RASA|Any CPU.ActiveCfg = Release|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.RASA|Any CPU.Build.0 = Release|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.RASA|x64.ActiveCfg = Release|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.RASA|x64.Build.0 = Release|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.Release|Any CPU.Build.0 = Release|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.Release|x64.ActiveCfg = Release|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.Release|x64.Build.0 = Release|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.Test|Any CPU.ActiveCfg = Debug|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.Test|Any CPU.Build.0 = Debug|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.Test|x64.ActiveCfg = Debug|Any CPU
{22C52A04-581B-4186-8C04-0CD359FA568A}.Test|x64.Build.0 = Debug|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE