From 97e0b687ce6609d7bdd1ae28291513e7ca8209d7 Mon Sep 17 00:00:00 2001 From: jason Date: Mon, 25 Nov 2024 22:20:32 +0800 Subject: [PATCH 01/48] add AvatarBase64 --- .../Browsing/Models/ElementLocatingArgs.cs | 1 + .../PlaywrightWebDriver.LocateElement.cs | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/ElementLocatingArgs.cs b/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/ElementLocatingArgs.cs index b50f2366..a8b5af51 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/ElementLocatingArgs.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/ElementLocatingArgs.cs @@ -36,4 +36,5 @@ public class ElementLocatingArgs /// public bool Highlight { get; set; } public string HighlightColor { get; set; } = "red"; + public bool IsImage { get; set; } } diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.LocateElement.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.LocateElement.cs index 8695fc5c..e9b4004e 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.LocateElement.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.LocateElement.cs @@ -17,6 +17,18 @@ public partial class PlaywrightWebDriver ILocator locator = page.Locator("body"); int count = 0; + if (location.IsImage) + { + var handle = await page.QuerySelectorAsync("img"); + byte[]? imageBytes = handle != null ? await handle.ScreenshotAsync() : null; + string? body = null; + if (imageBytes?.Any() == true) + { + body = Convert.ToBase64String(imageBytes); + } + return new BrowserActionResult { IsSuccess = true, Body = body }; + } + // check if selector is specified if (location.Selector != null) { From 8cb29b147c642ed54d03cfc107e41c66e1c6410b Mon Sep 17 00:00:00 2001 From: jason Date: Mon, 25 Nov 2024 23:05:56 +0800 Subject: [PATCH 02/48] use IHttpClientFactory --- .../Browsing/Models/ElementLocatingArgs.cs | 1 - .../PlaywrightWebDriver.LocateElement.cs | 12 ------------ 2 files changed, 13 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/ElementLocatingArgs.cs b/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/ElementLocatingArgs.cs index a8b5af51..b50f2366 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/ElementLocatingArgs.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/ElementLocatingArgs.cs @@ -36,5 +36,4 @@ public class ElementLocatingArgs /// public bool Highlight { get; set; } public string HighlightColor { get; set; } = "red"; - public bool IsImage { get; set; } } diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.LocateElement.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.LocateElement.cs index e9b4004e..8695fc5c 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.LocateElement.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.LocateElement.cs @@ -17,18 +17,6 @@ public partial class PlaywrightWebDriver ILocator locator = page.Locator("body"); int count = 0; - if (location.IsImage) - { - var handle = await page.QuerySelectorAsync("img"); - byte[]? imageBytes = handle != null ? await handle.ScreenshotAsync() : null; - string? body = null; - if (imageBytes?.Any() == true) - { - body = Convert.ToBase64String(imageBytes); - } - return new BrowserActionResult { IsSuccess = true, Body = body }; - } - // check if selector is specified if (location.Selector != null) { From ee1de29495fa6e3695e6ff75bf472bb7d43afb1d Mon Sep 17 00:00:00 2001 From: AnonymousDotNet <18776095145@163.com> Date: Fri, 6 Dec 2024 17:03:31 +0800 Subject: [PATCH 03/48] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E6=89=8B=E6=9C=BA/=E9=82=AE=E7=AE=B1=E5=90=8E?= =?UTF-8?q?=E6=9C=AA=E9=87=8D=E6=96=B0=E7=99=BB=E5=BD=95=EF=BC=8C=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E4=BF=AE=E6=94=B9=E5=AF=86=E7=A0=81=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs index 9bc436a7..4cee45db 100644 --- a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs +++ b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs @@ -127,7 +127,8 @@ public class UserService : IUserService public async Task UpdatePassword(string password, string verificationCode) { var db = _services.GetRequiredService(); - var record = db.GetUserByUserName(_user.UserName); + + var record = db.GetUserById(_user.Id); if (record == null) { From 018d7c871f375f8a86f1a93cc222e178935941c3 Mon Sep 17 00:00:00 2001 From: AnonymousDotNet <18776095145@163.com> Date: Fri, 6 Dec 2024 17:34:43 +0800 Subject: [PATCH 04/48] fix: add regionCode for ActiveUser API --- .../BotSharp.Abstraction/Users/Models/UserActivationModel.cs | 1 + src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Users/Models/UserActivationModel.cs b/src/Infrastructure/BotSharp.Abstraction/Users/Models/UserActivationModel.cs index 904bd936..3ea4a915 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Users/Models/UserActivationModel.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Users/Models/UserActivationModel.cs @@ -4,4 +4,5 @@ public class UserActivationModel { public string UserName { get; set; } public string VerificationCode { get; set; } + public string RegionCode { get; set; } = "CN"; } diff --git a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs index 4cee45db..55e8c0cd 100644 --- a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs +++ b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs @@ -474,7 +474,7 @@ public class UserService : IUserService var record = id.Contains("@") ? db.GetUserByEmail(id) : db.GetUserByUserName(id); if (record == null) { - record = db.GetUserByPhone(id); + record = db.GetUserByPhone(id, regionCode: string.IsNullOrWhiteSpace(model.RegionCode) ? "CN" : model.RegionCode); } if (record == null) From 480d6d8ed8403625de014dc1c600d0d898bb024d Mon Sep 17 00:00:00 2001 From: AnonymousDotNet <18776095145@163.com> Date: Fri, 6 Dec 2024 17:44:07 +0800 Subject: [PATCH 05/48] fix: add regionCode for updatepassword API --- .../BotSharp.Core/Users/Services/UserService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs index 55e8c0cd..468de184 100644 --- a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs +++ b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs @@ -474,7 +474,7 @@ public class UserService : IUserService var record = id.Contains("@") ? db.GetUserByEmail(id) : db.GetUserByUserName(id); if (record == null) { - record = db.GetUserByPhone(id, regionCode: string.IsNullOrWhiteSpace(model.RegionCode) ? "CN" : model.RegionCode); + record = db.GetUserByPhone(id, regionCode: (string.IsNullOrWhiteSpace(model.RegionCode) ? "CN" : model.RegionCode)); } if (record == null) @@ -647,7 +647,7 @@ public class UserService : IUserService if (!string.IsNullOrEmpty(user.Phone)) { - record = db.GetUserByPhone(user.Phone); + record = db.GetUserByPhone(user.Phone, regionCode: (string.IsNullOrWhiteSpace(user.RegionCode) ? "CN" : user.RegionCode)); } if (record == null) From ff51e81b6d58d96a7668c1516ed4f4f83ad0a663 Mon Sep 17 00:00:00 2001 From: AnonymousDotNet <18776095145@163.com> Date: Fri, 6 Dec 2024 17:59:08 +0800 Subject: [PATCH 06/48] fix: add regionCode for ModifyUserPhone API --- src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs index 468de184..03d983ba 100644 --- a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs +++ b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs @@ -696,7 +696,7 @@ public class UserService : IUserService var curUser = await GetMyProfile(); var db = _services.GetRequiredService(); var record = db.GetUserById(curUser.Id); - var existPhone = db.GetUserByPhone(phone); + var existPhone = db.GetUserByPhone(phone, regionCode: regionCode); if (record == null || (existPhone != null && existPhone.RegionCode == regionCode)) { From 117cbd7865d76b92b212dfb701a0a41bb8c435ce Mon Sep 17 00:00:00 2001 From: AnonymousDotNet <18776095145@163.com> Date: Fri, 6 Dec 2024 18:21:34 +0800 Subject: [PATCH 07/48] fix: add regionCode for GetUserByPhone API --- src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs index 03d983ba..cb451e26 100644 --- a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs +++ b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs @@ -62,7 +62,7 @@ public class UserService : IUserService if (!string.IsNullOrWhiteSpace(user.Phone)) { - record = db.GetUserByPhone(user.Phone); + record = db.GetUserByPhone(user.Phone, regionCode: (string.IsNullOrWhiteSpace(user.RegionCode) ? "CN" : user.RegionCode)); } if (record == null && !string.IsNullOrWhiteSpace(user.Email)) From ecc0e5cedfe7af55a1d682bc392067a64f544b83 Mon Sep 17 00:00:00 2001 From: AnonymousDotNet <18776095145@163.com> Date: Wed, 11 Dec 2024 15:02:14 +0800 Subject: [PATCH 08/48] test: Add regionCode to log --- src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs index cb451e26..a87c55fa 100644 --- a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs +++ b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs @@ -112,7 +112,7 @@ public class UserService : IUserService db.UpdateExistUser(hasRegisterId, record); } - _logger.LogWarning($"Created new user account: {record.Id} {record.UserName}"); + _logger.LogWarning($"Created new user account: {record.Id} {record.UserName}, RegionCode: {record.RegionCode}"); Utilities.ClearCache(); var hooks = _services.GetServices(); From 5ac77f984504771bf0e50874b259374c8cc7671d Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Wed, 11 Dec 2024 21:16:42 +0000 Subject: [PATCH 09/48] Delay 1 second after release --- .../Drivers/PlaywrightDriver/PlaywrightWebDriver.DoAction.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.DoAction.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.DoAction.cs index 40fec84e..b851cd1a 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.DoAction.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.DoAction.cs @@ -113,6 +113,7 @@ public partial class PlaywrightWebDriver } // Release mouse button + await Task.Delay(1000); await mouse.UpAsync(); } else From dead8cfc93d0c8b6efaf6e84164e0a62c62a4e57 Mon Sep 17 00:00:00 2001 From: AnonymousDotNet <18776095145@163.com> Date: Thu, 12 Dec 2024 17:08:10 +0800 Subject: [PATCH 10/48] feat: Add WeChat User Dto --- .../Users/Models/WeChatUser.cs | 55 +++++++++++++ .../Collections/WeChatUserDocument.cs | 78 +++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 src/Infrastructure/BotSharp.Abstraction/Users/Models/WeChatUser.cs create mode 100644 src/Plugins/BotSharp.Plugin.MongoStorage/Collections/WeChatUserDocument.cs diff --git a/src/Infrastructure/BotSharp.Abstraction/Users/Models/WeChatUser.cs b/src/Infrastructure/BotSharp.Abstraction/Users/Models/WeChatUser.cs new file mode 100644 index 00000000..511ef236 --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Users/Models/WeChatUser.cs @@ -0,0 +1,55 @@ +namespace BotSharp.Abstraction.Users.Models; + +public class WeChatUser +{ + public string Id { get; set; } = string.Empty; + + /// + /// User unique identifier (unique under the current application) + /// + public string OpenId { get; set; } = string.Empty; + + public string SessionKey { get; set; } = string.Empty; + + /// + /// User unique identifier (cross application unique, requiring open platform binding) + /// + public string UnionId { get; set; } = string.Empty; + + /// + /// User's gender: 1- Male, 2- Female, 0- Unknown + /// + public int Sex { get; set; } + + /// + /// The province where the user's personal information is filled in + /// + public string Province { get; set; } = string.Empty; + + public string City { get; set; } = string.Empty; + + public string NickName { get; set; } = string.Empty; + + /// + /// User avatar URL (46/64/96/132/0 pixels) + /// + public string Headimgurl { get; set; } = string.Empty; + + public string PhoneNumber { get; set; } = string.Empty; + + /// + /// The country where the user is located, such as China CN + /// + public string Country { get; set; } = "CN"; + + /// + /// User privilege information (such as WeChat membership, etc.) + /// + public string[] Privilege { get; set; } = Array.Empty(); + + //public string AppId { get; set; } = string.Empty; + + public DateTime? UpdatedAt { get; set; } + + public DateTime CreatedAt { get; set; } +} diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/WeChatUserDocument.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/WeChatUserDocument.cs new file mode 100644 index 00000000..6898cb9c --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/WeChatUserDocument.cs @@ -0,0 +1,78 @@ +using BotSharp.Abstraction.Users.Models; + +namespace BotSharp.Plugin.MongoStorage.Collections; + +public class WeChatUserDocument : MongoBase +{ + public string Id { get; set; } = string.Empty; + + /// + /// User unique identifier (unique under the current application) + /// + public string OpenId { get; set; } = string.Empty; + + public string SessionKey { get; set; } = string.Empty; + + /// + /// User unique identifier (cross application unique, requiring open platform binding) + /// + public string UnionId { get; set; } = string.Empty; + + /// + /// User's gender: 1- Male, 2- Female, 0- Unknown + /// + public int Sex { get; set; } + + /// + /// The province where the user's personal information is filled in + /// + public string Province { get; set; } = string.Empty; + + public string City { get; set; } = string.Empty; + + public string NickName { get; set; } = string.Empty; + + /// + /// User avatar URL (46/64/96/132/0 pixels) + /// + public string Headimgurl { get; set; } = string.Empty; + + public string PhoneNumber { get; set; } = string.Empty; + + /// + /// The country where the user is located, such as China CN + /// + public string Country { get; set; } = "CN"; + + /// + /// User privilege information (such as WeChat membership, etc.) + /// + public string[] Privilege { get; set; } = Array.Empty(); + + //public string AppId { get; set; } = string.Empty; + + public DateTime? UpdatedAt { get; set; } + + public DateTime CreatedAt { get; set; } + + public WeChatUser ToWeChatUser() + { + return new WeChatUser + { + Id = Id, + OpenId = OpenId, + SessionKey = SessionKey, + UnionId = UnionId, + Sex = Sex, + Province = Province, + City = City, + NickName = NickName, + Headimgurl = Headimgurl, + PhoneNumber = PhoneNumber, + Country = Country, + Privilege = Privilege, + CreatedAt = CreatedAt, + UpdatedAt = UpdatedAt + }; + } +} From 1857cc66e4c31005f2d667a9a2083937bb792284 Mon Sep 17 00:00:00 2001 From: AnonymousDotNet <18776095145@163.com> Date: Thu, 12 Dec 2024 17:09:46 +0800 Subject: [PATCH 11/48] feat: Add GetWeChatUser API --- .../BotSharp.Plugin.MongoStorage/MongoDbContext.cs | 5 ++++- .../Repository/MongoRepository.WeChatUser.cs | 13 +++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/MongoDbContext.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/MongoDbContext.cs index 89eb18ad..4c633dd9 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/MongoDbContext.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/MongoDbContext.cs @@ -36,7 +36,7 @@ public class MongoDbContext Key = x.Split("=")[0], Value = x.Split("=")[1] }).ToList(); - + var source = queries.FirstOrDefault(x => x.Key.IsEqualTo(DB_NAME_INDEX)); if (source != null) { @@ -168,4 +168,7 @@ public class MongoDbContext public IMongoCollection CrontabItems => Database.GetCollection($"{_collectionPrefix}_CronTabItems"); + + public IMongoCollection WeChatUsers + => Database.GetCollection($"{_collectionPrefix}_WeChatUsers"); } diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs new file mode 100644 index 00000000..81a325d4 --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs @@ -0,0 +1,13 @@ +using BotSharp.Abstraction.Users.Models; + +namespace BotSharp.Plugin.MongoStorage.Repository; + +public partial class MongoRepository +{ + public WeChatUser? GetWeChatUser(string openId) + { + var weChatUser = _dc.WeChatUsers.AsQueryable().FirstOrDefault(x => x.OpenId == openId); + return weChatUser != null ? weChatUser.ToWeChatUser() : null; + } + +} From af95a6e1b2f2ad7704c0700a79f78a35409c92fb Mon Sep 17 00:00:00 2001 From: AnonymousDotNet <18776095145@163.com> Date: Thu, 12 Dec 2024 17:11:26 +0800 Subject: [PATCH 12/48] feat: Add CreateWeChatUser API --- .../Repository/MongoRepository.WeChatUser.cs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs index 81a325d4..e85cfebf 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs @@ -10,4 +10,31 @@ public partial class MongoRepository return weChatUser != null ? weChatUser.ToWeChatUser() : null; } + public WeChatUser? CreateWeChatUser(WeChatUser weChatUser) + { + if (weChatUser == null) return null; + + var weChatUserInfo = new WeChatUserDocument + { + Id = weChatUser.Id ?? Guid.NewGuid().ToString(), + OpenId = weChatUser.OpenId, + SessionKey = weChatUser.SessionKey, + UnionId = weChatUser.UnionId, + Sex = weChatUser.Sex, + Province = weChatUser.Province, + City = weChatUser.City, + NickName = weChatUser.NickName, + Headimgurl = weChatUser.Headimgurl, + PhoneNumber = weChatUser.PhoneNumber, + Country = weChatUser.Country, + Privilege = weChatUser.Privilege, + CreatedAt = DateTime.UtcNow, + }; + + _dc.WeChatUsers.InsertOne(weChatUserInfo); + + return weChatUserInfo.ToWeChatUser(); + } + + } From 541b7893da025756889f6723c94710dbe74c5a68 Mon Sep 17 00:00:00 2001 From: AnonymousDotNet <18776095145@163.com> Date: Thu, 12 Dec 2024 17:12:07 +0800 Subject: [PATCH 13/48] feat: Add UpdateWeChatUser API --- .../Repository/MongoRepository.WeChatUser.cs | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs index e85cfebf..4399a5df 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs @@ -36,5 +36,27 @@ public partial class MongoRepository return weChatUserInfo.ToWeChatUser(); } - + public WeChatUser? UpdateWeChatUser(WeChatUser weChatUser) + { + if (weChatUser == null) return null; + + var filter = Builders.Filter.Eq(x => x.Id, weChatUser.Id); + var update = Builders.Update + .Set(x => x.OpenId, weChatUser.OpenId) + .Set(x => x.SessionKey, weChatUser.SessionKey) + .Set(x => x.UnionId, weChatUser.UnionId) + .Set(x => x.Sex, weChatUser.Sex) + .Set(x => x.Province, weChatUser.Province) + .Set(x => x.City, weChatUser.City) + .Set(x => x.NickName, weChatUser.NickName) + .Set(x => x.Headimgurl, weChatUser.Headimgurl) + .Set(x => x.PhoneNumber, weChatUser.PhoneNumber) + .Set(x => x.Country, weChatUser.Country) + .Set(x => x.Privilege, weChatUser.Privilege) + .Set(x => x.UpdatedAt, DateTime.UtcNow); + + _dc.WeChatUsers.UpdateOne(filter, update); + + return weChatUser; + } } From d11e91ca84ac9d7ece2544ea1b4a67328d3990c9 Mon Sep 17 00:00:00 2001 From: AnonymousDotNet <18776095145@163.com> Date: Thu, 12 Dec 2024 20:58:22 +0800 Subject: [PATCH 14/48] feat: Add Create WeChat User Interface API --- .../Repositories/IBotSharpRepository.cs | 5 +++ .../Users/IWeChatUserService.cs | 12 +++++++ .../Users/Services/WeChatUserService.cs | 31 +++++++++++++++++++ .../Controllers/UserController.cs | 16 ++++++++-- 4 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 src/Infrastructure/BotSharp.Abstraction/Users/IWeChatUserService.cs create mode 100644 src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs index 61982cc4..da5b2f3f 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs @@ -49,6 +49,11 @@ public interface IBotSharpRepository : IHaveServiceProvider PagedItems GetUsers(UserFilter filter) => throw new NotImplementedException(); User? GetUserDetails(string userId, bool includeAgent = false) => throw new NotImplementedException(); bool UpdateUser(User user, bool updateUserAgents = false) => throw new NotImplementedException(); + + WeChatUser? GetWeChatUser(string openId) => throw new NotImplementedException(); + WeChatUser? CreateWeChatUser(WeChatUser weChatUser) => throw new NotImplementedException(); + WeChatUser? UpdateWeChatUser(WeChatUser weChatUser) => throw new NotImplementedException(); + #endregion #region Agent diff --git a/src/Infrastructure/BotSharp.Abstraction/Users/IWeChatUserService.cs b/src/Infrastructure/BotSharp.Abstraction/Users/IWeChatUserService.cs new file mode 100644 index 00000000..b25ba73d --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Users/IWeChatUserService.cs @@ -0,0 +1,12 @@ +using BotSharp.Abstraction.Users.Models; + +namespace BotSharp.Abstraction.Users; + +public interface IWeChatUserService +{ + Task GetWeChatUser(string openId); + + Task CreateWeChatUser(WeChatUser weChatUser); + + Task UpdateWeChatUser(WeChatUser weChatUser); +} diff --git a/src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs b/src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs new file mode 100644 index 00000000..ab776b28 --- /dev/null +++ b/src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs @@ -0,0 +1,31 @@ +using BotSharp.Abstraction.Users.Models; + +namespace BotSharp.Core.Users.Services; + +public class WeChatUserService : IWeChatUserService +{ + private readonly IServiceProvider _services; + public WeChatUserService(IServiceProvider services) + { + _services = services; + } + + public async Task GetWeChatUser(string openId) + { + var db = _services.GetRequiredService(); + var weChatUser = db.GetWeChatUser(openId); + return weChatUser; + } + + public async Task CreateWeChatUser(WeChatUser weChatUser) + { + var db = _services.GetRequiredService(); + return db.CreateWeChatUser(weChatUser); + } + + public async Task UpdateWeChatUser(WeChatUser weChatUser) + { + var db = _services.GetRequiredService(); + return db.UpdateWeChatUser(weChatUser); + } +} diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs index 9d652a3e..b72888f3 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs @@ -1,4 +1,3 @@ -using BotSharp.Abstraction.Users.Enums; using BotSharp.Abstraction.Users.Settings; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; @@ -14,17 +13,20 @@ public class UserController : ControllerBase private readonly IUserService _userService; private readonly IUserIdentity _user; private readonly AccountSetting _setting; + private readonly IWeChatUserService _weChatUserService; public UserController( IUserService userService, IServiceProvider services, IUserIdentity user, - AccountSetting setting) + AccountSetting setting, + IWeChatUserService weChatUserService) { _services = services; _userService = userService; _user = user; _setting = setting; + _weChatUserService = weChatUserService; } [AllowAnonymous] @@ -72,6 +74,16 @@ public class UserController : ControllerBase return UserViewModel.FromUser(createdUser); } + [HttpPost("/user/wechat")] + public async Task CreateWeChatUser(string code) + { + // Get WeChat User Info + + + WeChatUser wechatUser = new(); + var user = await _weChatUserService.CreateWeChatUser(wechatUser); + } + [AllowAnonymous] [HttpPost("/user/activate")] public async Task> ActivateUser(UserActivationModel model) From d41d6eddd82ff4cec450b7a6d0d750f55cb8175a Mon Sep 17 00:00:00 2001 From: AnonymousDotNet <18776095145@163.com> Date: Fri, 13 Dec 2024 19:29:12 +0800 Subject: [PATCH 15/48] wip: Integrated WeChat login --- .../Repositories/IBotSharpRepository.cs | 2 +- .../Users/IWeChatUserService.cs | 2 + .../Users/Models/WeChatUser.cs | 22 ++++- .../Users/Services/WeChatUserService.cs | 88 ++++++++++++++++++- .../Controllers/UserController.cs | 15 +++- .../Collections/WeChatUserDocument.cs | 3 - .../Repository/MongoRepository.WeChatUser.cs | 6 +- src/WebStarter/appsettings.json | 10 +++ 8 files changed, 132 insertions(+), 16 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs index da5b2f3f..aafb5b5f 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs @@ -51,7 +51,7 @@ public interface IBotSharpRepository : IHaveServiceProvider bool UpdateUser(User user, bool updateUserAgents = false) => throw new NotImplementedException(); WeChatUser? GetWeChatUser(string openId) => throw new NotImplementedException(); - WeChatUser? CreateWeChatUser(WeChatUser weChatUser) => throw new NotImplementedException(); + WeChatUser CreateWeChatUser(WeChatUser weChatUser) => throw new NotImplementedException(); WeChatUser? UpdateWeChatUser(WeChatUser weChatUser) => throw new NotImplementedException(); #endregion diff --git a/src/Infrastructure/BotSharp.Abstraction/Users/IWeChatUserService.cs b/src/Infrastructure/BotSharp.Abstraction/Users/IWeChatUserService.cs index b25ba73d..a6b69865 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Users/IWeChatUserService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Users/IWeChatUserService.cs @@ -9,4 +9,6 @@ public interface IWeChatUserService Task CreateWeChatUser(WeChatUser weChatUser); Task UpdateWeChatUser(WeChatUser weChatUser); + + Task WeChatUserLogin(string code); } diff --git a/src/Infrastructure/BotSharp.Abstraction/Users/Models/WeChatUser.cs b/src/Infrastructure/BotSharp.Abstraction/Users/Models/WeChatUser.cs index 511ef236..165787a0 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Users/Models/WeChatUser.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Users/Models/WeChatUser.cs @@ -1,3 +1,5 @@ +using BotSharp.Abstraction.Users.Enums; + namespace BotSharp.Abstraction.Users.Models; public class WeChatUser @@ -9,8 +11,6 @@ public class WeChatUser /// public string OpenId { get; set; } = string.Empty; - public string SessionKey { get; set; } = string.Empty; - /// /// User unique identifier (cross application unique, requiring open platform binding) /// @@ -52,4 +52,22 @@ public class WeChatUser public DateTime? UpdatedAt { get; set; } public DateTime CreatedAt { get; set; } + + public User ToUser() + { + return new User + { + Id = Id, + Phone = PhoneNumber, + UserName = PhoneNumber, + FirstName = PhoneNumber, + LastName = PhoneNumber, + Email = null, + Password = string.Empty, + Role = UserRole.User, + Type = UserType.Client, + RegionCode = "CN", + ReferralCode = null, + }; + } } diff --git a/src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs b/src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs index ab776b28..d79c1648 100644 --- a/src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs +++ b/src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs @@ -1,23 +1,30 @@ using BotSharp.Abstraction.Users.Models; +using Microsoft.Extensions.Configuration; +using Newtonsoft.Json.Linq; namespace BotSharp.Core.Users.Services; public class WeChatUserService : IWeChatUserService { private readonly IServiceProvider _services; - public WeChatUserService(IServiceProvider services) + private readonly ILogger _logger; + private readonly IConfiguration _configuration; + + public WeChatUserService(IServiceProvider services, ILogger logger, IConfiguration configuration) { _services = services; + _logger = logger; + _configuration = configuration; } public async Task GetWeChatUser(string openId) { - var db = _services.GetRequiredService(); + var db = _services.GetRequiredService(); var weChatUser = db.GetWeChatUser(openId); return weChatUser; } - public async Task CreateWeChatUser(WeChatUser weChatUser) + public async Task CreateWeChatUser(WeChatUser weChatUser) { var db = _services.GetRequiredService(); return db.CreateWeChatUser(weChatUser); @@ -28,4 +35,79 @@ public class WeChatUserService : IWeChatUserService var db = _services.GetRequiredService(); return db.UpdateWeChatUser(weChatUser); } + + #region 微信扫码登录(OAuth 2.0 网页授权) + + public async Task WeChatUserLogin(string code) + { + // 实现获取 access_token 和 openid,再获取用户信息 + if (string.IsNullOrEmpty(code)) + { + _logger.LogError("Create WeChatUser Error: code is empty, Please check if the code has been obtained correctly!"); + throw new Exception("code is empty"); + } + + var appId = _configuration["WeChatQtoss:AppId"] ?? throw new Exception("AppId is not configured."); + var appSecret = _configuration["WeChatQtoss:AppSecret"] ?? throw new Exception("AppSecret is not configured."); + + try + { + // Step 1: 使用 code 获取 access_token 和 openid + var tokenUrl = $"https://api.weixin.qq.com/sns/oauth2/access_token?appid={appId}&secret={appSecret}&code={code}&grant_type=authorization_code"; + + using var httpClient = new HttpClient(); + var tokenResponse = await httpClient.GetStringAsync(tokenUrl); + + var tokenData = JObject.Parse(tokenResponse); + var accessToken = tokenData["access_token"]?.ToString(); + var openId = tokenData["openid"]?.ToString(); + + if (string.IsNullOrEmpty(accessToken) || string.IsNullOrEmpty(openId)) + { + _logger.LogError("Create WeChatUser Error: Failed to get access_token or openid"); + throw new Exception("Failed to get access_token or openid"); + } + + // Step 2: Retrieve user information using access_token and openid + var userInfoUrl = $"https://api.weixin.qq.com/sns/userinfo?access_token={accessToken}&openid={openId}&lang=zh_CN"; + + var userInfoResponse = await httpClient.GetStringAsync(userInfoUrl); + var userInfo = JObject.Parse(userInfoResponse); + + // 提取用户信息 + var nickname = userInfo["nickname"]?.ToString() ?? string.Empty; + var avatar = userInfo["headimgurl"]?.ToString() ?? string.Empty; + var country = userInfo["country"]?.ToString() ?? string.Empty; + var province = userInfo["province"]?.ToString() ?? string.Empty; + var city = userInfo["city"]?.ToString() ?? string.Empty; + var sex = userInfo["sex"]?.ToString() ?? "0"; + var privilege = userInfo["privilege"]?.ToString() ?? string.Empty; + var unionId = userInfo["unionId"]?.ToString() ?? string.Empty; + + // 创建或更新 WeChatUser + var weChatUser = new WeChatUser + { + OpenId = openId, + NickName = nickname, + Sex = int.Parse(sex), + Province = province, + City = city, + Country = country, + Headimgurl = avatar, + Privilege = privilege.Split(','), + UnionId = unionId + }; + + return await CreateWeChatUser(weChatUser); + } + catch (Exception ex) + { + _logger.LogError($"Create WeChatUser Error: {ex.Message}"); + throw new Exception($"Failed to create WeChatUser: {ex.Message}", ex); + } + + } + + + #endregion 微信扫码登录(OAuth 2.0 网页授权) } diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs index b72888f3..a39200e2 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs @@ -78,10 +78,21 @@ public class UserController : ControllerBase public async Task CreateWeChatUser(string code) { // Get WeChat User Info + var wechatUser = await _weChatUserService.WeChatUserLogin(code); + if (wechatUser == null) + { + return; + } + var weChatUser = await _weChatUserService.CreateWeChatUser(wechatUser); - WeChatUser wechatUser = new(); - var user = await _weChatUserService.CreateWeChatUser(wechatUser); + if (wechatUser == null) + { + return; + } + + // Create User + var createdUser = await _userService.CreateUser(weChatUser.ToUser()); } [AllowAnonymous] diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/WeChatUserDocument.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/WeChatUserDocument.cs index 6898cb9c..c85c7f4e 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/WeChatUserDocument.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/WeChatUserDocument.cs @@ -11,8 +11,6 @@ public class WeChatUserDocument : MongoBase /// public string OpenId { get; set; } = string.Empty; - public string SessionKey { get; set; } = string.Empty; - /// /// User unique identifier (cross application unique, requiring open platform binding) /// @@ -61,7 +59,6 @@ public class WeChatUserDocument : MongoBase { Id = Id, OpenId = OpenId, - SessionKey = SessionKey, UnionId = UnionId, Sex = Sex, Province = Province, diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs index 4399a5df..91cca0bf 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs @@ -10,15 +10,12 @@ public partial class MongoRepository return weChatUser != null ? weChatUser.ToWeChatUser() : null; } - public WeChatUser? CreateWeChatUser(WeChatUser weChatUser) + public WeChatUser CreateWeChatUser(WeChatUser weChatUser) { - if (weChatUser == null) return null; - var weChatUserInfo = new WeChatUserDocument { Id = weChatUser.Id ?? Guid.NewGuid().ToString(), OpenId = weChatUser.OpenId, - SessionKey = weChatUser.SessionKey, UnionId = weChatUser.UnionId, Sex = weChatUser.Sex, Province = weChatUser.Province, @@ -43,7 +40,6 @@ public partial class MongoRepository var filter = Builders.Filter.Eq(x => x.Id, weChatUser.Id); var update = Builders.Update .Set(x => x.OpenId, weChatUser.OpenId) - .Set(x => x.SessionKey, weChatUser.SessionKey) .Set(x => x.UnionId, weChatUser.UnionId) .Set(x => x.Sex, weChatUser.Sex) .Set(x => x.Province, weChatUser.Province) diff --git a/src/WebStarter/appsettings.json b/src/WebStarter/appsettings.json index c3d4bdd5..3efc0b4d 100644 --- a/src/WebStarter/appsettings.json +++ b/src/WebStarter/appsettings.json @@ -273,6 +273,16 @@ "WeixinAppSecret": "#{WeixinAppSecret}#" }, + "WeChatQtoss": { + "AppId": "", + "AppSecret": "" + }, + + "WeChatQtossAI": { + "AppId": "", + "AppSecret": "" + }, + "KnowledgeBase": { "VectorDb": { "Provider": "Qdrant" From dedf6d740bbef319951cb1c7983f6d52e2622594 Mon Sep 17 00:00:00 2001 From: AnonymousDotNet <18776095145@163.com> Date: Fri, 13 Dec 2024 19:37:47 +0800 Subject: [PATCH 16/48] wip: update CreateWeChatUser API --- .../Users/Services/WeChatUserService.cs | 8 ++++---- .../Controllers/UserController.cs | 19 +++++++------------ 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs b/src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs index d79c1648..1da9b47e 100644 --- a/src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs +++ b/src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs @@ -40,7 +40,7 @@ public class WeChatUserService : IWeChatUserService public async Task WeChatUserLogin(string code) { - // 实现获取 access_token 和 openid,再获取用户信息 + // Implement obtaining access_token and openid, and then obtaining user information if (string.IsNullOrEmpty(code)) { _logger.LogError("Create WeChatUser Error: code is empty, Please check if the code has been obtained correctly!"); @@ -52,7 +52,7 @@ public class WeChatUserService : IWeChatUserService try { - // Step 1: 使用 code 获取 access_token 和 openid + // Step 1: Use the code to obtain the access_token and openid var tokenUrl = $"https://api.weixin.qq.com/sns/oauth2/access_token?appid={appId}&secret={appSecret}&code={code}&grant_type=authorization_code"; using var httpClient = new HttpClient(); @@ -74,7 +74,7 @@ public class WeChatUserService : IWeChatUserService var userInfoResponse = await httpClient.GetStringAsync(userInfoUrl); var userInfo = JObject.Parse(userInfoResponse); - // 提取用户信息 + // Retrieve user information var nickname = userInfo["nickname"]?.ToString() ?? string.Empty; var avatar = userInfo["headimgurl"]?.ToString() ?? string.Empty; var country = userInfo["country"]?.ToString() ?? string.Empty; @@ -84,7 +84,7 @@ public class WeChatUserService : IWeChatUserService var privilege = userInfo["privilege"]?.ToString() ?? string.Empty; var unionId = userInfo["unionId"]?.ToString() ?? string.Empty; - // 创建或更新 WeChatUser + // Create or update WeChatUser var weChatUser = new WeChatUser { OpenId = openId, diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs index a39200e2..964e8aee 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs @@ -74,25 +74,20 @@ public class UserController : ControllerBase return UserViewModel.FromUser(createdUser); } + [AllowAnonymous] [HttpPost("/user/wechat")] - public async Task CreateWeChatUser(string code) + public async Task CreateWeChatUser(string code) { // Get WeChat User Info - var wechatUser = await _weChatUserService.WeChatUserLogin(code); - if (wechatUser == null) - { - return; - } + var wechatUserInfo = await _weChatUserService.WeChatUserLogin(code); - var weChatUser = await _weChatUserService.CreateWeChatUser(wechatUser); - - if (wechatUser == null) - { - return; - } + // Create WeChatUser + var weChatUser = await _weChatUserService.CreateWeChatUser(wechatUserInfo); // Create User var createdUser = await _userService.CreateUser(weChatUser.ToUser()); + + return UserViewModel.FromUser(createdUser); } [AllowAnonymous] From 802401690b32532c4cd74554a076203cd73a892a Mon Sep 17 00:00:00 2001 From: AnonymousDotNet <18776095145@163.com> Date: Sat, 14 Dec 2024 10:44:35 +0800 Subject: [PATCH 17/48] fix: updated country --- .../BotSharp.Core/Users/Services/WeChatUserService.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs b/src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs index 1da9b47e..55b8e0e9 100644 --- a/src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs +++ b/src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs @@ -77,7 +77,7 @@ public class WeChatUserService : IWeChatUserService // Retrieve user information var nickname = userInfo["nickname"]?.ToString() ?? string.Empty; var avatar = userInfo["headimgurl"]?.ToString() ?? string.Empty; - var country = userInfo["country"]?.ToString() ?? string.Empty; + var country = userInfo["country"]?.ToString() ?? "CN"; var province = userInfo["province"]?.ToString() ?? string.Empty; var city = userInfo["city"]?.ToString() ?? string.Empty; var sex = userInfo["sex"]?.ToString() ?? "0"; @@ -92,7 +92,7 @@ public class WeChatUserService : IWeChatUserService Sex = int.Parse(sex), Province = province, City = city, - Country = country, + Country = ((country != "CN" && country.Contains("CN")) ? "CN" : country), Headimgurl = avatar, Privilege = privilege.Split(','), UnionId = unionId @@ -105,7 +105,7 @@ public class WeChatUserService : IWeChatUserService _logger.LogError($"Create WeChatUser Error: {ex.Message}"); throw new Exception($"Failed to create WeChatUser: {ex.Message}", ex); } - + } From d87afc7151e69b697f8f761754119469f4cd23a7 Mon Sep 17 00:00:00 2001 From: AnonymousDotNet <18776095145@163.com> Date: Sat, 14 Dec 2024 15:55:16 +0800 Subject: [PATCH 18/48] revert: #57 --- .../Repositories/IBotSharpRepository.cs | 4 - .../Users/IWeChatUserService.cs | 14 --- .../Users/Models/WeChatUser.cs | 73 ----------- .../Users/Services/WeChatUserService.cs | 113 ------------------ .../Controllers/UserController.cs | 21 +--- .../Collections/WeChatUserDocument.cs | 75 ------------ .../MongoDbContext.cs | 2 - .../Repository/MongoRepository.WeChatUser.cs | 58 --------- src/WebStarter/appsettings.json | 10 -- 9 files changed, 1 insertion(+), 369 deletions(-) delete mode 100644 src/Infrastructure/BotSharp.Abstraction/Users/IWeChatUserService.cs delete mode 100644 src/Infrastructure/BotSharp.Abstraction/Users/Models/WeChatUser.cs delete mode 100644 src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs delete mode 100644 src/Plugins/BotSharp.Plugin.MongoStorage/Collections/WeChatUserDocument.cs delete mode 100644 src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs index aafb5b5f..3fca7372 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs @@ -50,10 +50,6 @@ public interface IBotSharpRepository : IHaveServiceProvider User? GetUserDetails(string userId, bool includeAgent = false) => throw new NotImplementedException(); bool UpdateUser(User user, bool updateUserAgents = false) => throw new NotImplementedException(); - WeChatUser? GetWeChatUser(string openId) => throw new NotImplementedException(); - WeChatUser CreateWeChatUser(WeChatUser weChatUser) => throw new NotImplementedException(); - WeChatUser? UpdateWeChatUser(WeChatUser weChatUser) => throw new NotImplementedException(); - #endregion #region Agent diff --git a/src/Infrastructure/BotSharp.Abstraction/Users/IWeChatUserService.cs b/src/Infrastructure/BotSharp.Abstraction/Users/IWeChatUserService.cs deleted file mode 100644 index a6b69865..00000000 --- a/src/Infrastructure/BotSharp.Abstraction/Users/IWeChatUserService.cs +++ /dev/null @@ -1,14 +0,0 @@ -using BotSharp.Abstraction.Users.Models; - -namespace BotSharp.Abstraction.Users; - -public interface IWeChatUserService -{ - Task GetWeChatUser(string openId); - - Task CreateWeChatUser(WeChatUser weChatUser); - - Task UpdateWeChatUser(WeChatUser weChatUser); - - Task WeChatUserLogin(string code); -} diff --git a/src/Infrastructure/BotSharp.Abstraction/Users/Models/WeChatUser.cs b/src/Infrastructure/BotSharp.Abstraction/Users/Models/WeChatUser.cs deleted file mode 100644 index 165787a0..00000000 --- a/src/Infrastructure/BotSharp.Abstraction/Users/Models/WeChatUser.cs +++ /dev/null @@ -1,73 +0,0 @@ -using BotSharp.Abstraction.Users.Enums; - -namespace BotSharp.Abstraction.Users.Models; - -public class WeChatUser -{ - public string Id { get; set; } = string.Empty; - - /// - /// User unique identifier (unique under the current application) - /// - public string OpenId { get; set; } = string.Empty; - - /// - /// User unique identifier (cross application unique, requiring open platform binding) - /// - public string UnionId { get; set; } = string.Empty; - - /// - /// User's gender: 1- Male, 2- Female, 0- Unknown - /// - public int Sex { get; set; } - - /// - /// The province where the user's personal information is filled in - /// - public string Province { get; set; } = string.Empty; - - public string City { get; set; } = string.Empty; - - public string NickName { get; set; } = string.Empty; - - /// - /// User avatar URL (46/64/96/132/0 pixels) - /// - public string Headimgurl { get; set; } = string.Empty; - - public string PhoneNumber { get; set; } = string.Empty; - - /// - /// The country where the user is located, such as China CN - /// - public string Country { get; set; } = "CN"; - - /// - /// User privilege information (such as WeChat membership, etc.) - /// - public string[] Privilege { get; set; } = Array.Empty(); - - //public string AppId { get; set; } = string.Empty; - - public DateTime? UpdatedAt { get; set; } - - public DateTime CreatedAt { get; set; } - - public User ToUser() - { - return new User - { - Id = Id, - Phone = PhoneNumber, - UserName = PhoneNumber, - FirstName = PhoneNumber, - LastName = PhoneNumber, - Email = null, - Password = string.Empty, - Role = UserRole.User, - Type = UserType.Client, - RegionCode = "CN", - ReferralCode = null, - }; - } -} diff --git a/src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs b/src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs deleted file mode 100644 index 55b8e0e9..00000000 --- a/src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs +++ /dev/null @@ -1,113 +0,0 @@ -using BotSharp.Abstraction.Users.Models; -using Microsoft.Extensions.Configuration; -using Newtonsoft.Json.Linq; - -namespace BotSharp.Core.Users.Services; - -public class WeChatUserService : IWeChatUserService -{ - private readonly IServiceProvider _services; - private readonly ILogger _logger; - private readonly IConfiguration _configuration; - - public WeChatUserService(IServiceProvider services, ILogger logger, IConfiguration configuration) - { - _services = services; - _logger = logger; - _configuration = configuration; - } - - public async Task GetWeChatUser(string openId) - { - var db = _services.GetRequiredService(); - var weChatUser = db.GetWeChatUser(openId); - return weChatUser; - } - - public async Task CreateWeChatUser(WeChatUser weChatUser) - { - var db = _services.GetRequiredService(); - return db.CreateWeChatUser(weChatUser); - } - - public async Task UpdateWeChatUser(WeChatUser weChatUser) - { - var db = _services.GetRequiredService(); - return db.UpdateWeChatUser(weChatUser); - } - - #region 微信扫码登录(OAuth 2.0 网页授权) - - public async Task WeChatUserLogin(string code) - { - // Implement obtaining access_token and openid, and then obtaining user information - if (string.IsNullOrEmpty(code)) - { - _logger.LogError("Create WeChatUser Error: code is empty, Please check if the code has been obtained correctly!"); - throw new Exception("code is empty"); - } - - var appId = _configuration["WeChatQtoss:AppId"] ?? throw new Exception("AppId is not configured."); - var appSecret = _configuration["WeChatQtoss:AppSecret"] ?? throw new Exception("AppSecret is not configured."); - - try - { - // Step 1: Use the code to obtain the access_token and openid - var tokenUrl = $"https://api.weixin.qq.com/sns/oauth2/access_token?appid={appId}&secret={appSecret}&code={code}&grant_type=authorization_code"; - - using var httpClient = new HttpClient(); - var tokenResponse = await httpClient.GetStringAsync(tokenUrl); - - var tokenData = JObject.Parse(tokenResponse); - var accessToken = tokenData["access_token"]?.ToString(); - var openId = tokenData["openid"]?.ToString(); - - if (string.IsNullOrEmpty(accessToken) || string.IsNullOrEmpty(openId)) - { - _logger.LogError("Create WeChatUser Error: Failed to get access_token or openid"); - throw new Exception("Failed to get access_token or openid"); - } - - // Step 2: Retrieve user information using access_token and openid - var userInfoUrl = $"https://api.weixin.qq.com/sns/userinfo?access_token={accessToken}&openid={openId}&lang=zh_CN"; - - var userInfoResponse = await httpClient.GetStringAsync(userInfoUrl); - var userInfo = JObject.Parse(userInfoResponse); - - // Retrieve user information - var nickname = userInfo["nickname"]?.ToString() ?? string.Empty; - var avatar = userInfo["headimgurl"]?.ToString() ?? string.Empty; - var country = userInfo["country"]?.ToString() ?? "CN"; - var province = userInfo["province"]?.ToString() ?? string.Empty; - var city = userInfo["city"]?.ToString() ?? string.Empty; - var sex = userInfo["sex"]?.ToString() ?? "0"; - var privilege = userInfo["privilege"]?.ToString() ?? string.Empty; - var unionId = userInfo["unionId"]?.ToString() ?? string.Empty; - - // Create or update WeChatUser - var weChatUser = new WeChatUser - { - OpenId = openId, - NickName = nickname, - Sex = int.Parse(sex), - Province = province, - City = city, - Country = ((country != "CN" && country.Contains("CN")) ? "CN" : country), - Headimgurl = avatar, - Privilege = privilege.Split(','), - UnionId = unionId - }; - - return await CreateWeChatUser(weChatUser); - } - catch (Exception ex) - { - _logger.LogError($"Create WeChatUser Error: {ex.Message}"); - throw new Exception($"Failed to create WeChatUser: {ex.Message}", ex); - } - - } - - - #endregion 微信扫码登录(OAuth 2.0 网页授权) -} diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs index 964e8aee..c893bcab 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs @@ -13,20 +13,17 @@ public class UserController : ControllerBase private readonly IUserService _userService; private readonly IUserIdentity _user; private readonly AccountSetting _setting; - private readonly IWeChatUserService _weChatUserService; public UserController( IUserService userService, IServiceProvider services, IUserIdentity user, - AccountSetting setting, - IWeChatUserService weChatUserService) + AccountSetting setting) { _services = services; _userService = userService; _user = user; _setting = setting; - _weChatUserService = weChatUserService; } [AllowAnonymous] @@ -74,22 +71,6 @@ public class UserController : ControllerBase return UserViewModel.FromUser(createdUser); } - [AllowAnonymous] - [HttpPost("/user/wechat")] - public async Task CreateWeChatUser(string code) - { - // Get WeChat User Info - var wechatUserInfo = await _weChatUserService.WeChatUserLogin(code); - - // Create WeChatUser - var weChatUser = await _weChatUserService.CreateWeChatUser(wechatUserInfo); - - // Create User - var createdUser = await _userService.CreateUser(weChatUser.ToUser()); - - return UserViewModel.FromUser(createdUser); - } - [AllowAnonymous] [HttpPost("/user/activate")] public async Task> ActivateUser(UserActivationModel model) diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/WeChatUserDocument.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/WeChatUserDocument.cs deleted file mode 100644 index c85c7f4e..00000000 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/WeChatUserDocument.cs +++ /dev/null @@ -1,75 +0,0 @@ -using BotSharp.Abstraction.Users.Models; - -namespace BotSharp.Plugin.MongoStorage.Collections; - -public class WeChatUserDocument : MongoBase -{ - public string Id { get; set; } = string.Empty; - - /// - /// User unique identifier (unique under the current application) - /// - public string OpenId { get; set; } = string.Empty; - - /// - /// User unique identifier (cross application unique, requiring open platform binding) - /// - public string UnionId { get; set; } = string.Empty; - - /// - /// User's gender: 1- Male, 2- Female, 0- Unknown - /// - public int Sex { get; set; } - - /// - /// The province where the user's personal information is filled in - /// - public string Province { get; set; } = string.Empty; - - public string City { get; set; } = string.Empty; - - public string NickName { get; set; } = string.Empty; - - /// - /// User avatar URL (46/64/96/132/0 pixels) - /// - public string Headimgurl { get; set; } = string.Empty; - - public string PhoneNumber { get; set; } = string.Empty; - - /// - /// The country where the user is located, such as China CN - /// - public string Country { get; set; } = "CN"; - - /// - /// User privilege information (such as WeChat membership, etc.) - /// - public string[] Privilege { get; set; } = Array.Empty(); - - //public string AppId { get; set; } = string.Empty; - - public DateTime? UpdatedAt { get; set; } - - public DateTime CreatedAt { get; set; } - - public WeChatUser ToWeChatUser() - { - return new WeChatUser - { - Id = Id, - OpenId = OpenId, - UnionId = UnionId, - Sex = Sex, - Province = Province, - City = City, - NickName = NickName, - Headimgurl = Headimgurl, - PhoneNumber = PhoneNumber, - Country = Country, - Privilege = Privilege, - CreatedAt = CreatedAt, - UpdatedAt = UpdatedAt - }; - } -} diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/MongoDbContext.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/MongoDbContext.cs index 4c633dd9..82e9f0d4 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/MongoDbContext.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/MongoDbContext.cs @@ -169,6 +169,4 @@ public class MongoDbContext public IMongoCollection CrontabItems => Database.GetCollection($"{_collectionPrefix}_CronTabItems"); - public IMongoCollection WeChatUsers - => Database.GetCollection($"{_collectionPrefix}_WeChatUsers"); } diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs deleted file mode 100644 index 91cca0bf..00000000 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs +++ /dev/null @@ -1,58 +0,0 @@ -using BotSharp.Abstraction.Users.Models; - -namespace BotSharp.Plugin.MongoStorage.Repository; - -public partial class MongoRepository -{ - public WeChatUser? GetWeChatUser(string openId) - { - var weChatUser = _dc.WeChatUsers.AsQueryable().FirstOrDefault(x => x.OpenId == openId); - return weChatUser != null ? weChatUser.ToWeChatUser() : null; - } - - public WeChatUser CreateWeChatUser(WeChatUser weChatUser) - { - var weChatUserInfo = new WeChatUserDocument - { - Id = weChatUser.Id ?? Guid.NewGuid().ToString(), - OpenId = weChatUser.OpenId, - UnionId = weChatUser.UnionId, - Sex = weChatUser.Sex, - Province = weChatUser.Province, - City = weChatUser.City, - NickName = weChatUser.NickName, - Headimgurl = weChatUser.Headimgurl, - PhoneNumber = weChatUser.PhoneNumber, - Country = weChatUser.Country, - Privilege = weChatUser.Privilege, - CreatedAt = DateTime.UtcNow, - }; - - _dc.WeChatUsers.InsertOne(weChatUserInfo); - - return weChatUserInfo.ToWeChatUser(); - } - - public WeChatUser? UpdateWeChatUser(WeChatUser weChatUser) - { - if (weChatUser == null) return null; - - var filter = Builders.Filter.Eq(x => x.Id, weChatUser.Id); - var update = Builders.Update - .Set(x => x.OpenId, weChatUser.OpenId) - .Set(x => x.UnionId, weChatUser.UnionId) - .Set(x => x.Sex, weChatUser.Sex) - .Set(x => x.Province, weChatUser.Province) - .Set(x => x.City, weChatUser.City) - .Set(x => x.NickName, weChatUser.NickName) - .Set(x => x.Headimgurl, weChatUser.Headimgurl) - .Set(x => x.PhoneNumber, weChatUser.PhoneNumber) - .Set(x => x.Country, weChatUser.Country) - .Set(x => x.Privilege, weChatUser.Privilege) - .Set(x => x.UpdatedAt, DateTime.UtcNow); - - _dc.WeChatUsers.UpdateOne(filter, update); - - return weChatUser; - } -} diff --git a/src/WebStarter/appsettings.json b/src/WebStarter/appsettings.json index 3efc0b4d..c3d4bdd5 100644 --- a/src/WebStarter/appsettings.json +++ b/src/WebStarter/appsettings.json @@ -273,16 +273,6 @@ "WeixinAppSecret": "#{WeixinAppSecret}#" }, - "WeChatQtoss": { - "AppId": "", - "AppSecret": "" - }, - - "WeChatQtossAI": { - "AppId": "", - "AppSecret": "" - }, - "KnowledgeBase": { "VectorDb": { "Provider": "Qdrant" From f5b2999408295a0d089c3b0b28d874da08adf321 Mon Sep 17 00:00:00 2001 From: AnonymousDotNet <18776095145@163.com> Date: Sat, 14 Dec 2024 17:19:40 +0800 Subject: [PATCH 19/48] fix: Add regionCode to GetUserByUserName API --- .../Repositories/IBotSharpRepository.cs | 2 +- .../Repository/FileRepository/FileRepository.User.cs | 4 ++-- .../BotSharp.Core/Users/Services/UserService.cs | 10 +++++----- .../Repository/MongoRepository.User.cs | 10 +++++----- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs index 3fca7372..9fe1619e 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs @@ -32,7 +32,7 @@ public interface IBotSharpRepository : IHaveServiceProvider User? GetUserById(string id) => throw new NotImplementedException(); List GetUserByIds(List ids) => throw new NotImplementedException(); List GetUsersByAffiliateId(string affiliateId) => throw new NotImplementedException(); - User? GetUserByUserName(string userName) => throw new NotImplementedException(); + User? GetUserByUserName(string userName, string regionCode = "CN") => throw new NotImplementedException(); Dashboard? GetDashboard(string id = null) => throw new NotImplementedException(); void CreateUser(User user) => throw new NotImplementedException(); void UpdateExistUser(string userId, User user) => throw new NotImplementedException(); diff --git a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.User.cs b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.User.cs index 9d5b42be..989c9ef9 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.User.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.User.cs @@ -48,9 +48,9 @@ public partial class FileRepository return Users.Where(x => x.AffiliateId == affiliateId).ToList(); } - public User? GetUserByUserName(string userName = null) + public User? GetUserByUserName(string userName = null, string regionCode = "CN") { - return Users.FirstOrDefault(x => x.UserName == userName.ToLower()); + return Users.FirstOrDefault(x => x.UserName == userName.ToLower() && x.RegionCode == regionCode.ToLower()); } public Dashboard? GetDashboard(string id = null) diff --git a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs index a87c55fa..991ef0df 100644 --- a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs +++ b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs @@ -50,7 +50,7 @@ public class UserService : IUserService if (!string.IsNullOrWhiteSpace(user.UserName)) { - record = db.GetUserByUserName(user.UserName); + record = db.GetUserByUserName(user.UserName, regionCode: user.RegionCode); } if (record != null && record.Verified) @@ -214,7 +214,7 @@ public class UserService : IUserService var (id, password, regionCode) = base64.SplitAsTuple(":"); var db = _services.GetRequiredService(); - var record = id.Contains("@") ? db.GetUserByEmail(id) : db.GetUserByUserName(id); + var record = id.Contains("@") ? db.GetUserByEmail(id) : db.GetUserByUserName(id, regionCode: regionCode); if (record == null) { record = db.GetUserByPhone(id, regionCode: regionCode); @@ -384,7 +384,7 @@ public class UserService : IUserService } else if (_user.UserName != null) { - user = db.GetUserByUserName(_user.UserName); + user = db.GetUserByUserName(_user.UserName, _user.RegionCode); } else if (_user.Email != null) { @@ -471,7 +471,7 @@ public class UserService : IUserService { var id = model.UserName; var db = _services.GetRequiredService(); - var record = id.Contains("@") ? db.GetUserByEmail(id) : db.GetUserByUserName(id); + var record = id.Contains("@") ? db.GetUserByEmail(id) : db.GetUserByUserName(id, regionCode: (string.IsNullOrWhiteSpace(model.RegionCode) ? "CN" : model.RegionCode)); if (record == null) { record = db.GetUserByPhone(id, regionCode: (string.IsNullOrWhiteSpace(model.RegionCode) ? "CN" : model.RegionCode)); @@ -515,7 +515,7 @@ public class UserService : IUserService var db = _services.GetRequiredService(); - var user = db.GetUserByUserName(userName); + var user = db.GetUserByUserName(userName, regionCode: "CN"); if (user != null && user.Verified) { return true; diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs index 3c76e21d..c463541f 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs @@ -61,9 +61,9 @@ public partial class MongoRepository return users?.Any() == true ? users.Select(x => x.ToUser()).ToList() : new List(); } - public User? GetUserByUserName(string userName) + public User? GetUserByUserName(string userName, string regionCode = "CN") { - var user = _dc.Users.AsQueryable().FirstOrDefault(x => x.UserName == userName.ToLower()); + var user = _dc.Users.AsQueryable().FirstOrDefault(x => x.UserName == userName.ToLower() && x.RegionCode == regionCode.ToLower()); return user != null ? user.ToUser() : null; } @@ -331,10 +331,10 @@ public partial class MongoRepository .FirstOrDefault(x => x.Id == userId || (x.ExternalId != null && x.ExternalId == userId)); if (user == null) return; var curDash = user.Dashboard ?? new Dashboard(); - curDash.ConversationList.Add(new DashboardConversation - { + curDash.ConversationList.Add(new DashboardConversation + { Id = Guid.NewGuid().ToString(), - ConversationId = conversationId + ConversationId = conversationId }); var filter = Builders.Filter.Eq(x => x.Id, userId); From 617a0119f461a5ec4e1eda61cf2d8d187abb9c21 Mon Sep 17 00:00:00 2001 From: YouWeiDH Date: Sat, 14 Dec 2024 18:36:51 +0800 Subject: [PATCH 20/48] hdong: create token by current user. --- .../BotSharp.Abstraction/Users/IUserService.cs | 1 + .../BotSharp.Core/Users/Services/UserService.cs | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/Infrastructure/BotSharp.Abstraction/Users/IUserService.cs b/src/Infrastructure/BotSharp.Abstraction/Users/IUserService.cs index 134ca25b..5e56b431 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Users/IUserService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Users/IUserService.cs @@ -17,6 +17,7 @@ public interface IUserService Task GetAffiliateToken(string authorization); Task GetAdminToken(string authorization); Task GetToken(string authorization); + Task CreateTokenByUser(User user); Task GetMyProfile(); Task VerifyUserNameExisting(string userName); Task VerifyEmailExisting(string email); diff --git a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs index a87c55fa..18deb7d8 100644 --- a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs +++ b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs @@ -506,6 +506,20 @@ public class UserService : IUserService return token; } + public async Task CreateTokenByUser(User user) + { + var accessToken = GenerateJwtToken(user); + var jwt = new JwtSecurityTokenHandler().ReadJwtToken(accessToken); + var token = new Token + { + AccessToken = accessToken, + ExpireTime = jwt.Payload.Exp.Value, + TokenType = "Bearer", + Scope = "api" + }; + return token; + } + public async Task VerifyUserNameExisting(string userName) { if (string.IsNullOrEmpty(userName)) From b3bdc01fc8b23940001d3cbfc542331e3f6a4b8b Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Sun, 15 Dec 2024 16:27:37 +0000 Subject: [PATCH 21/48] Add machine and retry to Redis Event message --- .../Infrastructures/Events/RedisPublisher.cs | 26 +++++++++++------ .../Infrastructures/Events/RedisSubscriber.cs | 28 ++++++++++++------- 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs index 89de2453..602fde53 100644 --- a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs +++ b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs @@ -39,10 +39,7 @@ public class RedisPublisher : IEventPublisher // Add a message to the stream, keeping only the latest 1 million messages var messageId = await db.StreamAddAsync(channel, - [ - new NameValueEntry("message", message), - new NameValueEntry("timestamp", DateTime.UtcNow.ToString("o")) - ], + AssembleMessage(message), maxLength: 1000 * 10000); _logger.LogInformation($"Published message {channel} {message} ({messageId})"); @@ -82,6 +79,17 @@ public class RedisPublisher : IEventPublisher return exists; } + private NameValueEntry[] AssembleMessage(RedisValue message, int retry = 0) + { + return + [ + new NameValueEntry("message", message), + new NameValueEntry("timestamp", DateTime.UtcNow.ToString("o")), + new NameValueEntry("machine", Environment.MachineName), + new NameValueEntry("retry", retry), + ]; + } + public async Task ReDispatchAsync(string channel, int count = 10, string order = "asc") { var db = _redis.GetDatabase(); @@ -93,10 +101,12 @@ public class RedisPublisher : IEventPublisher try { - var messageId = await db.StreamAddAsync(channel, [ - new NameValueEntry("message", entry.Values[0].Value), - new NameValueEntry("timestamp", DateTime.UtcNow.ToString("o")) - ]); + var message = entry.Values.First(x => x.Name == "message").Value; + var retryKv = entry.Values.FirstOrDefault(x => x.Name == "retry"); + int.TryParse(retryKv.Value, out int retry); + var messageId = await db.StreamAddAsync(channel, + AssembleMessage(message, retry: retry + 1), + maxLength: 1000 * 10000); _logger.LogWarning($"ReDispatched message: {channel} {entry.Values[0].Value} ({messageId})"); diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs index 9a3c9982..fb035aeb 100644 --- a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs +++ b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs @@ -58,23 +58,31 @@ public class RedisSubscriber : IEventSubscriber break; } - if (priorityEnabled) + try { - if (await HandleGroupMessage(db, $"{channel}-{EventPriority.High}", group, consumer, received) > 0) + if (priorityEnabled) { - continue; - } + if (await HandleGroupMessage(db, $"{channel}-{EventPriority.High}", group, consumer, received) > 0) + { + continue; + } - if (await HandleGroupMessage(db, $"{channel}-{EventPriority.Medium}", group, consumer, received) > 0) + if (await HandleGroupMessage(db, $"{channel}-{EventPriority.Medium}", group, consumer, received) > 0) + { + continue; + } + + await HandleGroupMessage(db, $"{channel}-{EventPriority.Low}", group, consumer, received); + } + else { - continue; + await HandleGroupMessage(db, channel, group, consumer, received); } - - await HandleGroupMessage(db, $"{channel}-{EventPriority.Low}", group, consumer, received); } - else + catch (Exception ex) { - await HandleGroupMessage(db, channel, group, consumer, received); + _logger.LogError($"Error processing message: {ex.Message}\r\n{ex}"); + await Task.Delay(1000 * 60); } } } From dfa2f477a0e234aacca2ade9ee3dd9758580cbf9 Mon Sep 17 00:00:00 2001 From: AnonymousDotNet <18776095145@163.com> Date: Mon, 16 Dec 2024 09:58:57 +0800 Subject: [PATCH 22/48] revert: #58 --- .../Repositories/IBotSharpRepository.cs | 2 +- .../Repository/FileRepository/FileRepository.User.cs | 4 ++-- .../BotSharp.Core/Users/Services/UserService.cs | 10 +++++----- .../Repository/MongoRepository.User.cs | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs index acb6a77c..87d4fd99 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs @@ -32,7 +32,7 @@ public interface IBotSharpRepository : IHaveServiceProvider User? GetUserById(string id) => throw new NotImplementedException(); List GetUserByIds(List ids) => throw new NotImplementedException(); List GetUsersByAffiliateId(string affiliateId) => throw new NotImplementedException(); - User? GetUserByUserName(string userName, string regionCode = "CN") => throw new NotImplementedException(); + User? GetUserByUserName(string userName) => throw new NotImplementedException(); Dashboard? GetDashboard(string id = null) => throw new NotImplementedException(); void CreateUser(User user) => throw new NotImplementedException(); void UpdateExistUser(string userId, User user) => throw new NotImplementedException(); diff --git a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.User.cs b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.User.cs index 989c9ef9..9d5b42be 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.User.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.User.cs @@ -48,9 +48,9 @@ public partial class FileRepository return Users.Where(x => x.AffiliateId == affiliateId).ToList(); } - public User? GetUserByUserName(string userName = null, string regionCode = "CN") + public User? GetUserByUserName(string userName = null) { - return Users.FirstOrDefault(x => x.UserName == userName.ToLower() && x.RegionCode == regionCode.ToLower()); + return Users.FirstOrDefault(x => x.UserName == userName.ToLower()); } public Dashboard? GetDashboard(string id = null) diff --git a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs index 991ef0df..a87c55fa 100644 --- a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs +++ b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs @@ -50,7 +50,7 @@ public class UserService : IUserService if (!string.IsNullOrWhiteSpace(user.UserName)) { - record = db.GetUserByUserName(user.UserName, regionCode: user.RegionCode); + record = db.GetUserByUserName(user.UserName); } if (record != null && record.Verified) @@ -214,7 +214,7 @@ public class UserService : IUserService var (id, password, regionCode) = base64.SplitAsTuple(":"); var db = _services.GetRequiredService(); - var record = id.Contains("@") ? db.GetUserByEmail(id) : db.GetUserByUserName(id, regionCode: regionCode); + var record = id.Contains("@") ? db.GetUserByEmail(id) : db.GetUserByUserName(id); if (record == null) { record = db.GetUserByPhone(id, regionCode: regionCode); @@ -384,7 +384,7 @@ public class UserService : IUserService } else if (_user.UserName != null) { - user = db.GetUserByUserName(_user.UserName, _user.RegionCode); + user = db.GetUserByUserName(_user.UserName); } else if (_user.Email != null) { @@ -471,7 +471,7 @@ public class UserService : IUserService { var id = model.UserName; var db = _services.GetRequiredService(); - var record = id.Contains("@") ? db.GetUserByEmail(id) : db.GetUserByUserName(id, regionCode: (string.IsNullOrWhiteSpace(model.RegionCode) ? "CN" : model.RegionCode)); + var record = id.Contains("@") ? db.GetUserByEmail(id) : db.GetUserByUserName(id); if (record == null) { record = db.GetUserByPhone(id, regionCode: (string.IsNullOrWhiteSpace(model.RegionCode) ? "CN" : model.RegionCode)); @@ -515,7 +515,7 @@ public class UserService : IUserService var db = _services.GetRequiredService(); - var user = db.GetUserByUserName(userName, regionCode: "CN"); + var user = db.GetUserByUserName(userName); if (user != null && user.Verified) { return true; diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs index c463541f..2c4676ca 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs @@ -61,9 +61,9 @@ public partial class MongoRepository return users?.Any() == true ? users.Select(x => x.ToUser()).ToList() : new List(); } - public User? GetUserByUserName(string userName, string regionCode = "CN") + public User? GetUserByUserName(string userName) { - var user = _dc.Users.AsQueryable().FirstOrDefault(x => x.UserName == userName.ToLower() && x.RegionCode == regionCode.ToLower()); + var user = _dc.Users.AsQueryable().FirstOrDefault(x => x.UserName == userName.ToLower()); return user != null ? user.ToUser() : null; } From 5369565701e159fb2a66bc65ce51cb2ba2b96e36 Mon Sep 17 00:00:00 2001 From: AnonymousDotNet <18776095145@163.com> Date: Mon, 16 Dec 2024 13:04:00 +0800 Subject: [PATCH 23/48] fix: update UpdateExistUser API --- .../Repository/MongoRepository.User.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs index 2c4676ca..0c2eb95c 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs @@ -102,6 +102,7 @@ public partial class MongoRepository { var filter = Builders.Filter.Eq(x => x.Id, userId); var update = Builders.Update + .Set(x => x.UserName, user.UserName) .Set(x => x.Email, user.Email) .Set(x => x.Phone, user.Phone) .Set(x => x.Salt, user.Salt) From ae8e2d3100726b02f25fa262ed933c81803a9d35 Mon Sep 17 00:00:00 2001 From: AnonymousDotNet <18776095145@163.com> Date: Mon, 16 Dec 2024 21:59:12 +0800 Subject: [PATCH 24/48] feat: add UpdateUserName API --- .../Repositories/IBotSharpRepository.cs | 1 + .../Repository/MongoRepository.User.cs | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs index 87d4fd99..35cb60df 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs @@ -33,6 +33,7 @@ public interface IBotSharpRepository : IHaveServiceProvider List GetUserByIds(List ids) => throw new NotImplementedException(); List GetUsersByAffiliateId(string affiliateId) => throw new NotImplementedException(); User? GetUserByUserName(string userName) => throw new NotImplementedException(); + void UpdateUserName(string userId, string userName) => throw new NotImplementedException(); Dashboard? GetDashboard(string id = null) => throw new NotImplementedException(); void CreateUser(User user) => throw new NotImplementedException(); void UpdateExistUser(string userId, User user) => throw new NotImplementedException(); diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs index 0c2eb95c..5dc088c5 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs @@ -113,6 +113,14 @@ public partial class MongoRepository _dc.Users.UpdateOne(filter, update); } + public void UpdateUserName(string userId, string userName) + { + var filter = Builders.Filter.Eq(x => x.Id, userId); + var update = Builders.Update + .Set(x => x.UserName, userName); + _dc.Users.UpdateOne(filter, update); + } + public void UpdateUserVerified(string userId) { var filter = Builders.Filter.Eq(x => x.Id, userId); From 5e70f10b83fef32b055ee5d2b4b22a994b24f7d3 Mon Sep 17 00:00:00 2001 From: AnonymousDotNet <18776095145@163.com> Date: Mon, 16 Dec 2024 22:01:06 +0800 Subject: [PATCH 25/48] revert: remove updated username --- .../Repository/MongoRepository.User.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs index 5dc088c5..f6bdbbdf 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs @@ -102,7 +102,6 @@ public partial class MongoRepository { var filter = Builders.Filter.Eq(x => x.Id, userId); var update = Builders.Update - .Set(x => x.UserName, user.UserName) .Set(x => x.Email, user.Email) .Set(x => x.Phone, user.Phone) .Set(x => x.Salt, user.Salt) From 3c4821c368e63e5b96dbe333227f6829ae3f201f Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Tue, 17 Dec 2024 01:18:24 +0000 Subject: [PATCH 26/48] EntityFrameworkCore.BootKit v8.7 --- src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj | 4 ++-- .../BotSharp.Plugin.MongoStorage.csproj | 2 +- .../BotSharp.Plugin.WebDriver.csproj | 5 +---- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj index 1c9955aa..d7f6cdde 100644 --- a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj +++ b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj @@ -190,10 +190,10 @@ - + - + diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/BotSharp.Plugin.MongoStorage.csproj b/src/Plugins/BotSharp.Plugin.MongoStorage/BotSharp.Plugin.MongoStorage.csproj index 88709238..5ac884e0 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/BotSharp.Plugin.MongoStorage.csproj +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/BotSharp.Plugin.MongoStorage.csproj @@ -11,7 +11,7 @@ - + diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/BotSharp.Plugin.WebDriver.csproj b/src/Plugins/BotSharp.Plugin.WebDriver/BotSharp.Plugin.WebDriver.csproj index 296e17c3..fde5adc9 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/BotSharp.Plugin.WebDriver.csproj +++ b/src/Plugins/BotSharp.Plugin.WebDriver/BotSharp.Plugin.WebDriver.csproj @@ -12,15 +12,12 @@ - - - - + From 067a701ff1f2277c653ad201b9396749844fb09a Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Tue, 17 Dec 2024 06:37:18 +0000 Subject: [PATCH 27/48] remove retry --- .../Infrastructures/Events/RedisPublisher.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs index 602fde53..5b32cd5a 100644 --- a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs +++ b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs @@ -79,14 +79,13 @@ public class RedisPublisher : IEventPublisher return exists; } - private NameValueEntry[] AssembleMessage(RedisValue message, int retry = 0) + private NameValueEntry[] AssembleMessage(RedisValue message) { return [ new NameValueEntry("message", message), new NameValueEntry("timestamp", DateTime.UtcNow.ToString("o")), - new NameValueEntry("machine", Environment.MachineName), - new NameValueEntry("retry", retry), + new NameValueEntry("machine", Environment.MachineName) ]; } @@ -102,10 +101,8 @@ public class RedisPublisher : IEventPublisher try { var message = entry.Values.First(x => x.Name == "message").Value; - var retryKv = entry.Values.FirstOrDefault(x => x.Name == "retry"); - int.TryParse(retryKv.Value, out int retry); var messageId = await db.StreamAddAsync(channel, - AssembleMessage(message, retry: retry + 1), + AssembleMessage(message), maxLength: 1000 * 10000); _logger.LogWarning($"ReDispatched message: {channel} {entry.Values[0].Value} ({messageId})"); From ab3e2e99dade2f0a53b2c98d227dae46f79a1b0f Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Tue, 17 Dec 2024 06:48:45 +0000 Subject: [PATCH 28/48] remove machine --- .../BotSharp.Core/Infrastructures/Events/RedisPublisher.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs index 5b32cd5a..b6517535 100644 --- a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs +++ b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs @@ -84,8 +84,7 @@ public class RedisPublisher : IEventPublisher return [ new NameValueEntry("message", message), - new NameValueEntry("timestamp", DateTime.UtcNow.ToString("o")), - new NameValueEntry("machine", Environment.MachineName) + new NameValueEntry("timestamp", DateTime.UtcNow.ToString("o")) ]; } From a2e87bee79021fd41c51b930a3dea3e53129ce0f Mon Sep 17 00:00:00 2001 From: AnonymousDotNet <18776095145@163.com> Date: Wed, 18 Dec 2024 16:59:10 +0800 Subject: [PATCH 29/48] fix: Remove Update UserName --- .../Repository/MongoRepository.User.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs index f6bdbbdf..29bd36be 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs @@ -159,7 +159,7 @@ public partial class MongoRepository var update = Builders.Update.Set(x => x.Phone, phone) .Set(x => x.UpdatedTime, DateTime.UtcNow) .Set(x => x.RegionCode, regionCode) - .Set(x => x.UserName, phone) + //.Set(x => x.UserName, phone) .Set(x => x.FirstName, phone); _dc.Users.UpdateOne(filter, update); } From adcb07e9dca861dfe8befb06ec54cef641e155bc Mon Sep 17 00:00:00 2001 From: YouWeiDH Date: Thu, 19 Dec 2024 17:34:04 +0800 Subject: [PATCH 30/48] hdong:split tow system user creation service. --- src/Infrastructure/BotSharp.Abstraction/Users/Models/User.cs | 1 - .../BotSharp.OpenAPI/Controllers/UserController.cs | 2 +- .../BotSharp.OpenAPI/ViewModels/Users/UserCreationModel.cs | 2 -- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Users/Models/User.cs b/src/Infrastructure/BotSharp.Abstraction/Users/Models/User.cs index 7699a58b..8d136dc5 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Users/Models/User.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Users/Models/User.cs @@ -23,7 +23,6 @@ public class User public bool Verified { get; set; } public string RegionCode { get; set; } = "CN"; public string? AffiliateId { get; set; } - public string? ReferralCode { get; set; } public string? EmployeeId { get; set; } public bool IsDisabled { get; set; } public IEnumerable Permissions { get; set; } = []; diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs index c893bcab..75b33c73 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs @@ -243,7 +243,7 @@ public class UserController : ControllerBase var file = fileStorage.GetUserAvatar(); if (string.IsNullOrEmpty(file)) { - return NotFound(); + return NoContent(); } return BuildFileResult(file); } diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Users/UserCreationModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Users/UserCreationModel.cs index b529a832..4d2594b8 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Users/UserCreationModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Users/UserCreationModel.cs @@ -13,7 +13,6 @@ public class UserCreationModel public string Type { get; set; } = UserType.Client; public string Role { get; set; } = UserRole.User; public string RegionCode { get; set; } = "CN"; - public string? ReferralCode { get; set; } public User ToUser() { return new User @@ -27,7 +26,6 @@ public class UserCreationModel Role = Role, Type = Type, RegionCode = RegionCode, - ReferralCode = ReferralCode }; } } From bb73f303a81aa735c973dbc5ef653c6fda21902e Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Sat, 21 Dec 2024 00:39:35 +0000 Subject: [PATCH 31/48] Remove Selenium --- .../BotSharp.Plugin.Selenium.csproj | 22 ++++++++++++++++++ .../Drivers}/SeleniumInstance.cs | 2 +- .../Drivers}/SeleniumWebDriver.DoAction.cs | 3 +-- .../SeleniumWebDriver.EvaluateScript.cs | 2 +- .../SeleniumWebDriver.GetAttributeValue.cs | 2 +- .../Drivers}/SeleniumWebDriver.GoToPage.cs | 2 +- .../Drivers}/SeleniumWebDriver.HttpRequest.cs | 2 +- .../SeleniumWebDriver.LaunchBrowser.cs | 2 +- .../SeleniumWebDriver.LocateElement.cs | 3 +-- .../Drivers}/SeleniumWebDriver.cs | 7 +++++- src/Plugins/BotSharp.Plugin.Selenium/Using.cs | 23 +++++++++++++++++++ .../BotSharp.Plugin.WebDriver.csproj | 8 +------ 12 files changed, 60 insertions(+), 18 deletions(-) create mode 100644 src/Plugins/BotSharp.Plugin.Selenium/BotSharp.Plugin.Selenium.csproj rename src/Plugins/{BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver => BotSharp.Plugin.Selenium/Drivers}/SeleniumInstance.cs (97%) rename src/Plugins/{BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver => BotSharp.Plugin.Selenium/Drivers}/SeleniumWebDriver.DoAction.cs (93%) rename src/Plugins/{BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver => BotSharp.Plugin.Selenium/Drivers}/SeleniumWebDriver.EvaluateScript.cs (86%) rename src/Plugins/{BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver => BotSharp.Plugin.Selenium/Drivers}/SeleniumWebDriver.GetAttributeValue.cs (91%) rename src/Plugins/{BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver => BotSharp.Plugin.Selenium/Drivers}/SeleniumWebDriver.GoToPage.cs (92%) rename src/Plugins/{BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver => BotSharp.Plugin.Selenium/Drivers}/SeleniumWebDriver.HttpRequest.cs (95%) rename src/Plugins/{BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver => BotSharp.Plugin.Selenium/Drivers}/SeleniumWebDriver.LaunchBrowser.cs (85%) rename src/Plugins/{BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver => BotSharp.Plugin.Selenium/Drivers}/SeleniumWebDriver.LocateElement.cs (97%) rename src/Plugins/{BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver => BotSharp.Plugin.Selenium/Drivers}/SeleniumWebDriver.cs (93%) create mode 100644 src/Plugins/BotSharp.Plugin.Selenium/Using.cs diff --git a/src/Plugins/BotSharp.Plugin.Selenium/BotSharp.Plugin.Selenium.csproj b/src/Plugins/BotSharp.Plugin.Selenium/BotSharp.Plugin.Selenium.csproj new file mode 100644 index 00000000..2a4e3e08 --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.Selenium/BotSharp.Plugin.Selenium.csproj @@ -0,0 +1,22 @@ + + + + $(TargetFramework) + enable + $(LangVersion) + $(BotSharpVersion) + $(GeneratePackageOnBuild) + $(GenerateDocumentationFile) + $(SolutionDir)packages + + + + + + + + + + + + diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumInstance.cs b/src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumInstance.cs similarity index 97% rename from src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumInstance.cs rename to src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumInstance.cs index 5e1f5eaf..253ba487 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumInstance.cs +++ b/src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumInstance.cs @@ -1,7 +1,7 @@ using OpenQA.Selenium.Chrome; using System.IO; -namespace BotSharp.Plugin.WebDriver.Drivers.SeleniumDriver; +namespace BotSharp.Plugin.Selenium.Drivers; public class SeleniumInstance : IDisposable { diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.DoAction.cs b/src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.DoAction.cs similarity index 93% rename from src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.DoAction.cs rename to src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.DoAction.cs index bb9afd87..931e6736 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.DoAction.cs +++ b/src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.DoAction.cs @@ -1,7 +1,6 @@ -using OpenQA.Selenium; using OpenQA.Selenium.Interactions; -namespace BotSharp.Plugin.WebDriver.Drivers.SeleniumDriver; +namespace BotSharp.Plugin.Selenium.Drivers; public partial class SeleniumWebDriver { diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.EvaluateScript.cs b/src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.EvaluateScript.cs similarity index 86% rename from src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.EvaluateScript.cs rename to src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.EvaluateScript.cs index 9a59cb81..3fb6b39a 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.EvaluateScript.cs +++ b/src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.EvaluateScript.cs @@ -1,4 +1,4 @@ -namespace BotSharp.Plugin.WebDriver.Drivers.SeleniumDriver; +namespace BotSharp.Plugin.Selenium.Drivers; public partial class SeleniumWebDriver { diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.GetAttributeValue.cs b/src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.GetAttributeValue.cs similarity index 91% rename from src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.GetAttributeValue.cs rename to src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.GetAttributeValue.cs index 0402b2db..ff99d29d 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.GetAttributeValue.cs +++ b/src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.GetAttributeValue.cs @@ -1,4 +1,4 @@ -namespace BotSharp.Plugin.WebDriver.Drivers.SeleniumDriver; +namespace BotSharp.Plugin.Selenium.Drivers; public partial class SeleniumWebDriver { diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.GoToPage.cs b/src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.GoToPage.cs similarity index 92% rename from src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.GoToPage.cs rename to src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.GoToPage.cs index db7d36a3..15a71480 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.GoToPage.cs +++ b/src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.GoToPage.cs @@ -1,4 +1,4 @@ -namespace BotSharp.Plugin.WebDriver.Drivers.SeleniumDriver; +namespace BotSharp.Plugin.Selenium.Drivers; public partial class SeleniumWebDriver { diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.HttpRequest.cs b/src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.HttpRequest.cs similarity index 95% rename from src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.HttpRequest.cs rename to src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.HttpRequest.cs index c9940318..affeaf62 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.HttpRequest.cs +++ b/src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.HttpRequest.cs @@ -1,6 +1,6 @@ using System.Net.Http; -namespace BotSharp.Plugin.WebDriver.Drivers.SeleniumDriver; +namespace BotSharp.Plugin.Selenium.Drivers; public partial class SeleniumWebDriver { diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.LaunchBrowser.cs b/src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.LaunchBrowser.cs similarity index 85% rename from src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.LaunchBrowser.cs rename to src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.LaunchBrowser.cs index 4e8b6498..9c104a59 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.LaunchBrowser.cs +++ b/src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.LaunchBrowser.cs @@ -1,4 +1,4 @@ -namespace BotSharp.Plugin.WebDriver.Drivers.SeleniumDriver; +namespace BotSharp.Plugin.Selenium.Drivers; public partial class SeleniumWebDriver { diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.LocateElement.cs b/src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.LocateElement.cs similarity index 97% rename from src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.LocateElement.cs rename to src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.LocateElement.cs index 4d96b9a6..184106a5 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.LocateElement.cs +++ b/src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.LocateElement.cs @@ -1,7 +1,6 @@ -using OpenQA.Selenium; using System.Collections.ObjectModel; -namespace BotSharp.Plugin.WebDriver.Drivers.SeleniumDriver; +namespace BotSharp.Plugin.Selenium.Drivers; public partial class SeleniumWebDriver { diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.cs b/src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.cs similarity index 93% rename from src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.cs rename to src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.cs index 15dd0bc1..0e6dd0a3 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/SeleniumDriver/SeleniumWebDriver.cs +++ b/src/Plugins/BotSharp.Plugin.Selenium/Drivers/SeleniumWebDriver.cs @@ -1,4 +1,4 @@ -namespace BotSharp.Plugin.WebDriver.Drivers.SeleniumDriver; +namespace BotSharp.Plugin.Selenium.Drivers; public partial class SeleniumWebDriver : IWebBrowser { @@ -86,4 +86,9 @@ public partial class SeleniumWebDriver : IWebBrowser { throw new NotImplementedException(); } + + public Task PressKey(MessageInfo message, string key) + { + throw new NotImplementedException(); + } } diff --git a/src/Plugins/BotSharp.Plugin.Selenium/Using.cs b/src/Plugins/BotSharp.Plugin.Selenium/Using.cs new file mode 100644 index 00000000..abadf8fa --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.Selenium/Using.cs @@ -0,0 +1,23 @@ +global using System; +global using System.Collections.Generic; +global using System.Text; +global using System.Threading.Tasks; +global using System.Text.Json; +global using System.Linq; +global using System.Text.RegularExpressions; +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Logging; +global using BotSharp.Abstraction.Browsing.Enums; +global using BotSharp.Abstraction.Conversations; +global using BotSharp.Abstraction.Plugins; +global using BotSharp.Abstraction.Conversations.Models; +global using BotSharp.Abstraction.Functions; +global using BotSharp.Abstraction.Agents.Models; +global using BotSharp.Abstraction.Templating; +global using BotSharp.Abstraction.Agents; +global using BotSharp.Abstraction.Utilities; +global using BotSharp.Abstraction.Browsing.Models; +global using BotSharp.Abstraction.Browsing; + +global using OpenQA.Selenium; \ No newline at end of file diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/BotSharp.Plugin.WebDriver.csproj b/src/Plugins/BotSharp.Plugin.WebDriver/BotSharp.Plugin.WebDriver.csproj index fde5adc9..15c2868c 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/BotSharp.Plugin.WebDriver.csproj +++ b/src/Plugins/BotSharp.Plugin.WebDriver/BotSharp.Plugin.WebDriver.csproj @@ -3,19 +3,13 @@ $(TargetFramework) enable - 12.0 + $(LangVersion) $(BotSharpVersion) $(GeneratePackageOnBuild) $(GenerateDocumentationFile) $(SolutionDir)packages - - - - - - From 103517088667fd9775cb13caace69d541b66ffdf Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Sat, 21 Dec 2024 15:41:15 +0000 Subject: [PATCH 32/48] =?UTF-8?q?=E4=BF=AE=E5=A4=8DFastMoss=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E6=94=B9=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs index fb035aeb..d53c9400 100644 --- a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs +++ b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs @@ -105,6 +105,8 @@ public class RedisSubscriber : IEventSubscriber catch (Exception ex) { _logger.LogError($"Error processing message: {ex.Message}, event id: {channel} {entry.Id}\r\n{ex}"); + // Slow down the consumer if there are errors + await Task.Delay(1000 * 10); } } From e8d182494acd662b05c06b56e947d2047b9dcd76 Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Mon, 23 Dec 2024 19:53:04 +0000 Subject: [PATCH 33/48] test webview2 --- .../Browsing/Models/BrowserActionArgs.cs | 2 + .../BotSharp.Core/BotSharp.Core.csproj | 2 +- .../PlaywrightDriver/PlaywrightInstance.cs | 48 +++++++++++-------- .../PlaywrightWebDriver.GoToPage.cs | 30 +++++++----- 4 files changed, 50 insertions(+), 32 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/BrowserActionArgs.cs b/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/BrowserActionArgs.cs index 21bdf6ab..7987b3a5 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/BrowserActionArgs.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/BrowserActionArgs.cs @@ -3,4 +3,6 @@ namespace BotSharp.Abstraction.Browsing.Models; public class BrowserActionArgs { public bool Headless { get; set; } + public string? UserDataDir { get; set; } + public string? RemoteHostUrl { get; set; } } diff --git a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj index d7f6cdde..23351fb5 100644 --- a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj +++ b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj @@ -190,7 +190,7 @@ - + diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs index b5155cd5..f14e4bdc 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs @@ -45,28 +45,36 @@ public class PlaywrightInstance : IDisposable _playwright = await Playwright.CreateAsync(); } - string tempFolderPath = $"{Path.GetTempPath()}\\playwright\\{ctxId}"; - - _contexts[ctxId] = await _playwright.Chromium.LaunchPersistentContextAsync(tempFolderPath, new BrowserTypeLaunchPersistentContextOptions + if (!string.IsNullOrEmpty(args.RemoteHostUrl)) { - Headless = args.Headless, - Channel = "chrome", - ViewportSize = new ViewportSize + var browser = await _playwright.Chromium.ConnectOverCDPAsync(args.RemoteHostUrl); + _contexts[ctxId] = browser.Contexts[0]; + } + else + { + string userDataDir = args.UserDataDir ?? $"{Path.GetTempPath()}\\playwright\\{ctxId}"; + _contexts[ctxId] = await _playwright.Chromium.LaunchPersistentContextAsync(userDataDir, new BrowserTypeLaunchPersistentContextOptions { - Width = 1600, - Height = 900 - }, - IgnoreDefaultArgs = - [ - "--enable-automation", - ], - Args = - [ - "--disable-infobars", - "--test-type" - // "--start-maximized" - ] - }); + Headless = args.Headless, + Channel = "chrome", + ViewportSize = new ViewportSize + { + Width = 1600, + Height = 900 + }, + IgnoreDefaultArgs = + [ + "--enable-automation", + ], + Args = + [ + "--disable-infobars", + "--test-type" + // "--start-maximized" + ] + }); + } + _pages[ctxId] = new List(); _contexts[ctxId].Page += async (sender, page) => diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.GoToPage.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.GoToPage.cs index 2f339ca6..0a0a5425 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.GoToPage.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.GoToPage.cs @@ -8,22 +8,30 @@ public partial class PlaywrightWebDriver var context = await _instance.GetContext(message.ContextId); try { - var page = await _instance.NewPage(message, enableResponseCallback: args.EnableResponseCallback, - responseInMemory: args.ResponseInMemory, - responseContainer: args.ResponseContainer, - excludeResponseUrls: args.ExcludeResponseUrls, - includeResponseUrls: args.IncludeResponseUrls); - - Serilog.Log.Information($"goto page: {args.Url}"); - - if (args.OpenNewTab && page != null && page.Url == "about:blank") + IPage? page = null; + if (!args.OpenNewTab && !args.EnableResponseCallback) { - page = await _instance.NewPage(message, - enableResponseCallback: args.EnableResponseCallback, + page = _instance.Contexts[message.ContextId].Pages.LastOrDefault(); + } + else + { + page = await _instance.NewPage(message, enableResponseCallback: args.EnableResponseCallback, responseInMemory: args.ResponseInMemory, responseContainer: args.ResponseContainer, excludeResponseUrls: args.ExcludeResponseUrls, includeResponseUrls: args.IncludeResponseUrls); + + Serilog.Log.Information($"goto page: {args.Url}"); + + if (args.OpenNewTab && page != null && page.Url == "about:blank") + { + page = await _instance.NewPage(message, + enableResponseCallback: args.EnableResponseCallback, + responseInMemory: args.ResponseInMemory, + responseContainer: args.ResponseContainer, + excludeResponseUrls: args.ExcludeResponseUrls, + includeResponseUrls: args.IncludeResponseUrls); + } } if (page == null) From bf22260f59825b313bd73cc80aa571288ee5bcd1 Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Tue, 24 Dec 2024 21:22:17 +0000 Subject: [PATCH 34/48] =?UTF-8?q?=E5=95=86=E5=93=81=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PlaywrightWebDriver.LocateElement.cs | 7 +++++++ .../BotSharp.Plugin.WebDriver/WebPageHelper.cs | 17 ++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.LocateElement.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.LocateElement.cs index 8695fc5c..613d2b22 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.LocateElement.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.LocateElement.cs @@ -14,6 +14,13 @@ public partial class PlaywrightWebDriver { var result = new BrowserActionResult(); var page = _instance.GetPage(message.ContextId); + if (page == null) + { + return new BrowserActionResult + { + IsSuccess = false + }; + } ILocator locator = page.Locator("body"); int count = 0; diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/WebPageHelper.cs b/src/Plugins/BotSharp.Plugin.WebDriver/WebPageHelper.cs index 113403eb..aaf61aa4 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/WebPageHelper.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/WebPageHelper.cs @@ -1,10 +1,25 @@ using HtmlAgilityPack; -using System.Net.Http; namespace BotSharp.Plugin.WebDriver; public static class WebPageHelper { + public static HtmlNode GetElement(string html, string selector) + { + var htmlDoc = new HtmlDocument(); + htmlDoc.LoadHtml(html); + + return htmlDoc.DocumentNode.SelectSingleNode(selector); + } + + public static HtmlNodeCollection GetElements(string html, string selector) + { + var htmlDoc = new HtmlDocument(); + htmlDoc.LoadHtml(html); + + return htmlDoc.DocumentNode.SelectNodes(selector); + } + public static string RemoveElements(string html, string selector) { var htmlDoc = new HtmlDocument(); From d041d423501e7dd99219d1652ad6c97f55ddb0a4 Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Wed, 25 Dec 2024 21:00:07 +0000 Subject: [PATCH 35/48] UrlAfterAction --- .../Browsing/Models/BrowserActionResult.cs | 4 ++++ .../PlaywrightDriver/PlaywrightWebDriver.ActionOnElement.cs | 1 + 2 files changed, 5 insertions(+) diff --git a/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/BrowserActionResult.cs b/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/BrowserActionResult.cs index 1867a687..e2f11972 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/BrowserActionResult.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/BrowserActionResult.cs @@ -8,6 +8,10 @@ public class BrowserActionResult public string? StackTrace { get; set; } public string? Selector { get; set; } public string? Body { get; set; } + /// + /// Page open in new tab after button click + /// + public string? UrlAfterAction { get; set; } public bool IsHighlighted { get; set; } public override string ToString() diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.ActionOnElement.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.ActionOnElement.cs index ab1a0731..7a5f4820 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.ActionOnElement.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.ActionOnElement.cs @@ -9,6 +9,7 @@ public partial class PlaywrightWebDriver if (result.IsSuccess) { await DoAction(message, action, result); + result.UrlAfterAction = _instance.GetPage(message.ContextId)?.Url; } return result; } From 7b14c8375d83d03a9541a7581998b26ca1e5d99f Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Fri, 27 Dec 2024 18:16:23 +0000 Subject: [PATCH 36/48] Add Error channel --- .../Infrastructures/Events/RedisPublisher.cs | 12 +++++++++++- .../Infrastructures/Events/RedisSubscriber.cs | 18 ++++++++++++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs index b6517535..514f4aa1 100644 --- a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs +++ b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs @@ -79,7 +79,7 @@ public class RedisPublisher : IEventPublisher return exists; } - private NameValueEntry[] AssembleMessage(RedisValue message) + public static NameValueEntry[] AssembleMessage(RedisValue message) { return [ @@ -88,6 +88,16 @@ public class RedisPublisher : IEventPublisher ]; } + public static NameValueEntry[] AssembleErrorMessage(RedisValue message, string error) + { + return + [ + new NameValueEntry("message", message), + new NameValueEntry("timestamp", DateTime.UtcNow.ToString("o")), + new NameValueEntry("error", error) + ]; + } + public async Task ReDispatchAsync(string channel, int count = 10, string order = "asc") { var db = _redis.GetDatabase(); diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs index d53c9400..b3d910d9 100644 --- a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs +++ b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs @@ -42,6 +42,8 @@ public class RedisSubscriber : IEventSubscriber await CreateConsumerGroup(db, channel, group); } + await CreateConsumerGroup(db, $"{channel}-Error", group); + var consumer = Environment.MachineName; if (port.HasValue) { @@ -98,16 +100,24 @@ public class RedisSubscriber : IEventSubscriber try { await received(channel, entry.Values[0].Value); - - // Optionally delete the message to save space - await db.StreamDeleteAsync(channel, [entry.Id]); } catch (Exception ex) { - _logger.LogError($"Error processing message: {ex.Message}, event id: {channel} {entry.Id}\r\n{ex}"); + _logger.LogError($"Error processing message: {ex.Message}, event id: {channel} {entry.Id} {entry.Values[0].Value}"); + + // Add a message to the Error stream, keeping only the latest 1 million messages + await db.StreamAddAsync($"{channel}-Error", + RedisPublisher.AssembleErrorMessage(entry.Values[0].Value, ex.Message), + messageId: entry.Id, + maxLength: 1000 * 10000); + // Slow down the consumer if there are errors await Task.Delay(1000 * 10); } + finally + { + await db.StreamDeleteAsync(channel, [entry.Id]); + } } return entries.Length; From f2456caf35c0b343b695e1b0eb28ada2d6b68785 Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Sat, 28 Dec 2024 01:20:48 +0000 Subject: [PATCH 37/48] SetAttributeValue --- .../Browsing/IWebBrowser.cs | 1 + .../PlaywrightWebDriver.GetAttributeValue.cs | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/Infrastructure/BotSharp.Abstraction/Browsing/IWebBrowser.cs b/src/Infrastructure/BotSharp.Abstraction/Browsing/IWebBrowser.cs index ff2c4a7d..9386dd8a 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Browsing/IWebBrowser.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Browsing/IWebBrowser.cs @@ -28,4 +28,5 @@ public interface IWebBrowser Task CloseCurrentPage(MessageInfo message); Task SendHttpRequest(MessageInfo message, HttpRequestParams actionParams); Task GetAttributeValue(MessageInfo message, ElementLocatingArgs location); + Task SetAttributeValue(MessageInfo message, ElementLocatingArgs location); } diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.GetAttributeValue.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.GetAttributeValue.cs index 035bcf3b..ef266d08 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.GetAttributeValue.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.GetAttributeValue.cs @@ -19,4 +19,25 @@ public partial class PlaywrightWebDriver Body = value ?? string.Empty }; } + + public async Task SetAttributeValue(MessageInfo message, ElementLocatingArgs location) + { + var page = _instance.GetPage(message.ContextId); + ILocator locator = page.Locator(location.Selector); + var elementCount = await locator.CountAsync(); + + if (elementCount > 0) + { + foreach (var element in await locator.AllAsync()) + { + var script = $"element => element.{location.AttributeName} = '{location.AttributeValue}'"; + var result = await locator.EvaluateAsync(script); + } + } + + return new BrowserActionResult + { + IsSuccess = true + }; + } } From 68df1f14c465535fba7db6fc460d170723c90f4a Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Sun, 29 Dec 2024 16:23:31 +0000 Subject: [PATCH 38/48] Fix ErrorChannel --- .../Infrastructures/Events/RedisSubscriber.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs index b3d910d9..0dedb7c6 100644 --- a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs +++ b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs @@ -64,21 +64,21 @@ public class RedisSubscriber : IEventSubscriber { if (priorityEnabled) { - if (await HandleGroupMessage(db, $"{channel}-{EventPriority.High}", group, consumer, received) > 0) + if (await HandleGroupMessage(db, $"{channel}-{EventPriority.High}", group, consumer, received, $"{channel}-Error") > 0) { continue; } - if (await HandleGroupMessage(db, $"{channel}-{EventPriority.Medium}", group, consumer, received) > 0) + if (await HandleGroupMessage(db, $"{channel}-{EventPriority.Medium}", group, consumer, received, $"{channel}-Error") > 0) { continue; } - await HandleGroupMessage(db, $"{channel}-{EventPriority.Low}", group, consumer, received); + await HandleGroupMessage(db, $"{channel}-{EventPriority.Low}", group, consumer, received, $"{channel}-Error"); } else { - await HandleGroupMessage(db, channel, group, consumer, received); + await HandleGroupMessage(db, channel, group, consumer, received, $"{channel}-Error"); } } catch (Exception ex) @@ -89,7 +89,7 @@ public class RedisSubscriber : IEventSubscriber } } - private async Task HandleGroupMessage(IDatabase db, string channel, string group, string consumer, Func received) + private async Task HandleGroupMessage(IDatabase db, string channel, string group, string consumer, Func received, string errorChannel) { var entries = await db.StreamReadGroupAsync(channel, group, consumer, count: 1); foreach (var entry in entries) @@ -106,7 +106,7 @@ public class RedisSubscriber : IEventSubscriber _logger.LogError($"Error processing message: {ex.Message}, event id: {channel} {entry.Id} {entry.Values[0].Value}"); // Add a message to the Error stream, keeping only the latest 1 million messages - await db.StreamAddAsync($"{channel}-Error", + await db.StreamAddAsync(errorChannel, RedisPublisher.AssembleErrorMessage(entry.Values[0].Value, ex.Message), messageId: entry.Id, maxLength: 1000 * 10000); From 01fac4098219d35eff268cf30e4b8114d42a9e17 Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Sun, 29 Dec 2024 19:16:39 +0000 Subject: [PATCH 39/48] window.open('', '_blank') --- .../PlaywrightDriver/PlaywrightInstance.cs | 118 +++++++++--------- .../PlaywrightWebDriver.GoToPage.cs | 37 +++--- 2 files changed, 78 insertions(+), 77 deletions(-) diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs index f14e4bdc..bf58a5ac 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs @@ -108,12 +108,7 @@ public class PlaywrightInstance : IDisposable return _contexts[ctxId]; } - public async Task NewPage(MessageInfo message, - bool enableResponseCallback = false, - bool responseInMemory = false, - List? responseContainer = null, - string[]? excludeResponseUrls = null, - string[]? includeResponseUrls = null) + public async Task NewPage(MessageInfo message, PageActionArgs args) { var context = await GetContext(message.ContextId); var page = await context.NewPageAsync(); @@ -123,70 +118,75 @@ public class PlaywrightInstance : IDisposable var js = @"Object.defineProperties(navigator, {webdriver:{get:()=>false}});"; await page.AddInitScriptAsync(js); - if (!enableResponseCallback) + if (!args.EnableResponseCallback) { return page; } page.Response += async (sender, e) => { - if (e.Status != 204 && - e.Headers.ContainsKey("content-type") && - (e.Request.ResourceType == "fetch" || e.Request.ResourceType == "xhr") && - (excludeResponseUrls == null || !excludeResponseUrls.Any(url => e.Url.ToLower().Contains(url))) && - (includeResponseUrls == null || includeResponseUrls.Any(url => e.Url.ToLower().Contains(url)))) - { - Serilog.Log.Information($"{e.Request.Method}: {e.Url}"); - - try - { - var result = new WebPageResponseData - { - Url = e.Url.ToLower(), - PostData = e.Request?.PostData ?? string.Empty, - ResponseInMemory = responseInMemory - }; - - if (e.Headers["content-type"].Contains("application/json")) - { - if (e.Status == 200 && e.Ok) - { - var json = await e.JsonAsync(); - result.ResponseData = JsonSerializer.Serialize(json); - } - } - else - { - var html = await e.TextAsync(); - result.ResponseData = html; - } - - if (responseContainer != null && responseInMemory) - { - responseContainer.Add(result); - } - - Serilog.Log.Warning($"Response status: {e.Status} {e.StatusText}, OK: {e.Ok}"); - var webPageResponseHooks = _services.GetServices(); - foreach (var hook in webPageResponseHooks) - { - hook.OnDataFetched(message, result); - } - } - catch (ObjectDisposedException ex) - { - Serilog.Log.Information(ex.Message); - } - catch (Exception ex) - { - Serilog.Log.Error($"{e.Url}\r\n" + ex.ToString()); - } - } + await HandleFetchResponse(e, message, args); }; return page; } + public async Task HandleFetchResponse(IResponse response, MessageInfo message, PageActionArgs args) + { + if (response.Status != 204 && + response.Headers.ContainsKey("content-type") && + (response.Request.ResourceType == "fetch" || response.Request.ResourceType == "xhr") && + (args.ExcludeResponseUrls == null || !args.ExcludeResponseUrls.Any(url => response.Url.ToLower().Contains(url))) && + (args.IncludeResponseUrls == null || args.IncludeResponseUrls.Any(url => response.Url.ToLower().Contains(url)))) + { + Serilog.Log.Information($"{response.Request.Method}: {response.Url}"); + + try + { + var result = new WebPageResponseData + { + Url = response.Url.ToLower(), + PostData = response.Request?.PostData ?? string.Empty, + ResponseInMemory = args.ResponseInMemory + }; + + if (response.Headers["content-type"].Contains("application/json")) + { + if (response.Status == 200 && response.Ok) + { + var json = await response.JsonAsync(); + result.ResponseData = JsonSerializer.Serialize(json); + } + } + else + { + var html = await response.TextAsync(); + result.ResponseData = html; + } + + if (args.ResponseContainer != null && args.ResponseInMemory) + { + args.ResponseContainer.Add(result); + } + + Serilog.Log.Warning($"Response status: {response.Status} {response.StatusText}, OK: {response.Ok}"); + var webPageResponseHooks = _services.GetServices(); + foreach (var hook in webPageResponseHooks) + { + hook.OnDataFetched(message, result); + } + } + catch (ObjectDisposedException ex) + { + Serilog.Log.Information(ex.Message); + } + catch (Exception ex) + { + Serilog.Log.Error($"{response.Url}\r\n" + ex.ToString()); + } + } + } + /// /// Wait page and network until timeout in seconds /// diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.GoToPage.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.GoToPage.cs index 0a0a5425..7f0501cf 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.GoToPage.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.GoToPage.cs @@ -9,39 +9,40 @@ public partial class PlaywrightWebDriver try { IPage? page = null; - if (!args.OpenNewTab && !args.EnableResponseCallback) + if (!args.OpenNewTab) { page = _instance.Contexts[message.ContextId].Pages.LastOrDefault(); + + if (page != null) + { + await page.EvaluateAsync(@"() => { + window.open('', '_blank'); + }"); + + if (args.EnableResponseCallback) + { + page.Response += async (sender, e) => + { + await _instance.HandleFetchResponse(e, message, args); + }; + } + } } else { - page = await _instance.NewPage(message, enableResponseCallback: args.EnableResponseCallback, - responseInMemory: args.ResponseInMemory, - responseContainer: args.ResponseContainer, - excludeResponseUrls: args.ExcludeResponseUrls, - includeResponseUrls: args.IncludeResponseUrls); + page = await _instance.NewPage(message, args); Serilog.Log.Information($"goto page: {args.Url}"); if (args.OpenNewTab && page != null && page.Url == "about:blank") { - page = await _instance.NewPage(message, - enableResponseCallback: args.EnableResponseCallback, - responseInMemory: args.ResponseInMemory, - responseContainer: args.ResponseContainer, - excludeResponseUrls: args.ExcludeResponseUrls, - includeResponseUrls: args.IncludeResponseUrls); + page = await _instance.NewPage(message, args); } } if (page == null) { - page = await _instance.NewPage(message, - enableResponseCallback: args.EnableResponseCallback, - responseInMemory: args.ResponseInMemory, - responseContainer: args.ResponseContainer, - excludeResponseUrls: args.ExcludeResponseUrls, - includeResponseUrls: args.IncludeResponseUrls); + page = await _instance.NewPage(message, args); } // Active current tab From 85d4cf17bdcdee008f15adcbfcbcafc74d885066 Mon Sep 17 00:00:00 2001 From: jason Date: Mon, 30 Dec 2024 19:15:30 +0800 Subject: [PATCH 40/48] fix content is null or '' --- .../Drivers/PlaywrightDriver/PlaywrightInstance.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs index bf58a5ac..95b88eee 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs @@ -150,17 +150,20 @@ public class PlaywrightInstance : IDisposable ResponseInMemory = args.ResponseInMemory }; + var html = await response.TextAsync(); if (response.Headers["content-type"].Contains("application/json")) { if (response.Status == 200 && response.Ok) - { - var json = await response.JsonAsync(); - result.ResponseData = JsonSerializer.Serialize(json); + { + if (!string.IsNullOrWhiteSpace(html)) + { + var json = await response.JsonAsync(); + result.ResponseData = JsonSerializer.Serialize(json); + } } } else { - var html = await response.TextAsync(); result.ResponseData = html; } From 1a8fa0b21390827fd96bf81be58f67545d5e7801 Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Tue, 31 Dec 2024 17:07:38 +0000 Subject: [PATCH 41/48] Batch remove message from Redis stream --- .../BotSharp.Core/BotSharp.Core.csproj | 2 +- .../Infrastructures/Events/RedisPublisher.cs | 17 ++--------------- .../Infrastructures/Events/RedisSubscriber.cs | 3 ++- .../BotSharp.Plugin.HttpHandler.csproj | 4 ---- .../Hooks/SqlDriverPlanningHook.cs | 4 ---- .../Functions/OpenBrowserFn.cs | 2 -- 6 files changed, 5 insertions(+), 27 deletions(-) diff --git a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj index 23351fb5..d1232c5e 100644 --- a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj +++ b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj @@ -190,7 +190,7 @@ - + diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs index 514f4aa1..cee5cc6f 100644 --- a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs +++ b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs @@ -180,20 +180,7 @@ public class RedisPublisher : IEventPublisher var db = _redis.GetDatabase(); var entries = await db.StreamRangeAsync(channel, "-", "+", count: count, messageOrder: Order.Ascending); - foreach (var entry in entries) - { - _logger.LogInformation($"Fetched message: {channel} {entry.Values[0].Value} ({entry.Id})"); - - try - { - await db.StreamDeleteAsync(channel, [entry.Id]); - - _logger.LogWarning($"Deleted message: {channel} {entry.Values[0].Value} ({entry.Id})"); - } - catch (Exception ex) - { - _logger.LogError($"Error processing message: {ex.Message}, event id: {channel} {entry.Id}\r\n{ex}"); - } - } + var deletedCount = await db.StreamDeleteAsync(channel, entries.Select(x => x.Id).ToArray()); + _logger.LogWarning($"Deleted {deletedCount} messages from Redis stream {channel}"); } } diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs index 0dedb7c6..61db1d33 100644 --- a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs +++ b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs @@ -116,7 +116,8 @@ public class RedisSubscriber : IEventSubscriber } finally { - await db.StreamDeleteAsync(channel, [entry.Id]); + var deletedCount = await db.StreamDeleteAsync(channel, [entry.Id]); + _logger.LogInformation($"Handled message {entry.Id}: {deletedCount == 1}"); } } diff --git a/src/Plugins/BotSharp.Plugin.HttpHandler/BotSharp.Plugin.HttpHandler.csproj b/src/Plugins/BotSharp.Plugin.HttpHandler/BotSharp.Plugin.HttpHandler.csproj index 7dc0ac87..61ab8648 100644 --- a/src/Plugins/BotSharp.Plugin.HttpHandler/BotSharp.Plugin.HttpHandler.csproj +++ b/src/Plugins/BotSharp.Plugin.HttpHandler/BotSharp.Plugin.HttpHandler.csproj @@ -33,10 +33,6 @@ - - - - diff --git a/src/Plugins/BotSharp.Plugin.SqlDriver/Hooks/SqlDriverPlanningHook.cs b/src/Plugins/BotSharp.Plugin.SqlDriver/Hooks/SqlDriverPlanningHook.cs index bb008319..231d793a 100644 --- a/src/Plugins/BotSharp.Plugin.SqlDriver/Hooks/SqlDriverPlanningHook.cs +++ b/src/Plugins/BotSharp.Plugin.SqlDriver/Hooks/SqlDriverPlanningHook.cs @@ -1,13 +1,9 @@ -using BotSharp.Abstraction.Agents.Enums; using BotSharp.Abstraction.Messaging.Enums; using BotSharp.Abstraction.Messaging.Models.RichContent.Template; using BotSharp.Abstraction.Messaging.Models.RichContent; using BotSharp.Abstraction.Messaging; using BotSharp.Abstraction.Planning; -using BotSharp.Abstraction.Routing; using BotSharp.Core.Infrastructures; -using System.Text.RegularExpressions; -using BotSharp.Plugin.SqlDriver.Interfaces; namespace BotSharp.Plugin.SqlDriver.Hooks; diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Functions/OpenBrowserFn.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Functions/OpenBrowserFn.cs index 6f4c3654..6a5a1ac1 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Functions/OpenBrowserFn.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Functions/OpenBrowserFn.cs @@ -1,5 +1,3 @@ -using SQLitePCL; - namespace BotSharp.Plugin.WebDriver.Functions; public class OpenBrowserFn : IFunctionCallback From b959508410a3d5e43c69e42afb57c39d300cc69a Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Thu, 2 Jan 2025 22:48:28 +0000 Subject: [PATCH 42/48] Avoid error for Redis. --- Directory.Build.props | 2 +- README.md | 2 +- .../BotSharp.Core/BotSharpCoreExtensions.cs | 5 +++++ .../Infrastructures/DistributedLocker.cs | 12 +++++++----- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 4233fb32..6716a3c7 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,7 +2,7 @@ net8.0 12.0 - 3.0.0 + 4.0.0 true false diff --git a/README.md b/README.md index e5c3684a..9fd42e2a 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ It's written in C# running on .Net Core that is full cross-platform framework, t * Built-in multi-agents and conversation with state management. * Support multiple LLM Planning approaches to handle different tasks from simple to complex. * Built-in RAG related interfaces, Memory based vector searching. -* Support multiple AI platforms (ChatGPT 3.5 / 4.0, PaLM 2, LLaMA 3, Claude Sonnet 3.5, HuggingFace). +* Support multiple AI platforms (ChatGPT 3.5/ 4o/ o1, Gemini 2, LLaMA 3, Claude Sonnet 3.5, HuggingFace). * Allow multiple agents with different responsibilities cooperate to complete complex tasks. * Build, test, evaluate and audit your LLM agent in one place. * Build-in `BotSharp UI` written in [SvelteKit](https://kit.svelte.dev/). diff --git a/src/Infrastructure/BotSharp.Core/BotSharpCoreExtensions.cs b/src/Infrastructure/BotSharp.Core/BotSharpCoreExtensions.cs index af8a9324..f588b4d1 100644 --- a/src/Infrastructure/BotSharp.Core/BotSharpCoreExtensions.cs +++ b/src/Infrastructure/BotSharp.Core/BotSharpCoreExtensions.cs @@ -105,6 +105,11 @@ public static class BotSharpCoreExtensions var dbSettings = new BotSharpDatabaseSettings(); config.Bind("Database", dbSettings); + if (string.IsNullOrEmpty(dbSettings.Redis)) + { + return; + } + services.AddSingleton(ConnectionMultiplexer.Connect(dbSettings.Redis)); services.AddSingleton(); services.AddSingleton(); diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/DistributedLocker.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/DistributedLocker.cs index 48ff193f..c87dbe45 100644 --- a/src/Infrastructure/BotSharp.Core/Infrastructures/DistributedLocker.cs +++ b/src/Infrastructure/BotSharp.Core/Infrastructures/DistributedLocker.cs @@ -6,12 +6,12 @@ namespace BotSharp.Core.Infrastructures; public class DistributedLocker : IDistributedLocker { - private readonly IConnectionMultiplexer _redis; + private readonly IServiceProvider _services; private readonly ILogger _logger; - public DistributedLocker(IConnectionMultiplexer redis, ILogger logger) + public DistributedLocker(IServiceProvider services, ILogger logger) { - _redis = redis; + _services = services; _logger = logger; } @@ -19,7 +19,8 @@ public class DistributedLocker : IDistributedLocker { var timeout = TimeSpan.FromSeconds(timeoutInSeconds); - var @lock = new RedisDistributedLock(resource, _redis.GetDatabase()); + var redis = _services.GetRequiredService(); + var @lock = new RedisDistributedLock(resource, redis.GetDatabase()); await using (var handle = await @lock.TryAcquireAsync(timeout)) { if (handle == null) @@ -37,7 +38,8 @@ public class DistributedLocker : IDistributedLocker { var timeout = TimeSpan.FromSeconds(timeoutInSeconds); - var @lock = new RedisDistributedLock(resource, _redis.GetDatabase()); + var redis = _services.GetRequiredService(); + var @lock = new RedisDistributedLock(resource, redis.GetDatabase()); using (var handle = @lock.TryAcquire(timeout)) { if (handle == null) From 72851d3c1e9f173be879869f866ebc46fb9aaa19 Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Fri, 3 Jan 2025 09:59:59 -0600 Subject: [PATCH 43/48] revert open ai client --- .../BotSharp.Plugin.OpenAI/Providers/ProviderHelper.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/ProviderHelper.cs b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/ProviderHelper.cs index b385b380..d3db3544 100644 --- a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/ProviderHelper.cs +++ b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/ProviderHelper.cs @@ -9,8 +9,9 @@ public class ProviderHelper { var settingsService = services.GetRequiredService(); var settings = settingsService.GetSetting(provider, model); - var client = new OpenAIClient(new ApiKeyCredential(settings.ApiKey)); - return client; + var options = !string.IsNullOrEmpty(settings.Endpoint) ? + new OpenAIClientOptions { Endpoint = new Uri(settings.Endpoint) } : null; + return new OpenAIClient(new ApiKeyCredential(settings.ApiKey), options); } public static List GetChatSamples(List lines) From 35ca81b6be0a0d2c6504726df4b162b032828b9b Mon Sep 17 00:00:00 2001 From: Gil Zhang Date: Sat, 4 Jan 2025 00:00:21 +0800 Subject: [PATCH 44/48] Update README.md Add LiteDBStorage Link --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9fd42e2a..f8f76eb4 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,7 @@ BotSharp uses component design, the kernel is kept to a minimum, and business fu #### Data Storages - BotSharp.Core.Repository - BotSharp.Plugin.MongoStorage +- [BotSharp.Plugin.LiteDBStorage](https://github.com/GreenShadeZhang/BotSharp/tree/dev_litedb/src/Plugins/BotSharp.Plugin.LiteDBStorage) - BotSharp.Plugin.TencentCos #### LLMs From d241b21adebd27244bee69a9c58c10f217a11507 Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Sun, 5 Jan 2025 23:54:48 -0600 Subject: [PATCH 45/48] add agent event rule --- .../Agents/Enums/AgentField.cs | 1 + .../Agents/IAgentService.cs | 2 -- .../Agents/Models/Agent.cs | 12 +++++++ .../Agents/Models/AgentEventRule.cs | 13 ++++++++ .../Hooks/IEventRuleHook.cs | 8 +++++ .../Services/AgentService.UpdateAgent.cs | 2 ++ .../Agents/Services/AgentService.cs | 11 ------- .../FileRepository/FileRepository.Agent.cs | 19 ++++++++++- .../BotSharp.OpenAPI/BotSharp.OpenAPI.csproj | 1 + .../Controllers/AgentController.cs | 22 ++++++++++++- .../ViewModels/Agents/AgentCreationModel.cs | 2 ++ .../ViewModels/Agents/AgentUpdateModel.cs | 18 ++++++---- .../ViewModels/Agents/AgentViewModel.cs | 22 ++++++++----- .../Collections/AgentDocument.cs | 1 + .../Models/AgentEventRuleMongoElement.cs | 33 +++++++++++++++++++ .../Repository/MongoRepository.Agent.cs | 23 +++++++++++-- 16 files changed, 157 insertions(+), 33 deletions(-) create mode 100644 src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentEventRule.cs create mode 100644 src/Infrastructure/BotSharp.Core.Rules/Hooks/IEventRuleHook.cs create mode 100644 src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentEventRuleMongoElement.cs diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs index 346bcf31..613c1778 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs @@ -19,6 +19,7 @@ public enum AgentField LlmConfig, Utility, KnowledgeBase, + EventRule, MaxMessageCount } diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs index 91beea8b..2ec4ff92 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs @@ -58,6 +58,4 @@ public interface IAgentService Task> GetUserAgents(string userId); PluginDef GetPlugin(string agentId); - - IEnumerable GetAgentUtilityOptions(); } diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs index 566df050..83927d9f 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs @@ -99,6 +99,11 @@ public class Agent /// public List Utilities { get; set; } = new(); + /// + /// Agent rules + /// + public List EventRules { get; set; } = new(); + /// /// Agent knowledge bases /// @@ -154,6 +159,7 @@ public class Agent MaxMessageCount = agent.MaxMessageCount, Profiles = agent.Profiles, RoutingRules = agent.RoutingRules, + EventRules = agent.EventRules, LlmConfig = agent.LlmConfig, KnowledgeBases = agent.KnowledgeBases, CreatedDateTime = agent.CreatedDateTime, @@ -269,6 +275,12 @@ public class Agent return this; } + public Agent SetEventRules(List rules) + { + EventRules = rules ?? []; + return this; + } + public Agent SetLlmConfig(AgentLlmConfig? llmConfig) { LlmConfig = llmConfig; diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentEventRule.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentEventRule.cs new file mode 100644 index 00000000..c23ef890 --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentEventRule.cs @@ -0,0 +1,13 @@ +namespace BotSharp.Abstraction.Agents.Models; + +public class AgentEventRule +{ + public string Name { get; set; } + public bool Disabled { get; set; } + + [JsonPropertyName("event_name")] + public string EventName { get; set; } + + [JsonPropertyName("event_type")] + public string EntityType { get; set; } +} diff --git a/src/Infrastructure/BotSharp.Core.Rules/Hooks/IEventRuleHook.cs b/src/Infrastructure/BotSharp.Core.Rules/Hooks/IEventRuleHook.cs new file mode 100644 index 00000000..e65050b8 --- /dev/null +++ b/src/Infrastructure/BotSharp.Core.Rules/Hooks/IEventRuleHook.cs @@ -0,0 +1,8 @@ +using BotSharp.Abstraction.Agents.Models; + +namespace BotSharp.Core.Rules.Hooks; + +public interface IEventRuleHook +{ + void AddRules(List rules); +} diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs index 584a4c7e..ea95daa5 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs @@ -40,6 +40,7 @@ public partial class AgentService record.Samples = agent.Samples ?? []; record.Utilities = agent.Utilities ?? []; record.KnowledgeBases = agent.KnowledgeBases ?? []; + record.EventRules = agent.EventRules ?? []; if (agent.LlmConfig != null && !agent.LlmConfig.IsInherit) { record.LlmConfig = agent.LlmConfig; @@ -104,6 +105,7 @@ public partial class AgentService .SetSamples(foundAgent.Samples) .SetUtilities(foundAgent.Utilities) .SetKnowledgeBases(foundAgent.KnowledgeBases) + .SetEventRules(foundAgent.EventRules) .SetLlmConfig(foundAgent.LlmConfig); _db.UpdateAgent(clonedAgent, AgentField.All); diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.cs index 80cdc56c..c54c4fd8 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.cs @@ -53,15 +53,4 @@ public partial class AgentService : IAgentService var userAgents = _db.GetUserAgents(userId); return userAgents; } - - public IEnumerable GetAgentUtilityOptions() - { - var utilities = new List(); - var hooks = _services.GetServices(); - foreach (var hook in hooks) - { - hook.AddUtilities(utilities); - } - return utilities.Where(x => !string.IsNullOrWhiteSpace(x.Name)).OrderBy(x => x.Name).ToList(); - } } diff --git a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Agent.cs b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Agent.cs index 0a8d5b65..3b8614f1 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Agent.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Agent.cs @@ -60,6 +60,9 @@ namespace BotSharp.Core.Repository case AgentField.KnowledgeBase: UpdateAgentKnowledgeBases(agent.Id, agent.KnowledgeBases); break; + case AgentField.EventRule: + UpdateAgentEventRules(agent.Id, agent.EventRules); + break; case AgentField.MaxMessageCount: UpdateAgentMaxMessageCount(agent.Id, agent.MaxMessageCount); break; @@ -184,6 +187,19 @@ namespace BotSharp.Core.Repository File.WriteAllText(agentFile, json); } + private void UpdateAgentEventRules(string agentId, List rules) + { + if (rules == null) return; + + var (agent, agentFile) = GetAgentFromFile(agentId); + if (agent == null) return; + + agent.EventRules = rules; + agent.UpdatedDateTime = DateTime.UtcNow; + var json = JsonSerializer.Serialize(agent, _options); + File.WriteAllText(agentFile, json); + } + private void UpdateAgentRoutingRules(string agentId, List rules) { if (rules == null) return; @@ -240,7 +256,7 @@ namespace BotSharp.Core.Repository var text = JsonSerializer.Serialize(func, _options); var file = Path.Combine(functionDir, $"{func.Name}.json"); File.WriteAllText(file, text); - Thread.Sleep(100); + Thread.Sleep(50); } } @@ -328,6 +344,7 @@ namespace BotSharp.Core.Repository agent.Utilities = inputAgent.Utilities; agent.KnowledgeBases = inputAgent.KnowledgeBases; agent.RoutingRules = inputAgent.RoutingRules; + agent.EventRules = inputAgent.EventRules; agent.LlmConfig = inputAgent.LlmConfig; agent.MaxMessageCount = inputAgent.MaxMessageCount; agent.UpdatedDateTime = DateTime.UtcNow; diff --git a/src/Infrastructure/BotSharp.OpenAPI/BotSharp.OpenAPI.csproj b/src/Infrastructure/BotSharp.OpenAPI/BotSharp.OpenAPI.csproj index 28dde755..bacf34e9 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/BotSharp.OpenAPI.csproj +++ b/src/Infrastructure/BotSharp.OpenAPI/BotSharp.OpenAPI.csproj @@ -48,6 +48,7 @@ + diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs index 1885365d..b4f1b3e6 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs @@ -1,4 +1,6 @@ using BotSharp.Abstraction.Agents.Models; +using BotSharp.Core.Infrastructures; +using BotSharp.Core.Rules.Hooks; namespace BotSharp.OpenAPI.Controllers; @@ -152,6 +154,24 @@ public class AgentController : ControllerBase [HttpGet("/agent/utility/options")] public IEnumerable GetAgentUtilityOptions() { - return _agentService.GetAgentUtilityOptions(); + var utilities = new List(); + var hooks = _services.GetServices(); + foreach (var hook in hooks) + { + hook.AddUtilities(utilities); + } + return utilities.Where(x => !string.IsNullOrWhiteSpace(x.Name)).OrderBy(x => x.Name).ToList(); + } + + [HttpGet("/agent/event-rule/options")] + public IEnumerable GetAgentEventRuleOptions() + { + var rules = new List(); + var hooks = _services.GetServices(); + foreach (var hook in hooks) + { + hook.AddRules(rules); + } + return rules.Where(x => !string.IsNullOrWhiteSpace(x.Name)).OrderBy(x => x.Name).ToList(); } } \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentCreationModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentCreationModel.cs index 3caba6ae..9df167b7 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentCreationModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentCreationModel.cs @@ -55,6 +55,7 @@ public class AgentCreationModel public List Utilities { get; set; } = new(); public List RoutingRules { get; set; } = new(); public List KnowledgeBases { get; set; } = new(); + public List EventRules { get; set; } = new(); public AgentLlmConfig? LlmConfig { get; set; } public Agent ToAgent() @@ -78,6 +79,7 @@ public class AgentCreationModel Profiles = Profiles, LlmConfig = LlmConfig, KnowledgeBases = KnowledgeBases, + EventRules = EventRules, RoutingRules = RoutingRules?.Select(x => RoutingRuleUpdateModel.ToDomainElement(x))?.ToList() ?? [], }; } diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentUpdateModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentUpdateModel.cs index 66618186..2bfaa52f 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentUpdateModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentUpdateModel.cs @@ -75,6 +75,9 @@ public class AgentUpdateModel [JsonPropertyName("routing_rules")] public List? RoutingRules { get; set; } + [JsonPropertyName("event_rules")] + public List? EventRules { get; set; } + [JsonPropertyName("llm_config")] public AgentLlmConfig? LlmConfig { get; set; } @@ -89,15 +92,16 @@ public class AgentUpdateModel MergeUtility = MergeUtility, MaxMessageCount = MaxMessageCount, Type = Type, - Profiles = Profiles ?? new List(), - RoutingRules = RoutingRules?.Select(x => RoutingRuleUpdateModel.ToDomainElement(x))?.ToList() ?? new List(), + Profiles = Profiles ?? [], + RoutingRules = RoutingRules?.Select(x => RoutingRuleUpdateModel.ToDomainElement(x))?.ToList() ?? [], Instruction = Instruction ?? string.Empty, - ChannelInstructions = ChannelInstructions ?? new List(), - Templates = Templates ?? new List(), - Functions = Functions ?? new List(), - Responses = Responses ?? new List(), - Utilities = Utilities ?? new List(), + ChannelInstructions = ChannelInstructions ?? [], + Templates = Templates ?? [], + Functions = Functions ?? [], + Responses = Responses ?? [], + Utilities = Utilities ?? [], KnowledgeBases = KnowledgeBases ?? [], + EventRules = EventRules ?? [], LlmConfig = LlmConfig }; diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs index e9479109..d2a6f2ca 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs @@ -28,6 +28,9 @@ public class AgentViewModel [JsonPropertyName("knowledge_bases")] public List KnowledgeBases { get; set; } + [JsonPropertyName("event_rules")] + public List EventRules { get; set; } + [JsonPropertyName("is_public")] public bool IsPublic { get; set; } @@ -72,20 +75,21 @@ public class AgentViewModel Description = agent.Description, Type = agent.Type, Instruction = agent.Instruction, - ChannelInstructions = agent.ChannelInstructions, - Templates = agent.Templates, - Functions = agent.Functions, - Responses = agent.Responses, - Samples = agent.Samples, - Utilities = agent.Utilities, - KnowledgeBases = agent.KnowledgeBases, + ChannelInstructions = agent.ChannelInstructions ?? [], + Templates = agent.Templates ?? [], + Functions = agent.Functions ?? [], + Responses = agent.Responses ?? [], + Samples = agent.Samples ?? [], + Utilities = agent.Utilities ?? [], + KnowledgeBases = agent.KnowledgeBases ?? [], IsPublic= agent.IsPublic, Disabled = agent.Disabled, MergeUtility = agent.MergeUtility, IconUrl = agent.IconUrl, MaxMessageCount = agent.MaxMessageCount, - Profiles = agent.Profiles ?? new List(), - RoutingRules = agent.RoutingRules, + Profiles = agent.Profiles ?? [], + RoutingRules = agent.RoutingRules ?? [], + EventRules = agent.EventRules ?? [], LlmConfig = agent.LlmConfig, Plugin = agent.Plugin, CreatedDateTime = agent.CreatedDateTime, diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs index 19945124..816e0904 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs @@ -21,6 +21,7 @@ public class AgentDocument : MongoBase public List KnowledgeBases { get; set; } public List Profiles { get; set; } public List RoutingRules { get; set; } + public List EventRules { get; set; } public AgentLlmConfigMongoElement? LlmConfig { get; set; } public DateTime CreatedTime { get; set; } diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentEventRuleMongoElement.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentEventRuleMongoElement.cs new file mode 100644 index 00000000..cadb3c45 --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentEventRuleMongoElement.cs @@ -0,0 +1,33 @@ +using BotSharp.Abstraction.Agents.Models; + +namespace BotSharp.Plugin.MongoStorage.Models; + +public class AgentEventRuleMongoElement +{ + public string Name { get; set; } + public bool Disabled { get; set; } + public string EventName { get; set; } + public string EntityType { get; set; } + + public static AgentEventRuleMongoElement ToMongoElement(AgentEventRule rule) + { + return new AgentEventRuleMongoElement + { + Name = rule.Name, + Disabled = rule.Disabled, + EventName = rule.EventName, + EntityType = rule.EntityType + }; + } + + public static AgentEventRule ToDomainElement(AgentEventRuleMongoElement rule) + { + return new AgentEventRule + { + Name = rule.Name, + Disabled = rule.Disabled, + EventName = rule.EventName, + EntityType = rule.EntityType + }; + } +} diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs index 7f86d144..92d9db60 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs @@ -61,6 +61,9 @@ public partial class MongoRepository case AgentField.KnowledgeBase: UpdateAgentKnowledgeBases(agent.Id, agent.KnowledgeBases); break; + case AgentField.EventRule: + UpdateAgentEventRules(agent.Id, agent.EventRules); + break; case AgentField.MaxMessageCount: UpdateAgentMaxMessageCount(agent.Id, agent.MaxMessageCount); break; @@ -256,6 +259,20 @@ public partial class MongoRepository _dc.Agents.UpdateOne(filter, update); } + private void UpdateAgentEventRules(string agentId, List rules) + { + if (rules == null) return; + + var elements = rules?.Select(x => AgentEventRuleMongoElement.ToMongoElement(x))?.ToList() ?? []; + + var filter = Builders.Filter.Eq(x => x.Id, agentId); + var update = Builders.Update + .Set(x => x.EventRules, elements) + .Set(x => x.UpdatedTime, DateTime.UtcNow); + + _dc.Agents.UpdateOne(filter, update); + } + private void UpdateAgentLlmConfig(string agentId, AgentLlmConfig? config) { var llmConfig = AgentLlmConfigMongoElement.ToMongoElement(config); @@ -297,12 +314,12 @@ public partial class MongoRepository .Set(x => x.Samples, agent.Samples) .Set(x => x.Utilities, agent.Utilities.Select(u => AgentUtilityMongoElement.ToMongoElement(u)).ToList()) .Set(x => x.KnowledgeBases, agent.KnowledgeBases.Select(u => AgentKnowledgeBaseMongoElement.ToMongoElement(u)).ToList()) + .Set(x => x.EventRules, agent.EventRules.Select(e => AgentEventRuleMongoElement.ToMongoElement(e)).ToList()) .Set(x => x.LlmConfig, AgentLlmConfigMongoElement.ToMongoElement(agent.LlmConfig)) .Set(x => x.IsPublic, agent.IsPublic) .Set(x => x.UpdatedTime, DateTime.UtcNow); var res = _dc.Agents.UpdateOne(filter, update); - Console.WriteLine(); } #endregion @@ -455,6 +472,7 @@ public partial class MongoRepository RoutingRules = x.RoutingRules?.Select(r => RoutingRuleMongoElement.ToMongoElement(r))?.ToList() ?? [], Utilities = x.Utilities?.Select(u => AgentUtilityMongoElement.ToMongoElement(u))?.ToList() ?? [], KnowledgeBases = x.KnowledgeBases?.Select(k => AgentKnowledgeBaseMongoElement.ToMongoElement(k))?.ToList() ?? [], + EventRules = x.EventRules?.Select(e => AgentEventRuleMongoElement.ToMongoElement(e))?.ToList() ?? [], CreatedTime = x.CreatedDateTime, UpdatedTime = x.UpdatedDateTime }).ToList(); @@ -546,7 +564,8 @@ public partial class MongoRepository Responses = agentDoc.Responses?.Select(r => AgentResponseMongoElement.ToDomainElement(r))?.ToList() ?? [], RoutingRules = agentDoc.RoutingRules?.Select(r => RoutingRuleMongoElement.ToDomainElement(agentDoc.Id, agentDoc.Name, r))?.ToList() ?? [], Utilities = agentDoc.Utilities?.Select(u => AgentUtilityMongoElement.ToDomainElement(u))?.ToList() ?? [], - KnowledgeBases = agentDoc.KnowledgeBases?.Select(x => AgentKnowledgeBaseMongoElement.ToDomainElement(x))?.ToList() ?? [] + KnowledgeBases = agentDoc.KnowledgeBases?.Select(x => AgentKnowledgeBaseMongoElement.ToDomainElement(x))?.ToList() ?? [], + EventRules = agentDoc.EventRules?.Select(e => AgentEventRuleMongoElement.ToDomainElement(e))?.ToList() ?? [] }; } } From 8dff3f5ce3a9fb9db14bc3b7edce8b44fc73bbea Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Mon, 6 Jan 2025 00:01:14 -0600 Subject: [PATCH 46/48] rename --- .../BotSharp.Abstraction/Agents/Models/AgentEventRule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentEventRule.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentEventRule.cs index c23ef890..180c83a6 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentEventRule.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentEventRule.cs @@ -8,6 +8,6 @@ public class AgentEventRule [JsonPropertyName("event_name")] public string EventName { get; set; } - [JsonPropertyName("event_type")] + [JsonPropertyName("entity_type")] public string EntityType { get; set; } } From b681b18ac2d0412a22a36fa38ff3b5603adb7e60 Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Tue, 7 Jan 2025 13:50:50 -0600 Subject: [PATCH 47/48] refine agent rule --- .../Agents/Enums/AgentField.cs | 2 +- .../Agents/IAgentRuleHook.cs | 6 ++++++ .../BotSharp.Abstraction/Agents/Models/Agent.cs | 8 ++++---- .../Models/{AgentEventRule.cs => AgentRule.cs} | 2 +- .../BotSharp.Core.Rules/Hooks/IEventRuleHook.cs | 8 -------- .../Agents/Services/AgentService.UpdateAgent.cs | 4 ++-- .../FileRepository/FileRepository.Agent.cs | 10 +++++----- .../BotSharp.OpenAPI/BotSharp.OpenAPI.csproj | 1 - .../Controllers/AgentController.cs | 10 ++++------ .../ViewModels/Agents/AgentCreationModel.cs | 4 ++-- .../ViewModels/Agents/AgentUpdateModel.cs | 6 +++--- .../ViewModels/Agents/AgentViewModel.cs | 6 +++--- .../Functions/HandleHttpRequestFn.cs | 9 ++++++--- .../Collections/AgentDocument.cs | 2 +- ...eMongoElement.cs => AgentRuleMongoElement.cs} | 10 +++++----- .../Repository/MongoRepository.Agent.cs | 16 ++++++++-------- 16 files changed, 51 insertions(+), 53 deletions(-) create mode 100644 src/Infrastructure/BotSharp.Abstraction/Agents/IAgentRuleHook.cs rename src/Infrastructure/BotSharp.Abstraction/Agents/Models/{AgentEventRule.cs => AgentRule.cs} (91%) delete mode 100644 src/Infrastructure/BotSharp.Core.Rules/Hooks/IEventRuleHook.cs rename src/Plugins/BotSharp.Plugin.MongoStorage/Models/{AgentEventRuleMongoElement.cs => AgentRuleMongoElement.cs} (68%) diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs index 613c1778..2a9508d7 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs @@ -19,7 +19,7 @@ public enum AgentField LlmConfig, Utility, KnowledgeBase, - EventRule, + Rule, MaxMessageCount } diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentRuleHook.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentRuleHook.cs new file mode 100644 index 00000000..8a19a561 --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentRuleHook.cs @@ -0,0 +1,6 @@ +namespace BotSharp.Abstraction.Agents; + +public interface IAgentRuleHook +{ + void AddRules(List rules); +} diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs index 83927d9f..96aa070c 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs @@ -102,7 +102,7 @@ public class Agent /// /// Agent rules /// - public List EventRules { get; set; } = new(); + public List Rules { get; set; } = new(); /// /// Agent knowledge bases @@ -159,7 +159,7 @@ public class Agent MaxMessageCount = agent.MaxMessageCount, Profiles = agent.Profiles, RoutingRules = agent.RoutingRules, - EventRules = agent.EventRules, + Rules = agent.Rules, LlmConfig = agent.LlmConfig, KnowledgeBases = agent.KnowledgeBases, CreatedDateTime = agent.CreatedDateTime, @@ -275,9 +275,9 @@ public class Agent return this; } - public Agent SetEventRules(List rules) + public Agent SetRules(List rules) { - EventRules = rules ?? []; + Rules = rules ?? []; return this; } diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentEventRule.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentRule.cs similarity index 91% rename from src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentEventRule.cs rename to src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentRule.cs index 180c83a6..5c3a276e 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentEventRule.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentRule.cs @@ -1,6 +1,6 @@ namespace BotSharp.Abstraction.Agents.Models; -public class AgentEventRule +public class AgentRule { public string Name { get; set; } public bool Disabled { get; set; } diff --git a/src/Infrastructure/BotSharp.Core.Rules/Hooks/IEventRuleHook.cs b/src/Infrastructure/BotSharp.Core.Rules/Hooks/IEventRuleHook.cs deleted file mode 100644 index e65050b8..00000000 --- a/src/Infrastructure/BotSharp.Core.Rules/Hooks/IEventRuleHook.cs +++ /dev/null @@ -1,8 +0,0 @@ -using BotSharp.Abstraction.Agents.Models; - -namespace BotSharp.Core.Rules.Hooks; - -public interface IEventRuleHook -{ - void AddRules(List rules); -} diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs index ea95daa5..6889336a 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs @@ -40,7 +40,7 @@ public partial class AgentService record.Samples = agent.Samples ?? []; record.Utilities = agent.Utilities ?? []; record.KnowledgeBases = agent.KnowledgeBases ?? []; - record.EventRules = agent.EventRules ?? []; + record.Rules = agent.Rules ?? []; if (agent.LlmConfig != null && !agent.LlmConfig.IsInherit) { record.LlmConfig = agent.LlmConfig; @@ -105,7 +105,7 @@ public partial class AgentService .SetSamples(foundAgent.Samples) .SetUtilities(foundAgent.Utilities) .SetKnowledgeBases(foundAgent.KnowledgeBases) - .SetEventRules(foundAgent.EventRules) + .SetRules(foundAgent.Rules) .SetLlmConfig(foundAgent.LlmConfig); _db.UpdateAgent(clonedAgent, AgentField.All); diff --git a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Agent.cs b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Agent.cs index 3b8614f1..d38b2a89 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Agent.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Agent.cs @@ -60,8 +60,8 @@ namespace BotSharp.Core.Repository case AgentField.KnowledgeBase: UpdateAgentKnowledgeBases(agent.Id, agent.KnowledgeBases); break; - case AgentField.EventRule: - UpdateAgentEventRules(agent.Id, agent.EventRules); + case AgentField.Rule: + UpdateAgentRules(agent.Id, agent.Rules); break; case AgentField.MaxMessageCount: UpdateAgentMaxMessageCount(agent.Id, agent.MaxMessageCount); @@ -187,14 +187,14 @@ namespace BotSharp.Core.Repository File.WriteAllText(agentFile, json); } - private void UpdateAgentEventRules(string agentId, List rules) + private void UpdateAgentRules(string agentId, List rules) { if (rules == null) return; var (agent, agentFile) = GetAgentFromFile(agentId); if (agent == null) return; - agent.EventRules = rules; + agent.Rules = rules; agent.UpdatedDateTime = DateTime.UtcNow; var json = JsonSerializer.Serialize(agent, _options); File.WriteAllText(agentFile, json); @@ -344,7 +344,7 @@ namespace BotSharp.Core.Repository agent.Utilities = inputAgent.Utilities; agent.KnowledgeBases = inputAgent.KnowledgeBases; agent.RoutingRules = inputAgent.RoutingRules; - agent.EventRules = inputAgent.EventRules; + agent.Rules = inputAgent.Rules; agent.LlmConfig = inputAgent.LlmConfig; agent.MaxMessageCount = inputAgent.MaxMessageCount; agent.UpdatedDateTime = DateTime.UtcNow; diff --git a/src/Infrastructure/BotSharp.OpenAPI/BotSharp.OpenAPI.csproj b/src/Infrastructure/BotSharp.OpenAPI/BotSharp.OpenAPI.csproj index bacf34e9..28dde755 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/BotSharp.OpenAPI.csproj +++ b/src/Infrastructure/BotSharp.OpenAPI/BotSharp.OpenAPI.csproj @@ -48,7 +48,6 @@ - diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs index b4f1b3e6..6efb7104 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs @@ -1,6 +1,4 @@ using BotSharp.Abstraction.Agents.Models; -using BotSharp.Core.Infrastructures; -using BotSharp.Core.Rules.Hooks; namespace BotSharp.OpenAPI.Controllers; @@ -163,11 +161,11 @@ public class AgentController : ControllerBase return utilities.Where(x => !string.IsNullOrWhiteSpace(x.Name)).OrderBy(x => x.Name).ToList(); } - [HttpGet("/agent/event-rule/options")] - public IEnumerable GetAgentEventRuleOptions() + [HttpGet("/agent/rule/options")] + public IEnumerable GetAgentRuleOptions() { - var rules = new List(); - var hooks = _services.GetServices(); + var rules = new List(); + var hooks = _services.GetServices(); foreach (var hook in hooks) { hook.AddRules(rules); diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentCreationModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentCreationModel.cs index 9df167b7..a0e8f790 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentCreationModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentCreationModel.cs @@ -55,7 +55,7 @@ public class AgentCreationModel public List Utilities { get; set; } = new(); public List RoutingRules { get; set; } = new(); public List KnowledgeBases { get; set; } = new(); - public List EventRules { get; set; } = new(); + public List Rules { get; set; } = new(); public AgentLlmConfig? LlmConfig { get; set; } public Agent ToAgent() @@ -79,7 +79,7 @@ public class AgentCreationModel Profiles = Profiles, LlmConfig = LlmConfig, KnowledgeBases = KnowledgeBases, - EventRules = EventRules, + Rules = Rules, RoutingRules = RoutingRules?.Select(x => RoutingRuleUpdateModel.ToDomainElement(x))?.ToList() ?? [], }; } diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentUpdateModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentUpdateModel.cs index 2bfaa52f..8e268b97 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentUpdateModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentUpdateModel.cs @@ -75,8 +75,8 @@ public class AgentUpdateModel [JsonPropertyName("routing_rules")] public List? RoutingRules { get; set; } - [JsonPropertyName("event_rules")] - public List? EventRules { get; set; } + [JsonPropertyName("rules")] + public List? Rules { get; set; } [JsonPropertyName("llm_config")] public AgentLlmConfig? LlmConfig { get; set; } @@ -101,7 +101,7 @@ public class AgentUpdateModel Responses = Responses ?? [], Utilities = Utilities ?? [], KnowledgeBases = KnowledgeBases ?? [], - EventRules = EventRules ?? [], + Rules = Rules ?? [], LlmConfig = LlmConfig }; diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs index d2a6f2ca..de4a13ba 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs @@ -28,8 +28,8 @@ public class AgentViewModel [JsonPropertyName("knowledge_bases")] public List KnowledgeBases { get; set; } - [JsonPropertyName("event_rules")] - public List EventRules { get; set; } + [JsonPropertyName("rules")] + public List Rules { get; set; } [JsonPropertyName("is_public")] public bool IsPublic { get; set; } @@ -89,7 +89,7 @@ public class AgentViewModel MaxMessageCount = agent.MaxMessageCount, Profiles = agent.Profiles ?? [], RoutingRules = agent.RoutingRules ?? [], - EventRules = agent.EventRules ?? [], + Rules = agent.Rules ?? [], LlmConfig = agent.LlmConfig, Plugin = agent.Plugin, CreatedDateTime = agent.CreatedDateTime, diff --git a/src/Plugins/BotSharp.Plugin.HttpHandler/Functions/HandleHttpRequestFn.cs b/src/Plugins/BotSharp.Plugin.HttpHandler/Functions/HandleHttpRequestFn.cs index d36aafba..f9a4342c 100644 --- a/src/Plugins/BotSharp.Plugin.HttpHandler/Functions/HandleHttpRequestFn.cs +++ b/src/Plugins/BotSharp.Plugin.HttpHandler/Functions/HandleHttpRequestFn.cs @@ -46,7 +46,7 @@ public class HandleHttpRequestFn : IFunctionCallback catch (Exception ex) { var msg = $"Fail when sending http request. Url: {url}, method: {method}, content: {content}"; - _logger.LogWarning($"{msg}\n(Error: {ex.Message})"); + _logger.LogError($"{msg}\n(Error: {ex.Message}\r\n{ex.InnerException})"); message.Content = msg; return false; } @@ -71,10 +71,13 @@ public class HandleHttpRequestFn : IFunctionCallback private void AddRequestHeaders(HttpClient client) { - client.DefaultRequestHeaders.Add("Authorization", $"{_context.HttpContext.Request.Headers["Authorization"]}"); + var auth = $"{_context.HttpContext.Request.Headers["Authorization"]}"; + var origin = $"{_context.HttpContext.Request.Headers["Origin"]}"; + + client.DefaultRequestHeaders.Add("Authorization", auth); var settings = _services.GetRequiredService(); - var origin = !string.IsNullOrEmpty(settings.Origin) ? settings.Origin : $"{_context.HttpContext.Request.Headers["Origin"]}"; + origin = !string.IsNullOrEmpty(origin) ? origin : settings.Origin; if (!string.IsNullOrEmpty(origin)) { client.DefaultRequestHeaders.Add("Origin", origin); diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs index 816e0904..54c9eae7 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs @@ -21,7 +21,7 @@ public class AgentDocument : MongoBase public List KnowledgeBases { get; set; } public List Profiles { get; set; } public List RoutingRules { get; set; } - public List EventRules { get; set; } + public List Rules { get; set; } public AgentLlmConfigMongoElement? LlmConfig { get; set; } public DateTime CreatedTime { get; set; } diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentEventRuleMongoElement.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentRuleMongoElement.cs similarity index 68% rename from src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentEventRuleMongoElement.cs rename to src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentRuleMongoElement.cs index cadb3c45..1b346768 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentEventRuleMongoElement.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentRuleMongoElement.cs @@ -2,16 +2,16 @@ using BotSharp.Abstraction.Agents.Models; namespace BotSharp.Plugin.MongoStorage.Models; -public class AgentEventRuleMongoElement +public class AgentRuleMongoElement { public string Name { get; set; } public bool Disabled { get; set; } public string EventName { get; set; } public string EntityType { get; set; } - public static AgentEventRuleMongoElement ToMongoElement(AgentEventRule rule) + public static AgentRuleMongoElement ToMongoElement(AgentRule rule) { - return new AgentEventRuleMongoElement + return new AgentRuleMongoElement { Name = rule.Name, Disabled = rule.Disabled, @@ -20,9 +20,9 @@ public class AgentEventRuleMongoElement }; } - public static AgentEventRule ToDomainElement(AgentEventRuleMongoElement rule) + public static AgentRule ToDomainElement(AgentRuleMongoElement rule) { - return new AgentEventRule + return new AgentRule { Name = rule.Name, Disabled = rule.Disabled, diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs index 92d9db60..af615298 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs @@ -61,8 +61,8 @@ public partial class MongoRepository case AgentField.KnowledgeBase: UpdateAgentKnowledgeBases(agent.Id, agent.KnowledgeBases); break; - case AgentField.EventRule: - UpdateAgentEventRules(agent.Id, agent.EventRules); + case AgentField.Rule: + UpdateAgentRules(agent.Id, agent.Rules); break; case AgentField.MaxMessageCount: UpdateAgentMaxMessageCount(agent.Id, agent.MaxMessageCount); @@ -259,15 +259,15 @@ public partial class MongoRepository _dc.Agents.UpdateOne(filter, update); } - private void UpdateAgentEventRules(string agentId, List rules) + private void UpdateAgentRules(string agentId, List rules) { if (rules == null) return; - var elements = rules?.Select(x => AgentEventRuleMongoElement.ToMongoElement(x))?.ToList() ?? []; + var elements = rules?.Select(x => AgentRuleMongoElement.ToMongoElement(x))?.ToList() ?? []; var filter = Builders.Filter.Eq(x => x.Id, agentId); var update = Builders.Update - .Set(x => x.EventRules, elements) + .Set(x => x.Rules, elements) .Set(x => x.UpdatedTime, DateTime.UtcNow); _dc.Agents.UpdateOne(filter, update); @@ -314,7 +314,7 @@ public partial class MongoRepository .Set(x => x.Samples, agent.Samples) .Set(x => x.Utilities, agent.Utilities.Select(u => AgentUtilityMongoElement.ToMongoElement(u)).ToList()) .Set(x => x.KnowledgeBases, agent.KnowledgeBases.Select(u => AgentKnowledgeBaseMongoElement.ToMongoElement(u)).ToList()) - .Set(x => x.EventRules, agent.EventRules.Select(e => AgentEventRuleMongoElement.ToMongoElement(e)).ToList()) + .Set(x => x.Rules, agent.Rules.Select(e => AgentRuleMongoElement.ToMongoElement(e)).ToList()) .Set(x => x.LlmConfig, AgentLlmConfigMongoElement.ToMongoElement(agent.LlmConfig)) .Set(x => x.IsPublic, agent.IsPublic) .Set(x => x.UpdatedTime, DateTime.UtcNow); @@ -472,7 +472,7 @@ public partial class MongoRepository RoutingRules = x.RoutingRules?.Select(r => RoutingRuleMongoElement.ToMongoElement(r))?.ToList() ?? [], Utilities = x.Utilities?.Select(u => AgentUtilityMongoElement.ToMongoElement(u))?.ToList() ?? [], KnowledgeBases = x.KnowledgeBases?.Select(k => AgentKnowledgeBaseMongoElement.ToMongoElement(k))?.ToList() ?? [], - EventRules = x.EventRules?.Select(e => AgentEventRuleMongoElement.ToMongoElement(e))?.ToList() ?? [], + Rules = x.Rules?.Select(e => AgentRuleMongoElement.ToMongoElement(e))?.ToList() ?? [], CreatedTime = x.CreatedDateTime, UpdatedTime = x.UpdatedDateTime }).ToList(); @@ -565,7 +565,7 @@ public partial class MongoRepository RoutingRules = agentDoc.RoutingRules?.Select(r => RoutingRuleMongoElement.ToDomainElement(agentDoc.Id, agentDoc.Name, r))?.ToList() ?? [], Utilities = agentDoc.Utilities?.Select(u => AgentUtilityMongoElement.ToDomainElement(u))?.ToList() ?? [], KnowledgeBases = agentDoc.KnowledgeBases?.Select(x => AgentKnowledgeBaseMongoElement.ToDomainElement(x))?.ToList() ?? [], - EventRules = agentDoc.EventRules?.Select(e => AgentEventRuleMongoElement.ToDomainElement(e))?.ToList() ?? [] + Rules = agentDoc.Rules?.Select(e => AgentRuleMongoElement.ToDomainElement(e))?.ToList() ?? [] }; } } From 3b63b8b720cc330f2a067f88070f5220d5548cfe Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Tue, 7 Jan 2025 16:30:47 -0600 Subject: [PATCH 48/48] add http request hook --- .../Http/IHttpRequestHook.cs | 8 ++++ .../Users/IAuthenticationHook.cs | 1 - .../Functions/HandleHttpRequestFn.cs | 19 +++------ .../Hooks/BasicHttpRequestHook.cs | 40 +++++++++++++++++++ .../HttpHandlerPlugin.cs | 2 + 5 files changed, 56 insertions(+), 14 deletions(-) create mode 100644 src/Infrastructure/BotSharp.Abstraction/Http/IHttpRequestHook.cs create mode 100644 src/Plugins/BotSharp.Plugin.HttpHandler/Hooks/BasicHttpRequestHook.cs diff --git a/src/Infrastructure/BotSharp.Abstraction/Http/IHttpRequestHook.cs b/src/Infrastructure/BotSharp.Abstraction/Http/IHttpRequestHook.cs new file mode 100644 index 00000000..18b96e77 --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Http/IHttpRequestHook.cs @@ -0,0 +1,8 @@ +using System.Net.Http.Headers; + +namespace BotSharp.Abstraction.Http; + +public interface IHttpRequestHook +{ + void OnAddHttpHeaders(HttpHeaders headers); +} diff --git a/src/Infrastructure/BotSharp.Abstraction/Users/IAuthenticationHook.cs b/src/Infrastructure/BotSharp.Abstraction/Users/IAuthenticationHook.cs index d953271f..939d509e 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Users/IAuthenticationHook.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Users/IAuthenticationHook.cs @@ -1,5 +1,4 @@ using BotSharp.Abstraction.Users.Models; -using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; namespace BotSharp.Abstraction.Users; diff --git a/src/Plugins/BotSharp.Plugin.HttpHandler/Functions/HandleHttpRequestFn.cs b/src/Plugins/BotSharp.Plugin.HttpHandler/Functions/HandleHttpRequestFn.cs index f9a4342c..52f5075b 100644 --- a/src/Plugins/BotSharp.Plugin.HttpHandler/Functions/HandleHttpRequestFn.cs +++ b/src/Plugins/BotSharp.Plugin.HttpHandler/Functions/HandleHttpRequestFn.cs @@ -1,5 +1,6 @@ using System.Net.Http; using System.Net.Mime; +using BotSharp.Abstraction.Http; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; @@ -13,7 +14,6 @@ public class HandleHttpRequestFn : IFunctionCallback private readonly IServiceProvider _services; private readonly ILogger _logger; private readonly IHttpClientFactory _httpClientFactory; - private readonly IHttpContextAccessor _context; private readonly BotSharpOptions _options; public HandleHttpRequestFn(IServiceProvider services, @@ -25,7 +25,6 @@ public class HandleHttpRequestFn : IFunctionCallback _services = services; _logger = logger; _httpClientFactory = httpClientFactory; - _context = context; _options = options; } @@ -57,7 +56,7 @@ public class HandleHttpRequestFn : IFunctionCallback if (string.IsNullOrEmpty(url)) return null; using var client = _httpClientFactory.CreateClient(); - AddRequestHeaders(client); + PrepareRequestHeaders(client); var (uri, request) = BuildHttpRequest(url, method, content); var response = await client.SendAsync(request); @@ -69,18 +68,12 @@ public class HandleHttpRequestFn : IFunctionCallback return response; } - private void AddRequestHeaders(HttpClient client) + private void PrepareRequestHeaders(HttpClient client) { - var auth = $"{_context.HttpContext.Request.Headers["Authorization"]}"; - var origin = $"{_context.HttpContext.Request.Headers["Origin"]}"; - - client.DefaultRequestHeaders.Add("Authorization", auth); - - var settings = _services.GetRequiredService(); - origin = !string.IsNullOrEmpty(origin) ? origin : settings.Origin; - if (!string.IsNullOrEmpty(origin)) + var hooks = _services.GetServices(); + foreach (var hook in hooks) { - client.DefaultRequestHeaders.Add("Origin", origin); + hook.OnAddHttpHeaders(client.DefaultRequestHeaders); } } diff --git a/src/Plugins/BotSharp.Plugin.HttpHandler/Hooks/BasicHttpRequestHook.cs b/src/Plugins/BotSharp.Plugin.HttpHandler/Hooks/BasicHttpRequestHook.cs new file mode 100644 index 00000000..5de858f2 --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.HttpHandler/Hooks/BasicHttpRequestHook.cs @@ -0,0 +1,40 @@ +using BotSharp.Abstraction.Http; +using Microsoft.AspNetCore.Http; +using System.Net.Http.Headers; + +namespace BotSharp.Plugin.HttpHandler.Hooks; + +public class BasicHttpRequestHook : IHttpRequestHook +{ + private readonly IServiceProvider _services; + private readonly IHttpContextAccessor _context; + + private const string AUTHORIZATION = "Authorization"; + private const string ORIGIN = "Origin"; + + public BasicHttpRequestHook( + IServiceProvider services, + IHttpContextAccessor context) + { + _services = services; + _context = context; + } + + public void OnAddHttpHeaders(HttpHeaders headers) + { + var settings = _services.GetRequiredService(); + + var auth = $"{_context.HttpContext.Request.Headers[AUTHORIZATION]}"; + if (!string.IsNullOrEmpty(auth)) + { + headers.Add(AUTHORIZATION, auth); + } + + var origin = $"{_context.HttpContext.Request.Headers[ORIGIN]}"; + origin = !string.IsNullOrEmpty(settings.Origin) ? settings.Origin : origin; + if (!string.IsNullOrEmpty(origin)) + { + headers.Add(ORIGIN, origin); + } + } +} diff --git a/src/Plugins/BotSharp.Plugin.HttpHandler/HttpHandlerPlugin.cs b/src/Plugins/BotSharp.Plugin.HttpHandler/HttpHandlerPlugin.cs index 9c8cab55..a3c85c0b 100644 --- a/src/Plugins/BotSharp.Plugin.HttpHandler/HttpHandlerPlugin.cs +++ b/src/Plugins/BotSharp.Plugin.HttpHandler/HttpHandlerPlugin.cs @@ -1,4 +1,5 @@ using BotSharp.Abstraction.Agents; +using BotSharp.Abstraction.Http; using BotSharp.Abstraction.Settings; using Microsoft.Extensions.Configuration; @@ -21,5 +22,6 @@ public class HttpHandlerPlugin : IBotSharpPlugin }); services.AddScoped(); + services.AddScoped(); } }