commit
884314dc2c
|
|
@ -0,0 +1,12 @@
|
|||
using Microsoft.AspNetCore.Builder;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.Abstraction.Plugins
|
||||
{
|
||||
public interface IBotSharpAppPlugin: IBotSharpPlugin
|
||||
{
|
||||
void Configure(IApplicationBuilder app);
|
||||
}
|
||||
}
|
||||
|
|
@ -37,6 +37,8 @@ public static class BotSharpServiceCollectionExtensions
|
|||
throw new ArgumentNullException(nameof(app));
|
||||
}
|
||||
|
||||
app.ApplicationServices.GetRequiredService<PluginLoader>().Configure(app);
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
|
|
@ -74,5 +76,7 @@ public static class BotSharpServiceCollectionExtensions
|
|||
|
||||
var loader = new PluginLoader(services, config, pluginSettings);
|
||||
loader.Load();
|
||||
|
||||
services.AddSingleton(loader);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
|
|
@ -13,7 +14,7 @@ public class PluginLoader
|
|||
private readonly PluginLoaderSettings _settings;
|
||||
private static List<IBotSharpPlugin> _modules = new List<IBotSharpPlugin>();
|
||||
|
||||
public PluginLoader(IServiceCollection services,
|
||||
public PluginLoader(IServiceCollection services,
|
||||
IConfiguration config,
|
||||
PluginLoaderSettings settings)
|
||||
{
|
||||
|
|
@ -59,4 +60,23 @@ public class PluginLoader
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
if(_modules.Count == 0)
|
||||
{
|
||||
Console.WriteLine($"No plugin loaded. Please check whether the Load() method is called.", Color.Yellow);
|
||||
}
|
||||
|
||||
_modules.ForEach(module =>
|
||||
{
|
||||
if (module.GetType().GetInterface(nameof(IBotSharpAppPlugin)) != null)
|
||||
{
|
||||
if (_settings.Plugins.Contains(module.GetType().Name))
|
||||
{
|
||||
(module as IBotSharpAppPlugin).Configure(app);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,12 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Senparc.Weixin.MP.MVC" Version="7.12.5.7" />
|
||||
<ProjectReference Include="..\..\Infrastructure\BotSharp.Abstraction\BotSharp.Abstraction.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Senparc.Weixin.MP.Middleware" Version="0.8.6" />
|
||||
<PackageReference Include="System.Threading.Channels" Version="7.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
53
src/Plugins/BotSharp.Plugin.WeChat/BotSharpMessageHandler.cs
Normal file
53
src/Plugins/BotSharp.Plugin.WeChat/BotSharpMessageHandler.cs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
using BotSharp.Abstraction.Conversations;
|
||||
using BotSharp.Abstraction.Infrastructures.ContentTransmitters;
|
||||
using BotSharp.Abstraction.Models;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Senparc.NeuChar.App.AppStore;
|
||||
using Senparc.NeuChar.Entities;
|
||||
using Senparc.Weixin.MP.Entities;
|
||||
using Senparc.Weixin.MP.Entities.Request;
|
||||
using Senparc.Weixin.MP.MessageContexts;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace BotSharp.Plugin.WeChat
|
||||
{
|
||||
public class BotSharpMessageHandler : Senparc.Weixin.MP.MessageHandlers.MessageHandler<DefaultMpMessageContext>
|
||||
{
|
||||
public static Func<Stream, PostModel, int, IServiceProvider, BotSharpMessageHandler> GenerateMessageHandler = (stream, postModel, maxRecordCount, serviceProvider)
|
||||
=> new BotSharpMessageHandler(stream, postModel, maxRecordCount, false /* 是否只允许处理加密消息,以提高安全性 */, serviceProvider: serviceProvider);
|
||||
|
||||
public BotSharpMessageHandler(Stream inputStream, PostModel postModel, int maxRecordCount = 0, bool onlyAllowEncryptMessage = false, DeveloperInfo developerInfo = null, IServiceProvider serviceProvider = null) : base(inputStream, postModel, maxRecordCount, onlyAllowEncryptMessage, developerInfo, serviceProvider)
|
||||
{
|
||||
}
|
||||
|
||||
public BotSharpMessageHandler(XDocument requestDocument, PostModel postModel, int maxRecordCount = 0, bool onlyAllowEncryptMessage = false, DeveloperInfo developerInfo = null, IServiceProvider serviceProvider = null) : base(requestDocument, postModel, maxRecordCount, onlyAllowEncryptMessage, developerInfo, serviceProvider)
|
||||
{
|
||||
}
|
||||
|
||||
public BotSharpMessageHandler(RequestMessageBase requestMessageBase, PostModel postModel, int maxRecordCount = 0, bool onlyAllowEncryptMessage = false, DeveloperInfo developerInfo = null, IServiceProvider serviceProvider = null) : base(requestMessageBase, postModel, maxRecordCount, onlyAllowEncryptMessage, developerInfo, serviceProvider)
|
||||
{
|
||||
}
|
||||
|
||||
public override IResponseMessageBase DefaultResponseMessage(IRequestMessageBase requestMessage)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public async override Task<IResponseMessageBase> OnTextRequestAsync(RequestMessageText requestMessage)
|
||||
{
|
||||
var messageQueue = ServiceProvider.GetRequiredService<IMessageQueue>();
|
||||
await messageQueue.EnqueueAsync(new WeChatMessage()
|
||||
{
|
||||
OpenId = OpenId,
|
||||
Message = requestMessage.Content,
|
||||
Type = "text"
|
||||
});
|
||||
return await base.OnTextRequestAsync(requestMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
12
src/Plugins/BotSharp.Plugin.WeChat/IMessageQueue.cs
Normal file
12
src/Plugins/BotSharp.Plugin.WeChat/IMessageQueue.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BotSharp.Plugin.WeChat
|
||||
{
|
||||
public interface IMessageQueue
|
||||
{
|
||||
Task EnqueueAsync(WeChatMessage message);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
using BotSharp.Abstraction.Conversations;
|
||||
using BotSharp.Abstraction.Infrastructures.ContentTransmitters;
|
||||
using BotSharp.Abstraction.Models;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Channels;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BotSharp.Plugin.WeChat
|
||||
{
|
||||
public class WeChatBackgroundService : BackgroundService, IMessageQueue
|
||||
{
|
||||
private readonly Channel<WeChatMessage> _queue;
|
||||
private readonly IServiceProvider _service;
|
||||
private readonly ILogger<WeChatBackgroundService> _logger;
|
||||
|
||||
public WeChatBackgroundService(
|
||||
IServiceProvider service,
|
||||
ILogger<WeChatBackgroundService> logger)
|
||||
{
|
||||
|
||||
this._service = service;
|
||||
this._logger = logger;
|
||||
this._queue = Channel.CreateUnbounded<WeChatMessage>();
|
||||
}
|
||||
|
||||
private async Task HandleTextMessageAsync(string openid, string message)
|
||||
{
|
||||
var scoped = _service.CreateScope().ServiceProvider;
|
||||
var conversationService = scoped.GetRequiredService<IConversationService>();
|
||||
var contentTransfer = scoped.GetRequiredService<IContentTransfer>();
|
||||
|
||||
var conversations = conversationService.GetDialogHistory(openid);
|
||||
conversations.Add(new RoleDialogModel
|
||||
{
|
||||
Role = "User",
|
||||
Text = message,
|
||||
});
|
||||
|
||||
var container = new ContentContainer
|
||||
{
|
||||
Conversations = conversations
|
||||
};
|
||||
|
||||
var result = await contentTransfer.Transport(container);
|
||||
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
var output = container.Output.Text.Trim();
|
||||
await ReplyTextMessageAsync(openid, output);
|
||||
conversationService.AddDialog(new RoleDialogModel()
|
||||
{
|
||||
Role = "Assistant",
|
||||
Text = output,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public async Task EnqueueAsync(WeChatMessage message)
|
||||
{
|
||||
await _queue.Writer.WriteAsync(message);
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
var message = await _queue.Reader.ReadAsync(cancellationToken);
|
||||
await HandleTextMessageAsync(message.OpenId, message.Message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error occurred Handle Message");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
src/Plugins/BotSharp.Plugin.WeChat/WeChatMessage.cs
Normal file
13
src/Plugins/BotSharp.Plugin.WeChat/WeChatMessage.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BotSharp.Plugin.WeChat
|
||||
{
|
||||
public class WeChatMessage
|
||||
{
|
||||
public string OpenId { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Message { get; set; }
|
||||
}
|
||||
}
|
||||
66
src/Plugins/BotSharp.Plugin.WeChat/WeChatPlugin.cs
Normal file
66
src/Plugins/BotSharp.Plugin.WeChat/WeChatPlugin.cs
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
using BotSharp.Abstraction.Plugins;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Senparc.CO2NET.AspNet;
|
||||
using Senparc.CO2NET;
|
||||
using Senparc.Weixin.RegisterServices;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Senparc.Weixin;
|
||||
using Senparc.Weixin.MP;
|
||||
using Senparc.Weixin.MP.MessageHandlers.Middleware;
|
||||
using Senparc.Weixin.Entities;
|
||||
using Senparc.CO2NET.RegisterServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace BotSharp.Plugin.WeChat
|
||||
{
|
||||
|
||||
public class WeChatPlugin : IBotSharpAppPlugin
|
||||
{
|
||||
public void RegisterDI(IServiceCollection services, IConfiguration config)
|
||||
{
|
||||
services.AddMemoryCache();
|
||||
|
||||
services.Configure<SenparcWeixinSetting>(config.GetSection("WeChat"));
|
||||
|
||||
if (!Senparc.CO2NET.RegisterServices.RegisterServiceExtension.SenparcGlobalServicesRegistered)
|
||||
{
|
||||
services = services.AddSenparcGlobalServices(config);
|
||||
}
|
||||
|
||||
services.AddSingleton<WeChatBackgroundService>();
|
||||
|
||||
services.AddHostedService(s => s.GetRequiredService<WeChatBackgroundService>());
|
||||
|
||||
services.TryAddSingleton<IMessageQueue>(s => s.GetRequiredService<WeChatBackgroundService>());
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
var env = app.ApplicationServices.GetRequiredService<IHostEnvironment>();
|
||||
var logger = app.ApplicationServices.GetRequiredService<ILogger<WeChatPlugin>>();
|
||||
|
||||
var register = app.UseSenparcGlobal(env);
|
||||
register.UseSenparcWeixin(null, (svc, settings) =>
|
||||
{
|
||||
svc.RegisterMpAccount(settings, "WeChat");
|
||||
}, app.ApplicationServices);
|
||||
|
||||
app.UseMessageHandlerForMp("/WeChatAsync", BotSharpMessageHandler.GenerateMessageHandler, options =>
|
||||
{
|
||||
options.AccountSettingFunc = context => Senparc.Weixin.Config.SenparcWeixinSetting;
|
||||
options.EnbleResponseLog = false;
|
||||
options.EnableRequestLog = false;
|
||||
});
|
||||
|
||||
logger.LogInformation("WeChat Message Handler is running on /WeChatAsync.");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -42,6 +42,7 @@
|
|||
<ProjectReference Include="..\Plugins\BotSharp.Plugin.MetaAI\BotSharp.Plugin.MetaAI.csproj" />
|
||||
<ProjectReference Include="..\Plugins\BotSharp.Plugin.PaddleSharp\BotSharp.Plugin.PaddleSharp.csproj" />
|
||||
<ProjectReference Include="..\Plugins\BotSharp.Plugin.Qdrant\BotSharp.Plugin.Qdrant.csproj" />
|
||||
<ProjectReference Include="..\Plugins\BotSharp.Plugin.WeChat\BotSharp.Plugin.WeChat.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -60,6 +60,13 @@
|
|||
"ApiKey": ""
|
||||
},
|
||||
|
||||
"WeChat": {
|
||||
"Token": "#{Token}#",
|
||||
"EncodingAESKey": "#{EncodingAESKey}#",
|
||||
"WeixinAppId": "#{WeixinAppId}#",
|
||||
"WeixinAppSecret": "#{WeixinAppSecret}#"
|
||||
},
|
||||
|
||||
"KnowledgeBase": {
|
||||
"VectorDb": "MemVecDbProvider"
|
||||
},
|
||||
|
|
@ -70,7 +77,8 @@
|
|||
"BotSharp.Plugin.AzureOpenAI",
|
||||
"BotSharp.Plugin.MetaAI",
|
||||
"BotSharp.Plugin.Qdrant",
|
||||
"BotSharp.Plugin.PaddleSharp"
|
||||
"BotSharp.Plugin.PaddleSharp",
|
||||
"BotSharp.Plugin.WeChat"
|
||||
],
|
||||
"Plugins": [
|
||||
"KnowledgeBasePlugin",
|
||||
|
|
@ -79,7 +87,8 @@
|
|||
"AzureOpenAiPlugin",
|
||||
"MetaAiPlugin",
|
||||
"QdrantPlugin",
|
||||
"PaddleSharpPlugin"
|
||||
"PaddleSharpPlugin",
|
||||
"WeChatPlugin"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue