Merge branch 'SciSharp:master' into master

This commit is contained in:
hchen2020 2024-07-29 10:54:23 -05:00 committed by GitHub
commit da4d811a54
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 134 additions and 86 deletions

View file

@ -0,0 +1,9 @@
using BotSharp.Abstraction.Browsing.Models;
namespace BotSharp.Abstraction.Browsing;
public interface IWebPageResponseHook
{
void OnDataFetched(MessageInfo message, string url, string postData, string responsData);
T? GetResponse<T>(MessageInfo message, string url);
}

View file

@ -12,13 +12,6 @@ public class PageActionArgs
public string Url { get; set; } = null!;
public bool OpenNewTab { get; set; } = false;
public bool WaitForNetworkIdle = true;
public bool WaitForNetworkIdle { get; set; } = true;
public float? Timeout { get; set; }
/// <summary>
/// On page data fetched
/// </summary>
public DataFetched? OnDataFetched { get; set; }
}
public delegate void DataFetched(string url, string data);

View file

@ -25,6 +25,8 @@ public interface IBotSharpRepository
void UpdateUserVerified(string userId) => throw new NotImplementedException();
void UpdateUserVerificationCode(string userId, string verficationCode) => throw new NotImplementedException();
void UpdateUserPassword(string userId, string password) => throw new NotImplementedException();
void UpdateUserEmail(string userId, string email)=> throw new NotImplementedException();
void UpdateUserPhone(string userId, string Iphone) => throw new NotImplementedException();
#endregion
#region Agent

View file

@ -14,4 +14,6 @@ public interface IUserService
Task<bool> VerifyEmailExisting(string email);
Task<bool> SendVerificationCodeResetPassword(User user);
Task<bool> ResetUserPassword(User user);
Task<bool> ModifyUserEmail(string email);
Task<bool> ModifyUserPhone(string phone);
}

View file

@ -170,7 +170,7 @@
<ItemGroup>
<PackageReference Include="Aspects.Cache" Version="2.0.4" />
<PackageReference Include="DistributedLock.Redis" Version="1.0.3" />
<PackageReference Include="EntityFrameworkCore.BootKit" Version="8.4.2" />
<PackageReference Include="EntityFrameworkCore.BootKit" Version="8.5.0" />
<PackageReference Include="Fluid.Core" Version="2.8.0" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />

View file

@ -28,7 +28,7 @@ public static class BotSharpCoreExtensions
services.AddScoped<IBotSharpRepository>(sp =>
{
var myDatabaseSettings = sp.GetRequiredService<BotSharpDatabaseSettings>();
return DataContextHelper.GetDbContext<BotSharpDbContext, DbContext4SqlServer>(myDatabaseSettings, sp);
return DataContextHelper.GetSqlServerDbContext<BotSharpDbContext>(myDatabaseSettings, sp);
});
return services;

View file

@ -1,14 +1,12 @@
using Microsoft.Data.SqlClient;
using MySqlConnector;
using System.Data.Common;
namespace BotSharp.Core.Repository;
public static class DataContextHelper
{
public static T GetDbContext<T, Tdb>(BotSharpDatabaseSettings settings, IServiceProvider serviceProvider)
public static T GetSqlServerDbContext<T>(BotSharpDatabaseSettings settings, IServiceProvider serviceProvider)
where T : Database, new()
where Tdb : DataContext
{
if (settings.Assemblies == null)
throw new Exception("Please set assemblies.");
@ -18,32 +16,40 @@ public static class DataContextHelper
var dc = new T();
if (typeof(T) == typeof(BotSharpDbContext))
{
if (typeof(Tdb).Name.StartsWith("DbContext4SqlServer"))
dc.BindDbContext<IBotSharpTable, DbContext4SqlServer>(new DatabaseBind
{
dc.BindDbContext<IBotSharpTable, Tdb>(new DatabaseBind
{
ServiceProvider = serviceProvider,
MasterConnection = new SqlConnection(settings.BotSharp.Master),
SlaveConnections = settings.BotSharp.Slavers.Length == 0 ?
new List<DbConnection> { new SqlConnection(settings.BotSharp.Master) } :
settings.BotSharp.Slavers.Select(x => new SqlConnection(x) as DbConnection)
.ToList(),
CreateDbIfNotExist = true
});
}
else if (typeof(Tdb).Name.StartsWith("DbContext4Aurora") ||
typeof(Tdb).Name.StartsWith("DbContext4MySql"))
{
dc.BindDbContext<IBotSharpTable, Tdb>(new DatabaseBind
{
ServiceProvider = serviceProvider,
MasterConnection = new MySqlConnection(settings.BotSharp.Master),
SlaveConnections = settings.BotSharp.Slavers
.Select(x => new MySqlConnection(x) as DbConnection).ToList(),
CreateDbIfNotExist = true
});
}
ServiceProvider = serviceProvider,
MasterConnection = new SqlConnection(settings.BotSharp.Master),
SlaveConnections = settings.BotSharp.Slavers.Length == 0 ?
new List<DbConnection> { new SqlConnection(settings.BotSharp.Master) } :
settings.BotSharp.Slavers.Select(x => new SqlConnection(x) as DbConnection)
.ToList(),
CreateDbIfNotExist = true
});
}
return dc;
}
/*public static T GetMySqlDbContext<T>(BotSharpDatabaseSettings settings, IServiceProvider serviceProvider)
where T : Database, new()
{
if (settings.Assemblies == null)
throw new Exception("Please set assemblies.");
AppDomain.CurrentDomain.SetData("Assemblies", settings.Assemblies);
var dc = new T();
if (typeof(T) == typeof(BotSharpDbContext))
{
dc.BindDbContext<IBotSharpTable, DbContext4MySql>(new DatabaseBind
{
ServiceProvider = serviceProvider,
MasterConnection = new MySqlConnection(settings.BotSharp.Master),
SlaveConnections = settings.BotSharp.Slavers
.Select(x => new MySqlConnection(x) as DbConnection).ToList(),
CreateDbIfNotExist = true
});
}
return dc;
}*/
}

View file

@ -1,7 +1,6 @@
using System.IO;
using FunctionDef = BotSharp.Abstraction.Functions.Models.FunctionDef;
using BotSharp.Abstraction.Users.Models;
using MongoDB.Driver;
using System.Text.Encodings.Web;
using BotSharp.Abstraction.Plugins.Models;
using BotSharp.Abstraction.Statistics.Settings;

View file

@ -1,12 +1,7 @@
using Amazon.SecurityToken.Model.Internal.MarshallTransformations;
using BotSharp.Abstraction.Agents.Models;
using BotSharp.Abstraction.Functions.Models;
using BotSharp.Abstraction.MLTasks;
using BotSharp.Abstraction.Routing;
using BotSharp.Abstraction.Routing.Models;
using BotSharp.Abstraction.Routing.Planning;
using BotSharp.Abstraction.Templating;
using System.Drawing;
namespace BotSharp.Core.Routing.Planning;

View file

@ -20,7 +20,7 @@ public class UserIdentity : IUserIdentity
[JsonPropertyName("user_name")]
public string UserName
=> _claims?.FirstOrDefault(x => x.Type == "name")?.Value!;
=> _claims?.FirstOrDefault(x => x.Type == ClaimTypes.Name)?.Value!;
public string Email
=> _claims?.FirstOrDefault(x => x.Type == ClaimTypes.Email)?.Value!;

View file

@ -364,4 +364,33 @@ public class UserService : IUserService
db.UpdateUserPassword(record.Id, newPassword);
return true;
}
public async Task<bool> ModifyUserEmail(string email)
{
var curUser = await GetMyProfile();
var db = _services.GetRequiredService<IBotSharpRepository>();
var record = db.GetUserById(curUser.Id);
if (record == null)
{
return false;
}
db.UpdateUserEmail(record.Id, email);
return true;
}
public async Task<bool> ModifyUserPhone(string phone)
{
var curUser = await GetMyProfile();
var db = _services.GetRequiredService<IBotSharpRepository>();
var record = db.GetUserById(curUser.Id);
if (record == null)
{
return false;
}
db.UpdateUserPhone(record.Id, phone);
return true;
}
}

View file

@ -1,9 +1,5 @@
using BotSharp.Abstraction.Loggers.Models;
using Microsoft.AspNetCore.Hosting;
using SharpCompress.Compressors.Xz;
using System;
using System.IO;
using System.Net.Mime;
namespace BotSharp.OpenAPI.Controllers;

View file

@ -121,6 +121,18 @@ public class UserController : ControllerBase
return await _userService.ResetUserPassword(user.ToUser());
}
[HttpPost("/user/email/modify")]
public async Task<bool> ModifyUserEmail([FromQuery] string email)
{
return await _userService.ModifyUserEmail(email);
}
[HttpPost("/user/phone/modify")]
public async Task<bool> ModifyUserPhone([FromQuery] string phone)
{
return await _userService.ModifyUserPhone(phone);
}
#region Avatar
[HttpPost("/user/avatar")]
public bool UploadUserAvatar([FromBody] BotSharpFile file)

View file

@ -72,4 +72,20 @@ public partial class MongoRepository
.Set(x => x.UpdatedTime, DateTime.UtcNow);
_dc.Users.UpdateOne(filter, update);
}
public void UpdateUserEmail(string userId, string email)
{
var filter = Builders<UserDocument>.Filter.Eq(x => x.Id, userId);
var update = Builders<UserDocument>.Update.Set(x => x.Email, email)
.Set(x => x.UpdatedTime, DateTime.UtcNow);
_dc.Users.UpdateOne(filter, update);
}
public void UpdateUserPhone(string userId, string phone)
{
var filter = Builders<UserDocument>.Filter.Eq(x => x.Id, userId);
var update = Builders<UserDocument>.Update.Set(x => x.Phone, phone)
.Set(x => x.UpdatedTime, DateTime.UtcNow);
_dc.Users.UpdateOne(filter, update);
}
}

View file

@ -1,4 +1,3 @@
using Amazon.Runtime.Internal.Transform;
using BotSharp.Abstraction.Agents.Enums;
using BotSharp.Abstraction.MLTasks;
using BotSharp.Core.Infrastructures;

View file

@ -17,7 +17,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Playwright" Version="1.45.0" />
<PackageReference Include="Microsoft.Playwright" Version="1.45.1" />
<PackageReference Include="Selenium.WebDriver" Version="4.23.0" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.61" />
</ItemGroup>

View file

@ -93,9 +93,9 @@ public class PlaywrightInstance : IDisposable
return _contexts[ctxId];
}
public async Task<IPage> NewPage(string ctxId, DataFetched? fetched)
public async Task<IPage> NewPage(MessageInfo message, IServiceProvider services)
{
var context = await GetContext(ctxId);
var context = await GetContext(message.ContextId);
var page = await context.NewPageAsync();
// 许多网站为了防止信息被爬取,会添加一些防护手段。其中之一是检测 window.navigator.webdriver 属性。
@ -103,35 +103,37 @@ public class PlaywrightInstance : IDisposable
var js = @"Object.defineProperties(navigator, {webdriver:{get:()=>false}});";
await page.AddInitScriptAsync(js);
if (fetched != null)
page.Response += async (sender, e) =>
{
page.Response += async (sender, e) =>
if (e.Headers.ContainsKey("content-type") &&
e.Headers["content-type"].Contains("application/json") &&
(e.Request.ResourceType == "fetch" || e.Request.ResourceType == "xhr"))
{
if (e.Headers.ContainsKey("content-type") &&
e.Headers["content-type"].Contains("application/json") &&
e.Request.ResourceType == "fetch")
Serilog.Log.Information($"{e.Request.Method}: {e.Url}");
JsonElement? json = null;
try
{
Serilog.Log.Information($"fetched: {e.Url}");
JsonElement? json = null;
try
if (e.Status == 200 && e.Ok)
{
if (e.Status == 200 && e.Ok)
{
json = await e.JsonAsync();
}
else
{
Serilog.Log.Warning($"Response status: {e.Status} {e.StatusText}, OK: {e.Ok}");
}
fetched(e.Url.ToLower(), JsonSerializer.Serialize(json));
json = await e.JsonAsync();
}
catch(Exception ex)
else
{
Serilog.Log.Error(ex.ToString());
Serilog.Log.Warning($"Response status: {e.Status} {e.StatusText}, OK: {e.Ok}");
}
var webPageResponseHooks = services.GetServices<IWebPageResponseHook>();
foreach (var hook in webPageResponseHooks)
{
hook.OnDataFetched(message, e.Url.ToLower(), e.Request?.PostData ?? string.Empty, JsonSerializer.Serialize(json));
}
}
};
}
catch(Exception ex)
{
Serilog.Log.Error(ex.ToString());
}
}
};
return page;
}

View file

@ -1,5 +1,3 @@
using System.Linq;
namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
public partial class PlaywrightWebDriver
@ -26,7 +24,7 @@ public partial class PlaywrightWebDriver
}
}*/
var page = args.OpenNewTab ? await _instance.NewPage(message.ContextId, fetched: args.OnDataFetched) :
var page = args.OpenNewTab ? await _instance.NewPage(message, _services) :
_instance.GetPage(message.ContextId);
Serilog.Log.Information($"goto page: {args.Url}");
@ -64,14 +62,4 @@ public partial class PlaywrightWebDriver
return result;
}
private void Page_Response1(object sender, IResponse e)
{
throw new NotImplementedException();
}
private void Page_Response(object sender, IResponse e)
{
throw new NotImplementedException();
}
}