Skip to content

Commit ac78e6d

Browse files
authored
Merge pull request #811 from Qtoss-AI/master
WebDriver enhancement
2 parents 7bb63bc + 9dc1f5c commit ac78e6d

38 files changed

+328
-179
lines changed

src/Infrastructure/BotSharp.Abstraction/Browsing/IWebBrowser.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,5 @@ public interface IWebBrowser
2828
Task<BrowserActionResult> CloseCurrentPage(MessageInfo message);
2929
Task<BrowserActionResult> SendHttpRequest(MessageInfo message, HttpRequestParams actionParams);
3030
Task<BrowserActionResult> GetAttributeValue(MessageInfo message, ElementLocatingArgs location);
31+
Task<BrowserActionResult> SetAttributeValue(MessageInfo message, ElementLocatingArgs location);
3132
}

src/Infrastructure/BotSharp.Abstraction/Browsing/Models/BrowserActionArgs.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@ namespace BotSharp.Abstraction.Browsing.Models;
33
public class BrowserActionArgs
44
{
55
public bool Headless { get; set; }
6+
public string? UserDataDir { get; set; }
7+
public string? RemoteHostUrl { get; set; }
68
}

src/Infrastructure/BotSharp.Abstraction/Browsing/Models/BrowserActionResult.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ public class BrowserActionResult
88
public string? StackTrace { get; set; }
99
public string? Selector { get; set; }
1010
public string? Body { get; set; }
11+
/// <summary>
12+
/// Page open in new tab after button click
13+
/// </summary>
14+
public string? UrlAfterAction { get; set; }
1115
public bool IsHighlighted { get; set; }
1216

1317
public override string ToString()

src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public interface IBotSharpRepository : IHaveServiceProvider
3333
List<User> GetUserByIds(List<string> ids) => throw new NotImplementedException();
3434
List<User> GetUsersByAffiliateId(string affiliateId) => throw new NotImplementedException();
3535
User? GetUserByUserName(string userName) => throw new NotImplementedException();
36+
void UpdateUserName(string userId, string userName) => throw new NotImplementedException();
3637
Dashboard? GetDashboard(string id = null) => throw new NotImplementedException();
3738
void CreateUser(User user) => throw new NotImplementedException();
3839
void UpdateExistUser(string userId, User user) => throw new NotImplementedException();
@@ -49,6 +50,7 @@ public interface IBotSharpRepository : IHaveServiceProvider
4950
PagedItems<User> GetUsers(UserFilter filter) => throw new NotImplementedException();
5051
User? GetUserDetails(string userId, bool includeAgent = false) => throw new NotImplementedException();
5152
bool UpdateUser(User user, bool updateUserAgents = false) => throw new NotImplementedException();
53+
5254
#endregion
5355

5456
#region Agent

src/Infrastructure/BotSharp.Abstraction/Users/IUserService.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public interface IUserService
1717
Task<Token?> GetAffiliateToken(string authorization);
1818
Task<Token?> GetAdminToken(string authorization);
1919
Task<Token?> GetToken(string authorization);
20+
Task<Token> CreateTokenByUser(User user);
2021
Task<User> GetMyProfile();
2122
Task<bool> VerifyUserNameExisting(string userName);
2223
Task<bool> VerifyEmailExisting(string email);

src/Infrastructure/BotSharp.Abstraction/Users/Models/User.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ public class User
2323
public bool Verified { get; set; }
2424
public string RegionCode { get; set; } = "CN";
2525
public string? AffiliateId { get; set; }
26-
public string? ReferralCode { get; set; }
2726
public string? EmployeeId { get; set; }
2827
public bool IsDisabled { get; set; }
2928
public IEnumerable<string> Permissions { get; set; } = [];

src/Infrastructure/BotSharp.Abstraction/Users/Models/UserActivationModel.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ public class UserActivationModel
44
{
55
public string UserName { get; set; }
66
public string VerificationCode { get; set; }
7+
public string RegionCode { get; set; } = "CN";
78
}

src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,10 @@
190190
<ItemGroup>
191191
<PackageReference Include="Aspects.Cache" Version="2.0.4" />
192192
<PackageReference Include="DistributedLock.Redis" Version="1.0.3" />
193-
<PackageReference Include="EntityFrameworkCore.BootKit" Version="8.6.0" />
193+
<PackageReference Include="EntityFrameworkCore.BootKit" Version="8.8.0" />
194194
<PackageReference Include="Fluid.Core" Version="2.11.1" />
195195
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" />
196-
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
196+
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.1" />
197197
<PackageReference Include="Nanoid" Version="3.1.0" />
198198
</ItemGroup>
199199

src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,7 @@ public async Task BroadcastAsync(string channel, string message)
3939

4040
// Add a message to the stream, keeping only the latest 1 million messages
4141
var messageId = await db.StreamAddAsync(channel,
42-
[
43-
new NameValueEntry("message", message),
44-
new NameValueEntry("timestamp", DateTime.UtcNow.ToString("o"))
45-
],
42+
AssembleMessage(message),
4643
maxLength: 1000 * 10000);
4744

4845
_logger.LogInformation($"Published message {channel} {message} ({messageId})");
@@ -82,6 +79,25 @@ private bool CheckMessageExists(IDatabase db, string channel, string fieldName,
8279
return exists;
8380
}
8481

82+
public static NameValueEntry[] AssembleMessage(RedisValue message)
83+
{
84+
return
85+
[
86+
new NameValueEntry("message", message),
87+
new NameValueEntry("timestamp", DateTime.UtcNow.ToString("o"))
88+
];
89+
}
90+
91+
public static NameValueEntry[] AssembleErrorMessage(RedisValue message, string error)
92+
{
93+
return
94+
[
95+
new NameValueEntry("message", message),
96+
new NameValueEntry("timestamp", DateTime.UtcNow.ToString("o")),
97+
new NameValueEntry("error", error)
98+
];
99+
}
100+
85101
public async Task ReDispatchAsync(string channel, int count = 10, string order = "asc")
86102
{
87103
var db = _redis.GetDatabase();
@@ -93,10 +109,10 @@ public async Task ReDispatchAsync(string channel, int count = 10, string order =
93109

94110
try
95111
{
96-
var messageId = await db.StreamAddAsync(channel, [
97-
new NameValueEntry("message", entry.Values[0].Value),
98-
new NameValueEntry("timestamp", DateTime.UtcNow.ToString("o"))
99-
]);
112+
var message = entry.Values.First(x => x.Name == "message").Value;
113+
var messageId = await db.StreamAddAsync(channel,
114+
AssembleMessage(message),
115+
maxLength: 1000 * 10000);
100116

101117
_logger.LogWarning($"ReDispatched message: {channel} {entry.Values[0].Value} ({messageId})");
102118

@@ -164,20 +180,7 @@ public async Task RemoveAsync(string channel, int count = 10)
164180
var db = _redis.GetDatabase();
165181

166182
var entries = await db.StreamRangeAsync(channel, "-", "+", count: count, messageOrder: Order.Ascending);
167-
foreach (var entry in entries)
168-
{
169-
_logger.LogInformation($"Fetched message: {channel} {entry.Values[0].Value} ({entry.Id})");
170-
171-
try
172-
{
173-
await db.StreamDeleteAsync(channel, [entry.Id]);
174-
175-
_logger.LogWarning($"Deleted message: {channel} {entry.Values[0].Value} ({entry.Id})");
176-
}
177-
catch (Exception ex)
178-
{
179-
_logger.LogError($"Error processing message: {ex.Message}, event id: {channel} {entry.Id}\r\n{ex}");
180-
}
181-
}
183+
var deletedCount = await db.StreamDeleteAsync(channel, entries.Select(x => x.Id).ToArray());
184+
_logger.LogWarning($"Deleted {deletedCount} messages from Redis stream {channel}");
182185
}
183186
}

src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ public async Task SubscribeAsync(string channel, string group, int? port, bool p
4242
await CreateConsumerGroup(db, channel, group);
4343
}
4444

45+
await CreateConsumerGroup(db, $"{channel}-Error", group);
46+
4547
var consumer = Environment.MachineName;
4648
if (port.HasValue)
4749
{
@@ -58,28 +60,36 @@ public async Task SubscribeAsync(string channel, string group, int? port, bool p
5860
break;
5961
}
6062

61-
if (priorityEnabled)
63+
try
6264
{
63-
if (await HandleGroupMessage(db, $"{channel}-{EventPriority.High}", group, consumer, received) > 0)
65+
if (priorityEnabled)
6466
{
65-
continue;
66-
}
67+
if (await HandleGroupMessage(db, $"{channel}-{EventPriority.High}", group, consumer, received, $"{channel}-Error") > 0)
68+
{
69+
continue;
70+
}
6771

68-
if (await HandleGroupMessage(db, $"{channel}-{EventPriority.Medium}", group, consumer, received) > 0)
72+
if (await HandleGroupMessage(db, $"{channel}-{EventPriority.Medium}", group, consumer, received, $"{channel}-Error") > 0)
73+
{
74+
continue;
75+
}
76+
77+
await HandleGroupMessage(db, $"{channel}-{EventPriority.Low}", group, consumer, received, $"{channel}-Error");
78+
}
79+
else
6980
{
70-
continue;
81+
await HandleGroupMessage(db, channel, group, consumer, received, $"{channel}-Error");
7182
}
72-
73-
await HandleGroupMessage(db, $"{channel}-{EventPriority.Low}", group, consumer, received);
7483
}
75-
else
84+
catch (Exception ex)
7685
{
77-
await HandleGroupMessage(db, channel, group, consumer, received);
86+
_logger.LogError($"Error processing message: {ex.Message}\r\n{ex}");
87+
await Task.Delay(1000 * 60);
7888
}
7989
}
8090
}
8191

82-
private async Task<int> HandleGroupMessage(IDatabase db, string channel, string group, string consumer, Func<string, string, Task> received)
92+
private async Task<int> HandleGroupMessage(IDatabase db, string channel, string group, string consumer, Func<string, string, Task> received, string errorChannel)
8393
{
8494
var entries = await db.StreamReadGroupAsync(channel, group, consumer, count: 1);
8595
foreach (var entry in entries)
@@ -90,13 +100,24 @@ private async Task<int> HandleGroupMessage(IDatabase db, string channel, string
90100
try
91101
{
92102
await received(channel, entry.Values[0].Value);
93-
94-
// Optionally delete the message to save space
95-
await db.StreamDeleteAsync(channel, [entry.Id]);
96103
}
97104
catch (Exception ex)
98105
{
99-
_logger.LogError($"Error processing message: {ex.Message}, event id: {channel} {entry.Id}\r\n{ex}");
106+
_logger.LogError($"Error processing message: {ex.Message}, event id: {channel} {entry.Id} {entry.Values[0].Value}");
107+
108+
// Add a message to the Error stream, keeping only the latest 1 million messages
109+
await db.StreamAddAsync(errorChannel,
110+
RedisPublisher.AssembleErrorMessage(entry.Values[0].Value, ex.Message),
111+
messageId: entry.Id,
112+
maxLength: 1000 * 10000);
113+
114+
// Slow down the consumer if there are errors
115+
await Task.Delay(1000 * 10);
116+
}
117+
finally
118+
{
119+
var deletedCount = await db.StreamDeleteAsync(channel, [entry.Id]);
120+
_logger.LogInformation($"Handled message {entry.Id}: {deletedCount == 1}");
100121
}
101122
}
102123

src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ record = db.GetUserByUserName(user.UserName);
6262

6363
if (!string.IsNullOrWhiteSpace(user.Phone))
6464
{
65-
record = db.GetUserByPhone(user.Phone);
65+
record = db.GetUserByPhone(user.Phone, regionCode: (string.IsNullOrWhiteSpace(user.RegionCode) ? "CN" : user.RegionCode));
6666
}
6767

6868
if (record == null && !string.IsNullOrWhiteSpace(user.Email))
@@ -112,7 +112,7 @@ record = user;
112112
db.UpdateExistUser(hasRegisterId, record);
113113
}
114114

115-
_logger.LogWarning($"Created new user account: {record.Id} {record.UserName}");
115+
_logger.LogWarning($"Created new user account: {record.Id} {record.UserName}, RegionCode: {record.RegionCode}");
116116
Utilities.ClearCache();
117117

118118
var hooks = _services.GetServices<IAuthenticationHook>();
@@ -127,7 +127,8 @@ record = user;
127127
public async Task<bool> UpdatePassword(string password, string verificationCode)
128128
{
129129
var db = _services.GetRequiredService<IBotSharpRepository>();
130-
var record = db.GetUserByUserName(_user.UserName);
130+
131+
var record = db.GetUserById(_user.Id);
131132

132133
if (record == null)
133134
{
@@ -473,7 +474,7 @@ public async Task<Token> ActiveUser(UserActivationModel model)
473474
var record = id.Contains("@") ? db.GetUserByEmail(id) : db.GetUserByUserName(id);
474475
if (record == null)
475476
{
476-
record = db.GetUserByPhone(id);
477+
record = db.GetUserByPhone(id, regionCode: (string.IsNullOrWhiteSpace(model.RegionCode) ? "CN" : model.RegionCode));
477478
}
478479

479480
if (record == null)
@@ -505,6 +506,20 @@ record = db.GetUserByPhone(id);
505506
return token;
506507
}
507508

509+
public async Task<Token> CreateTokenByUser(User user)
510+
{
511+
var accessToken = GenerateJwtToken(user);
512+
var jwt = new JwtSecurityTokenHandler().ReadJwtToken(accessToken);
513+
var token = new Token
514+
{
515+
AccessToken = accessToken,
516+
ExpireTime = jwt.Payload.Exp.Value,
517+
TokenType = "Bearer",
518+
Scope = "api"
519+
};
520+
return token;
521+
}
522+
508523
public async Task<bool> VerifyUserNameExisting(string userName)
509524
{
510525
if (string.IsNullOrEmpty(userName))
@@ -646,7 +661,7 @@ record = db.GetUserByEmail(user.Email);
646661

647662
if (!string.IsNullOrEmpty(user.Phone))
648663
{
649-
record = db.GetUserByPhone(user.Phone);
664+
record = db.GetUserByPhone(user.Phone, regionCode: (string.IsNullOrWhiteSpace(user.RegionCode) ? "CN" : user.RegionCode));
650665
}
651666

652667
if (record == null)
@@ -695,7 +710,7 @@ public async Task<bool> ModifyUserPhone(string phone, string regionCode)
695710
var curUser = await GetMyProfile();
696711
var db = _services.GetRequiredService<IBotSharpRepository>();
697712
var record = db.GetUserById(curUser.Id);
698-
var existPhone = db.GetUserByPhone(phone);
713+
var existPhone = db.GetUserByPhone(phone, regionCode: regionCode);
699714

700715
if (record == null || (existPhone != null && existPhone.RegionCode == regionCode))
701716
{

src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using BotSharp.Abstraction.Users.Enums;
21
using BotSharp.Abstraction.Users.Settings;
32
using Microsoft.AspNetCore.Authentication;
43
using Microsoft.AspNetCore.Authentication.Cookies;
@@ -244,7 +243,7 @@ public IActionResult GetUserAvatar()
244243
var file = fileStorage.GetUserAvatar();
245244
if (string.IsNullOrEmpty(file))
246245
{
247-
return NotFound();
246+
return NoContent();
248247
}
249248
return BuildFileResult(file);
250249
}

src/Infrastructure/BotSharp.OpenAPI/ViewModels/Users/UserCreationModel.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ public class UserCreationModel
1313
public string Type { get; set; } = UserType.Client;
1414
public string Role { get; set; } = UserRole.User;
1515
public string RegionCode { get; set; } = "CN";
16-
public string? ReferralCode { get; set; }
1716
public User ToUser()
1817
{
1918
return new User
@@ -27,7 +26,6 @@ public User ToUser()
2726
Role = Role,
2827
Type = Type,
2928
RegionCode = RegionCode,
30-
ReferralCode = ReferralCode
3129
};
3230
}
3331
}

src/Plugins/BotSharp.Plugin.HttpHandler/BotSharp.Plugin.HttpHandler.csproj

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,6 @@
3333
</Content>
3434
</ItemGroup>
3535

36-
<ItemGroup>
37-
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
38-
</ItemGroup>
39-
4036
<ItemGroup>
4137
<ProjectReference Include="..\..\Infrastructure\BotSharp.Core\BotSharp.Core.csproj" />
4238
</ItemGroup>

src/Plugins/BotSharp.Plugin.MongoStorage/BotSharp.Plugin.MongoStorage.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
</PropertyGroup>
1212

1313
<ItemGroup>
14-
<PackageReference Include="MongoDB.Driver" Version="3.0.0" />
14+
<PackageReference Include="MongoDB.Driver" Version="3.1.0" />
1515
</ItemGroup>
1616

1717
<ItemGroup>

src/Plugins/BotSharp.Plugin.MongoStorage/MongoDbContext.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ private string GetDatabaseName(string mongoDbConnectionString)
3636
Key = x.Split("=")[0],
3737
Value = x.Split("=")[1]
3838
}).ToList();
39-
39+
4040
var source = queries.FirstOrDefault(x => x.Key.IsEqualTo(DB_NAME_INDEX));
4141
if (source != null)
4242
{
@@ -168,4 +168,5 @@ public IMongoCollection<RoleAgentDocument> RoleAgents
168168

169169
public IMongoCollection<CrontabItemDocument> CrontabItems
170170
=> Database.GetCollection<CrontabItemDocument>($"{_collectionPrefix}_CronTabItems");
171+
171172
}

0 commit comments

Comments
 (0)