Merge pull request #83 from xbotter/wechat-plugin

update Wechat plugin
This commit is contained in:
Haiping 2023-07-03 20:30:58 -05:00 committed by GitHub
commit 63f3c6f184
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 134 additions and 40 deletions

View file

@ -18,7 +18,7 @@ public partial class AgentService
{
var db = _services.GetRequiredService<AgentDbContext>();
var query = from agent in db.Agent
where agent.OwnerId == _user.Id && agent.Id == id
where agent.Id == id
select agent.ToAgent();
var profile = query.FirstOrDefault();

View file

@ -14,12 +14,12 @@ public class UserIdentity : IUserIdentity
_contextAccessor = contextAccessor;
}
public string Id => _claims.First(x => x.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier").Value;
public string Id => _claims.First(x => x.Type == ClaimTypes.NameIdentifier).Value;
public string Email => _claims.First(x => x.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress").Value;
public string Email => _claims.First(x => x.Type == ClaimTypes.Email).Value;
public string FirstName => _claims.First(x => x.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname").Value;
public string FirstName => _claims.First(x => x.Type == ClaimTypes.GivenName).Value;
public string LastName => _claims.First(x => x.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname").Value;
public string LastName => _claims.First(x => x.Type == ClaimTypes.Surname).Value;
}

View file

@ -21,6 +21,7 @@
<ItemGroup>
<ProjectReference Include="..\..\Infrastructure\BotSharp.Abstraction\BotSharp.Abstraction.csproj" />
<ProjectReference Include="..\..\Infrastructure\BotSharp.Core\BotSharp.Core.csproj" />
</ItemGroup>
<ItemGroup>

View file

@ -1,47 +1,45 @@
# botsharp-channel-weixin
A channel module of BotSharp for Tencent Weixin
# botsharp-plugin-wechat
### How to install through NuGet
```
PM> Install-Package BotSharp.Channel.Weixin
```
A channel plugin of BotSharp for Tencent WeChat
### How to run locally
```
git clone https://github.com/dotnetcore/BotSharp
git clone https://github.com/SciSharp/BotSharp
```
Check app.json to use DialogflowAi
Check appsettings.json to import module
```
{
"version": "0.1.0",
"assemblies": "BotSharp.Core",
"platformModuleName": "DialogflowAi"
}
```
Update channels.weixin.json to set the corresponding KEY
```
{
"weixinChannel": {
"token": "botsharp",
"encodingAESKey": "",
"appId": "",
"agentId": "60bee6f9-ba58-4fe8-8b95-94af69d6fd41"
"PluginLoader": {
"Assemblies": [
...
"BotSharp.Plugin.WeChat"
],
"Plugins": [
...
"WeChatPlugin"
]
}
}
```
F5 run BotSharp.WebHost
Update appsettings.json to set the corresponding KEY
```
{
"WeChat": {
"AgentId": "437bed34-1169-4833-95ce-c24b8b56154a",
"Token": "#{Token}#",
"EncodingAESKey": "#{EncodingAESKey}#",
"WeixinAppId": "#{WeixinAppId}#",
"WeixinAppSecret": "#{WeixinAppSecret}#"
}
}
```
Access http://localhost:3112
Update WeChat WebHook form https://mp.weixin.qq.com/ ,set as `https://{HOST}/WeChatAsync`
Import demo (Spotify.zip) agent located at App_Data
F5 run WebStarter
Train agent (id: 60bee6f9-ba58-4fe8-8b95-94af69d6fd41)
Access http://localhost:5500
Or refer [BotSharp docs](https://botsharp.readthedocs.io) to design your new chatbot.
Setup Wechat webhood from https://mp.weixin.qq.com/.
If you are debugging and developing locally, you can use an intranet penetration tool to receive WeChat message push. It is recommended to use the Dev Tunnels of VS.

View file

@ -0,0 +1,11 @@
using BotSharp.Abstraction.Users;
using BotSharp.Abstraction.Users.Models;
using System.Threading.Tasks;
namespace BotSharp.Plugin.WeChat.Users
{
public interface IWeChatAccountUserService
{
Task<User> GetOrCreateWeChatAccountUserAsync(string appId, string openId);
}
}

View file

@ -0,0 +1,30 @@
using BotSharp.Abstraction.Users;
using BotSharp.Abstraction.Users.Models;
using BotSharp.Core.Repository;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace BotSharp.Plugin.WeChat.Users
{
public class WeChatAccountUserService : IWeChatAccountUserService
{
private readonly IUserService userService;
public WeChatAccountUserService(IUserService userService)
{
this.userService = userService;
}
public async Task<User> GetOrCreateWeChatAccountUserAsync(string appId, string openId)
{
var user = await userService.CreateUser(new User()
{
Email = openId + "@" + appId + ".wechat",
Password = openId
});
return user;
}
}
}

View file

@ -1,10 +1,20 @@
using BotSharp.Abstraction.Agents;
using BotSharp.Abstraction.Conversations;
using BotSharp.Abstraction.Conversations.Models;
using BotSharp.Abstraction.Models;
using BotSharp.Abstraction.Users;
using BotSharp.Abstraction.Users.Models;
using BotSharp.Plugin.WeChat.Users;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Senparc.Weixin.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;
@ -16,6 +26,8 @@ namespace BotSharp.Plugin.WeChat
private readonly Channel<WeChatMessage> _queue;
private readonly IServiceProvider _service;
private readonly ILogger<WeChatBackgroundService> _logger;
private string WeChatAppId => Senparc.Weixin.Config.SenparcWeixinSetting.WeixinAppId;
public static string AgentId { get; set; }
public WeChatBackgroundService(
IServiceProvider service,
@ -30,9 +42,21 @@ namespace BotSharp.Plugin.WeChat
private async Task HandleTextMessageAsync(string openid, string message)
{
var scoped = _service.CreateScope().ServiceProvider;
var user = await GetWeChatAccountUserAsync(openid, scoped);
BindWeChatAccountUser(user, scoped);
var conversationService = scoped.GetRequiredService<IConversationService>();
var result = await conversationService.SendMessage(openid, Guid.Empty.ToString(), new RoleDialogModel
var latestConversationId = (await conversationService.GetConversations()).OrderByDescending(_ => _.CreatedTime).FirstOrDefault()?.Id;
latestConversationId ??= (await conversationService.NewConversation(new Conversation()
{
UserId = openid,
AgentId = AgentId
}))?.Id;
var result = await conversationService.SendMessage(AgentId, latestConversationId, new RoleDialogModel
{
Role = "user",
Text = message,
@ -41,10 +65,34 @@ namespace BotSharp.Plugin.WeChat
await ReplyTextMessageAsync(openid, result);
}
private async Task<User> GetWeChatAccountUserAsync(string openId, IServiceProvider service)
{
var userService = service.GetRequiredService<IWeChatAccountUserService>();
return await userService.GetOrCreateWeChatAccountUserAsync(WeChatAppId, openId);
}
private void BindWeChatAccountUser(User user,IServiceProvider service)
{
var context = service.GetService<IHttpContextAccessor>();
var claims = new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, user.Id)
};
if (!string.IsNullOrWhiteSpace(user.Email))
{
claims.Add(new Claim(ClaimTypes.Email, user.Email));
}
context.HttpContext = new DefaultHttpContext
{
User = new ClaimsPrincipal(new ClaimsIdentity(claims))
};
}
private async Task ReplyTextMessageAsync(string openid, string content)
{
var appId = Senparc.Weixin.Config.SenparcWeixinSetting.WeixinAppId;
await Senparc.Weixin.MP.AdvancedAPIs.CustomApi.SendTextAsync(appId, openid, content);
await Senparc.Weixin.MP.AdvancedAPIs.CustomApi.SendTextAsync(WeChatAppId, openid, content);
}
public async Task EnqueueAsync(WeChatMessage message)

View file

@ -17,6 +17,8 @@ using Senparc.Weixin.Entities;
using Senparc.CO2NET.RegisterServices;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Http;
using BotSharp.Abstraction.Users;
using BotSharp.Plugin.WeChat.Users;
namespace BotSharp.Plugin.WeChat
{
@ -25,6 +27,8 @@ namespace BotSharp.Plugin.WeChat
{
public void RegisterDI(IServiceCollection services, IConfiguration config)
{
services.AddScoped<IWeChatAccountUserService,WeChatAccountUserService> ();
services.AddMemoryCache();
services.Configure<SenparcWeixinSetting>(config.GetSection("WeChat"));
@ -33,9 +37,10 @@ namespace BotSharp.Plugin.WeChat
{
services = services.AddSenparcGlobalServices(config);
}
WeChatBackgroundService.AgentId = config["WeChat:AgentId"];
services.AddSingleton<WeChatBackgroundService>();
services.AddHostedService(s => s.GetRequiredService<WeChatBackgroundService>());
services.TryAddSingleton<IMessageQueue>(s => s.GetRequiredService<WeChatBackgroundService>());

View file

@ -58,6 +58,7 @@
},
"WeChat": {
"AgentId": "437bed34-1169-4833-95ce-c24b8b56154a",
"Token": "#{Token}#",
"EncodingAESKey": "#{EncodingAESKey}#",
"WeixinAppId": "#{WeixinAppId}#",