Merge pull request #492 from Qtoss-AI/master
Fix WebDriver locator issue.
This commit is contained in:
commit
dc6534f45f
|
|
@ -4,4 +4,7 @@ public enum BroswerActionEnum
|
|||
{
|
||||
Click = 1,
|
||||
InputText = 2,
|
||||
Typing = 3,
|
||||
Hover = 4,
|
||||
Scroll = 5,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ namespace BotSharp.Abstraction.Browsing;
|
|||
|
||||
public interface IWebBrowser
|
||||
{
|
||||
Task<BrowserActionResult> LaunchBrowser(string contextId, string? url);
|
||||
Task<BrowserActionResult> ScreenshotAsync(string contextId, string path);
|
||||
Task<BrowserActionResult> ScrollPageAsync(BrowserActionParams actionParams);
|
||||
Task<BrowserActionResult> LaunchBrowser(MessageInfo message);
|
||||
Task<BrowserActionResult> ScreenshotAsync(MessageInfo message, string path);
|
||||
Task<BrowserActionResult> ScrollPage(MessageInfo message, PageActionArgs args);
|
||||
|
||||
Task<BrowserActionResult> ActionOnElement(MessageInfo message, ElementLocatingArgs location, ElementActionArgs action);
|
||||
Task<BrowserActionResult> LocateElement(MessageInfo message, ElementLocatingArgs location);
|
||||
|
|
@ -19,11 +19,11 @@ public interface IWebBrowser
|
|||
Task<BrowserActionResult> ChangeListValue(BrowserActionParams actionParams);
|
||||
Task<BrowserActionResult> CheckRadioButton(BrowserActionParams actionParams);
|
||||
Task<BrowserActionResult> ChangeCheckbox(BrowserActionParams actionParams);
|
||||
Task<BrowserActionResult> GoToPage(string contextId, string url, bool openNewTab = false);
|
||||
Task<BrowserActionResult> GoToPage(MessageInfo message, PageActionArgs args);
|
||||
Task<string> ExtractData(BrowserActionParams actionParams);
|
||||
Task<T> EvaluateScript<T>(string contextId, string script);
|
||||
Task CloseBrowser(string contextId);
|
||||
Task CloseCurrentPage(string contextId);
|
||||
Task<BrowserActionResult> CloseCurrentPage(MessageInfo message);
|
||||
Task<BrowserActionResult> SendHttpRequest(MessageInfo message, HttpRequestParams actionParams);
|
||||
Task<BrowserActionResult> GetAttributeValue(MessageInfo message, ElementLocatingArgs location);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@ namespace BotSharp.Abstraction.Browsing.Models;
|
|||
|
||||
public class MessageInfo
|
||||
{
|
||||
public string AgentId { get; set; }
|
||||
public string ContextId { get; set; }
|
||||
public string MessageId { get; set; }
|
||||
public string AgentId { get; set; } = null!;
|
||||
public string UserId { get; set; } = null!;
|
||||
public string ContextId { get; set; } = null!;
|
||||
public string? MessageId { get; set; }
|
||||
public string? TaskId { get; set; }
|
||||
public string StepId { get; set; } = Guid.NewGuid().ToString();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
using BotSharp.Abstraction.Browsing.Enums;
|
||||
|
||||
namespace BotSharp.Abstraction.Browsing.Models;
|
||||
|
||||
public class PageActionArgs
|
||||
{
|
||||
public BroswerActionEnum Action { get; set; }
|
||||
|
||||
public string? Content { get; set; }
|
||||
public string? Direction { get; set; }
|
||||
|
||||
public string Url { get; set; } = null!;
|
||||
public bool OpenNewTab { get; set; } = false;
|
||||
}
|
||||
|
|
@ -7,8 +7,9 @@ public class User
|
|||
public string Id { get; set; } = string.Empty;
|
||||
public string UserName { get; set; } = string.Empty;
|
||||
public string FirstName { get; set; } = string.Empty;
|
||||
public string LastName { get; set; } = string.Empty;
|
||||
public string Email { get; set; } = string.Empty;
|
||||
public string? LastName { get; set; }
|
||||
public string? Email { get; set; }
|
||||
public string? Phone { get; set; }
|
||||
public string Salt { get; set; } = string.Empty;
|
||||
public string Password { get; set; } = string.Empty;
|
||||
public string Source { get; set; } = "internal";
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Aspects.Cache" Version="2.0.4" />
|
||||
<PackageReference Include="Colorful.Console" Version="1.2.15" />
|
||||
<PackageReference Include="EntityFrameworkCore.BootKit" Version="8.2.1" />
|
||||
<PackageReference Include="EntityFrameworkCore.BootKit" Version="8.3.1" />
|
||||
<PackageReference Include="Fluid.Core" Version="2.8.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
|
||||
<PackageReference Include="Nanoid" Version="3.0.0" />
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using Microsoft.IdentityModel.Tokens;
|
|||
using NanoidDotNet;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace BotSharp.Core.Users.Services;
|
||||
|
||||
|
|
@ -55,6 +56,10 @@ public class UserService : IUserService
|
|||
|
||||
record = user;
|
||||
record.Email = user.Email?.ToLower();
|
||||
if (user.Phone != null)
|
||||
{
|
||||
record.Phone = "+" + Regex.Match(user.Phone, @"\d+").Value;
|
||||
}
|
||||
record.Salt = Guid.NewGuid().ToString("N");
|
||||
record.Password = Utilities.HashText(user.Password, record.Salt);
|
||||
|
||||
|
|
|
|||
|
|
@ -95,12 +95,14 @@ public class UserController : ControllerBase
|
|||
return UserViewModel.FromUser(user);
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[HttpGet("/user/name/existing")]
|
||||
public async Task<bool> VerifyUserNameExisting([FromQuery] string userName)
|
||||
{
|
||||
return await _userService.VerifyUserNameExisting(userName);
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[HttpGet("/user/email/existing")]
|
||||
public async Task<bool> VerifyEmailExisting([FromQuery] string email)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,10 +4,11 @@ namespace BotSharp.OpenAPI.ViewModels.Users;
|
|||
|
||||
public class UserCreationModel
|
||||
{
|
||||
public string UserName { get; set; } = string.Empty;
|
||||
public string? UserName { get; set; }
|
||||
public string FirstName { get; set; } = string.Empty;
|
||||
public string LastName { get; set; } = string.Empty;
|
||||
public string Email { get; set; } = string.Empty;
|
||||
public string? LastName { get; set; }
|
||||
public string? Email { get; set; }
|
||||
public string? Phone { get; set; }
|
||||
public string Password { get; set; } = string.Empty;
|
||||
public string Role { get; set; } = UserRole.Client;
|
||||
|
||||
|
|
@ -19,6 +20,7 @@ public class UserCreationModel
|
|||
FirstName = FirstName,
|
||||
LastName = LastName,
|
||||
Email = Email,
|
||||
Phone = Phone,
|
||||
Password = Password,
|
||||
Role = Role
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,14 +5,15 @@ namespace BotSharp.OpenAPI.ViewModels.Users;
|
|||
|
||||
public class UserViewModel
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Id { get; set; } = null!;
|
||||
[JsonPropertyName("user_name")]
|
||||
public string UserName { get; set; }
|
||||
public string UserName { get; set; } = null!;
|
||||
[JsonPropertyName("first_name")]
|
||||
public string FirstName { get; set; }
|
||||
public string FirstName { get; set; } = null!;
|
||||
[JsonPropertyName("last_name")]
|
||||
public string LastName { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string? LastName { get; set; }
|
||||
public string? Email { get; set; }
|
||||
public string? Phone { get; set; }
|
||||
public string Role { get; set; } = UserRole.Client;
|
||||
[JsonPropertyName("full_name")]
|
||||
public string FullName => $"{FirstName} {LastName}".Trim();
|
||||
|
|
@ -44,6 +45,7 @@ public class UserViewModel
|
|||
FirstName = user.FirstName,
|
||||
LastName = user.LastName,
|
||||
Email = user.Email,
|
||||
Phone = user.Phone,
|
||||
Role = user.Role,
|
||||
Source = user.Source,
|
||||
ExternalId = user.ExternalId,
|
||||
|
|
|
|||
|
|
@ -4,15 +4,16 @@ namespace BotSharp.Plugin.MongoStorage.Collections;
|
|||
|
||||
public class UserDocument : MongoBase
|
||||
{
|
||||
public string UserName { get; set; }
|
||||
public string FirstName { get; set; }
|
||||
public string LastName { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string Salt { get; set; }
|
||||
public string Password { get; set; }
|
||||
public string UserName { get; set; } = null!;
|
||||
public string FirstName { get; set; } = null!;
|
||||
public string? LastName { get; set; }
|
||||
public string? Email { get; set; }
|
||||
public string? Phone { get; set; }
|
||||
public string Salt { get; set; } = null!;
|
||||
public string Password { get; set; } = null!;
|
||||
public string Source { get; set; } = "internal";
|
||||
public string? ExternalId { get; set; }
|
||||
public string Role { get; set; }
|
||||
public string Role { get; set; } = null!;
|
||||
public string? VerificationCode { get; set; }
|
||||
public bool Verified { get; set; }
|
||||
public DateTime CreatedTime { get; set; }
|
||||
|
|
@ -27,6 +28,7 @@ public class UserDocument : MongoBase
|
|||
FirstName = FirstName,
|
||||
LastName = LastName,
|
||||
Email = Email,
|
||||
Phone = Phone,
|
||||
Password = Password,
|
||||
Salt = Salt,
|
||||
Source = Source,
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ public partial class MongoRepository
|
|||
Salt = user.Salt,
|
||||
Password = user.Password,
|
||||
Email = user.Email,
|
||||
Phone = user.Phone,
|
||||
Source = user.Source,
|
||||
ExternalId = user.ExternalId,
|
||||
Role = user.Role,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>$(LangVersion)</LangVersion>
|
||||
<LangVersion>12.0</LangVersion>
|
||||
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
|
||||
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
|
||||
<GenerateDocumentationFile>$(GenerateDocumentationFile)</GenerateDocumentationFile>
|
||||
|
|
@ -19,6 +19,7 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Playwright" Version="1.44.0" />
|
||||
<PackageReference Include="Selenium.WebDriver" Version="4.21.0" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.61" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -38,16 +38,16 @@ public class PlaywrightInstance : IDisposable
|
|||
Headless = true,
|
||||
#endif
|
||||
Channel = "chrome",
|
||||
IgnoreDefaultArgs = new[]
|
||||
{
|
||||
IgnoreDefaultArgs =
|
||||
[
|
||||
"--enable-automation",
|
||||
},
|
||||
Args = new[]
|
||||
{
|
||||
],
|
||||
Args =
|
||||
[
|
||||
"--disable-infobars",
|
||||
"--no-sandbox",
|
||||
"--test-type"
|
||||
// "--start-maximized"
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
_contexts[id].Page += async (sender, e) =>
|
||||
|
|
|
|||
|
|
@ -2,8 +2,14 @@ namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
|
|||
|
||||
public partial class PlaywrightWebDriver
|
||||
{
|
||||
public async Task CloseCurrentPage(string contextId)
|
||||
public async Task<BrowserActionResult> CloseCurrentPage(MessageInfo message)
|
||||
{
|
||||
await _instance.CloseCurrentPage(contextId);
|
||||
await _instance.CloseCurrentPage(message.ContextId);
|
||||
var result = new BrowserActionResult
|
||||
{
|
||||
IsSuccess = true
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,5 +34,17 @@ public partial class PlaywrightWebDriver
|
|||
await locator.PressAsync(action.PressKey);
|
||||
}
|
||||
}
|
||||
else if (action.Action == BroswerActionEnum.Typing)
|
||||
{
|
||||
await locator.PressSequentiallyAsync(action.Content);
|
||||
if (action.PressKey != null)
|
||||
{
|
||||
await locator.PressAsync(action.PressKey);
|
||||
}
|
||||
}
|
||||
else if (action.Action == BroswerActionEnum.Hover)
|
||||
{
|
||||
await locator.HoverAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,36 +2,38 @@ namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
|
|||
|
||||
public partial class PlaywrightWebDriver
|
||||
{
|
||||
public async Task<BrowserActionResult> GoToPage(string contextId, string url, bool openNewTab = false)
|
||||
public async Task<BrowserActionResult> GoToPage(MessageInfo message, PageActionArgs args)
|
||||
{
|
||||
var result = new BrowserActionResult();
|
||||
var context = await _instance.InitInstance(contextId);
|
||||
var context = await _instance.InitInstance(message.ContextId);
|
||||
try
|
||||
{
|
||||
// Check if the page is already open
|
||||
foreach (var p in context.Pages)
|
||||
if (!args.OpenNewTab && context.Pages.Count > 0)
|
||||
{
|
||||
if (p.Url == url)
|
||||
foreach (var p in context.Pages)
|
||||
{
|
||||
result.Body = await p.ContentAsync();
|
||||
result.IsSuccess = true;
|
||||
await p.BringToFrontAsync();
|
||||
return result;
|
||||
if (p.Url == args.Url)
|
||||
{
|
||||
// Disable this due to performance issue, some page is too large
|
||||
// result.Body = await p.ContentAsync();
|
||||
result.IsSuccess = true;
|
||||
await p.BringToFrontAsync();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var page = openNewTab ? await _instance.NewPage(contextId) :
|
||||
_instance.GetPage(contextId);
|
||||
var response = await page.GotoAsync(url);
|
||||
var page = args.OpenNewTab ? await _instance.NewPage(message.ContextId) :
|
||||
_instance.GetPage(message.ContextId);
|
||||
var response = await page.GotoAsync(args.Url);
|
||||
await page.WaitForLoadStateAsync(LoadState.DOMContentLoaded);
|
||||
await page.WaitForLoadStateAsync(LoadState.NetworkIdle, new PageWaitForLoadStateOptions
|
||||
{
|
||||
Timeout = 1000 * 60 * 5
|
||||
});
|
||||
await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
|
||||
|
||||
if (response.Status == 200)
|
||||
{
|
||||
result.Body = await page.ContentAsync();
|
||||
// Disable this due to performance issue, some page is too large
|
||||
// result.Body = await page.InnerHTMLAsync("body");
|
||||
result.IsSuccess = true;
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -2,44 +2,13 @@ namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
|
|||
|
||||
public partial class PlaywrightWebDriver
|
||||
{
|
||||
public async Task<BrowserActionResult> LaunchBrowser(string contextId, string? url)
|
||||
public async Task<BrowserActionResult> LaunchBrowser(MessageInfo message)
|
||||
{
|
||||
var result = new BrowserActionResult()
|
||||
{
|
||||
IsSuccess = true
|
||||
};
|
||||
var context = await _instance.InitInstance(contextId);
|
||||
|
||||
if (!string.IsNullOrEmpty(url))
|
||||
var context = await _instance.InitInstance(message.ContextId);
|
||||
var result = new BrowserActionResult
|
||||
{
|
||||
// Check if the page is already open
|
||||
foreach (var p in context.Pages)
|
||||
{
|
||||
if (p.Url == url)
|
||||
{
|
||||
await p.BringToFrontAsync();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
var page = await _instance.NewPage(contextId);
|
||||
|
||||
try
|
||||
{
|
||||
var response = await page.GotoAsync(url, new PageGotoOptions
|
||||
{
|
||||
Timeout = 15 * 1000
|
||||
});
|
||||
await page.WaitForLoadStateAsync(LoadState.DOMContentLoaded);
|
||||
result.IsSuccess = response.Status == 200;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Message = ex.Message;
|
||||
result.StackTrace = ex.StackTrace;
|
||||
_logger.LogError(ex.Message);
|
||||
}
|
||||
}
|
||||
IsSuccess = context.Pages.Count > 0
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ public partial class PlaywrightWebDriver
|
|||
locator = locator.Locator("..");
|
||||
}
|
||||
|
||||
result.Selector = locator.ToString().Split('@').Last();
|
||||
result.Selector = locator.ToString().Split("Locator@").Last();
|
||||
|
||||
// Make sure the element is visible
|
||||
/*if (!await locator.IsVisibleAsync())
|
||||
|
|
@ -117,7 +117,7 @@ public partial class PlaywrightWebDriver
|
|||
}
|
||||
else
|
||||
{
|
||||
result.Selector = locator.ToString();
|
||||
result.Selector = locator.ToString().Split("Locator@").Last();
|
||||
result.IsSuccess = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@ namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
|
|||
|
||||
public partial class PlaywrightWebDriver
|
||||
{
|
||||
public async Task<BrowserActionResult> ScreenshotAsync(string contextId, string path)
|
||||
public async Task<BrowserActionResult> ScreenshotAsync(MessageInfo message, string path)
|
||||
{
|
||||
var result = new BrowserActionResult();
|
||||
|
||||
await _instance.Wait(contextId);
|
||||
var page = _instance.GetPage(contextId);
|
||||
await _instance.Wait(message.ContextId);
|
||||
var page = _instance.GetPage(message.ContextId);
|
||||
|
||||
await Task.Delay(500);
|
||||
var bytes = await page.ScreenshotAsync(new PageScreenshotOptions
|
||||
|
|
|
|||
|
|
@ -2,21 +2,43 @@ namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
|
|||
|
||||
public partial class PlaywrightWebDriver
|
||||
{
|
||||
public async Task<BrowserActionResult> ScrollPageAsync(BrowserActionParams actionParams)
|
||||
public async Task<BrowserActionResult> ScrollPage(MessageInfo message, PageActionArgs args)
|
||||
{
|
||||
var result = new BrowserActionResult();
|
||||
await _instance.Wait(actionParams.ContextId);
|
||||
await _instance.Wait(message.ContextId);
|
||||
|
||||
var page = _instance.GetPage(actionParams.ContextId);
|
||||
var page = _instance.GetPage(message.ContextId);
|
||||
|
||||
if(actionParams.Context.Direction == "down")
|
||||
await page.EvaluateAsync("window.scrollBy(0, window.innerHeight - 200)");
|
||||
else if (actionParams.Context.Direction == "up")
|
||||
await page.EvaluateAsync("window.scrollBy(0, -window.innerHeight + 200)");
|
||||
else if (actionParams.Context.Direction == "left")
|
||||
await page.EvaluateAsync("window.scrollBy(-400, 0)");
|
||||
else if (actionParams.Context.Direction == "right")
|
||||
await page.EvaluateAsync("window.scrollBy(400, 0)");
|
||||
if (args.Direction == "down")
|
||||
{
|
||||
// Get the total page height
|
||||
int scrollY = await page.EvaluateAsync<int>("document.body.scrollHeight");
|
||||
|
||||
// Scroll to the bottom
|
||||
await page.Mouse.WheelAsync(0, scrollY);
|
||||
}
|
||||
else if (args.Direction == "up")
|
||||
{
|
||||
// Get the total page height
|
||||
int scrollY = await page.EvaluateAsync<int>("document.body.scrollHeight");
|
||||
|
||||
// Scroll to the bottom
|
||||
await page.Mouse.WheelAsync(0, -scrollY);
|
||||
}
|
||||
else if (args.Direction == "left")
|
||||
{
|
||||
await page.EvaluateAsync(@"
|
||||
var scrollingElement = (document.scrollingElement || document.body);
|
||||
scrollingElement.scrollLeft = 0;
|
||||
");
|
||||
}
|
||||
else if (args.Direction == "right")
|
||||
{
|
||||
await page.EvaluateAsync(@"
|
||||
var scrollingElement = (document.scrollingElement || document.body);
|
||||
scrollingElement.scrollLeft = scrollingElement.scrollWidth;
|
||||
");
|
||||
}
|
||||
|
||||
result.IsSuccess = true;
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -2,17 +2,17 @@ namespace BotSharp.Plugin.WebDriver.Drivers.SeleniumDriver;
|
|||
|
||||
public partial class SeleniumWebDriver
|
||||
{
|
||||
public async Task<BrowserActionResult> GoToPage(string contextId, string url, bool openNewTab = false)
|
||||
public async Task<BrowserActionResult> GoToPage(MessageInfo message, PageActionArgs args)
|
||||
{
|
||||
var result = new BrowserActionResult();
|
||||
try
|
||||
{
|
||||
var page = openNewTab ? await _instance.NewPage(contextId) :
|
||||
_instance.GetPage(contextId);
|
||||
page.GoToUrl(url);
|
||||
await _instance.Wait(contextId);
|
||||
var page = args.OpenNewTab ? await _instance.NewPage(message.ContextId) :
|
||||
_instance.GetPage(message.ContextId);
|
||||
page.GoToUrl(args.Url);
|
||||
await _instance.Wait(message.ContextId);
|
||||
|
||||
result.Body = _instance.GetPageContent(contextId);
|
||||
result.Body = _instance.GetPageContent(message.ContextId);
|
||||
result.IsSuccess = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
|
|||
|
|
@ -2,32 +2,13 @@ namespace BotSharp.Plugin.WebDriver.Drivers.SeleniumDriver;
|
|||
|
||||
public partial class SeleniumWebDriver
|
||||
{
|
||||
public async Task<BrowserActionResult> LaunchBrowser(string contextId, string? url)
|
||||
public async Task<BrowserActionResult> LaunchBrowser(MessageInfo message)
|
||||
{
|
||||
var context = await _instance.InitInstance(message.ContextId);
|
||||
var result = new BrowserActionResult()
|
||||
{
|
||||
IsSuccess = true
|
||||
};
|
||||
var context = await _instance.InitInstance(contextId);
|
||||
|
||||
if (!string.IsNullOrEmpty(url))
|
||||
{
|
||||
// Check if the page is already open
|
||||
var page = await _instance.NewPage(contextId);
|
||||
|
||||
try
|
||||
{
|
||||
page.GoToUrl(url);
|
||||
result.IsSuccess = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Message = ex.Message;
|
||||
result.StackTrace = ex.StackTrace;
|
||||
_logger.LogError(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ public partial class SeleniumWebDriver : IWebBrowser
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task CloseCurrentPage(string contextId)
|
||||
public Task<BrowserActionResult> CloseCurrentPage(MessageInfo message)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
@ -72,12 +72,12 @@ public partial class SeleniumWebDriver : IWebBrowser
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<BrowserActionResult> ScreenshotAsync(string contextId, string path)
|
||||
public Task<BrowserActionResult> ScreenshotAsync(MessageInfo message, string path)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<BrowserActionResult> ScrollPageAsync(BrowserActionParams actionParams)
|
||||
public Task<BrowserActionResult> ScrollPage(MessageInfo message, PageActionArgs args)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,12 @@ public class ChangeCheckboxFn : IFunctionCallback
|
|||
var webDriverService = _services.GetRequiredService<WebDriverService>();
|
||||
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
|
||||
|
||||
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
|
||||
message.Data = await _browser.ScreenshotAsync(new MessageInfo
|
||||
{
|
||||
AgentId = message.CurrentAgentId,
|
||||
ContextId = convService.ConversationId,
|
||||
MessageId = message.MessageId
|
||||
}, path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,12 @@ public class ChangeListValueFn : IFunctionCallback
|
|||
var webDriverService = _services.GetRequiredService<WebDriverService>();
|
||||
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
|
||||
|
||||
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
|
||||
message.Data = await _browser.ScreenshotAsync(new MessageInfo
|
||||
{
|
||||
AgentId = message.CurrentAgentId,
|
||||
ContextId = convService.ConversationId,
|
||||
MessageId = message.MessageId
|
||||
}, path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,12 @@ public class CheckRadioButtonFn : IFunctionCallback
|
|||
var webDriverService = _services.GetRequiredService<WebDriverService>();
|
||||
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
|
||||
|
||||
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
|
||||
message.Data = await _browser.ScreenshotAsync(new MessageInfo
|
||||
{
|
||||
AgentId = message.CurrentAgentId,
|
||||
ContextId = convService.ConversationId,
|
||||
MessageId = message.MessageId
|
||||
}, path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,12 @@ public class ClickButtonFn : IFunctionCallback
|
|||
var webDriverService = _services.GetRequiredService<WebDriverService>();
|
||||
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
|
||||
|
||||
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
|
||||
message.Data = await _browser.ScreenshotAsync(new MessageInfo
|
||||
{
|
||||
AgentId = message.CurrentAgentId,
|
||||
ContextId = convService.ConversationId,
|
||||
MessageId = message.MessageId
|
||||
}, path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,12 @@ public class ClickElementFn : IFunctionCallback
|
|||
var webDriverService = _services.GetRequiredService<WebDriverService>();
|
||||
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
|
||||
|
||||
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
|
||||
message.Data = await _browser.ScreenshotAsync(new MessageInfo
|
||||
{
|
||||
AgentId = message.CurrentAgentId,
|
||||
ContextId = convService.ConversationId,
|
||||
MessageId = message.MessageId
|
||||
}, path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,12 @@ public class ExtractDataFn : IFunctionCallback
|
|||
var webDriverService = _services.GetRequiredService<WebDriverService>();
|
||||
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
|
||||
|
||||
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
|
||||
message.Data = await _browser.ScreenshotAsync(new MessageInfo
|
||||
{
|
||||
AgentId = message.CurrentAgentId,
|
||||
ContextId = convService.ConversationId,
|
||||
MessageId = message.MessageId
|
||||
}, path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,12 +26,25 @@ public class GoToPageFn : IFunctionCallback
|
|||
|
||||
url = url.Replace("https://https://", "https://");
|
||||
|
||||
var result = await _browser.GoToPage(convService.ConversationId, url);
|
||||
var result = await _browser.GoToPage(new MessageInfo
|
||||
{
|
||||
AgentId = message.CurrentAgentId,
|
||||
ContextId = convService.ConversationId,
|
||||
MessageId = message.MessageId
|
||||
}, new PageActionArgs
|
||||
{
|
||||
Url = url
|
||||
});
|
||||
message.Content = result.IsSuccess ? $"Page {url} is open." : $"Page {url} open failed. {result.Message}";
|
||||
|
||||
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
|
||||
|
||||
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
|
||||
message.Data = await _browser.ScreenshotAsync(new MessageInfo
|
||||
{
|
||||
AgentId = message.CurrentAgentId,
|
||||
ContextId = convService.ConversationId,
|
||||
MessageId = message.MessageId
|
||||
}, path);
|
||||
|
||||
return result.IsSuccess;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,12 @@ public class InputUserPasswordFn : IFunctionCallback
|
|||
|
||||
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
|
||||
|
||||
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
|
||||
message.Data = await _browser.ScreenshotAsync(new MessageInfo
|
||||
{
|
||||
AgentId = message.CurrentAgentId,
|
||||
ContextId = convService.ConversationId,
|
||||
MessageId = message.MessageId
|
||||
}, path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,12 @@ public class InputUserTextFn : IFunctionCallback
|
|||
var webDriverService = _services.GetRequiredService<WebDriverService>();
|
||||
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
|
||||
|
||||
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
|
||||
message.Data = await _browser.ScreenshotAsync(new MessageInfo
|
||||
{
|
||||
AgentId = message.CurrentAgentId,
|
||||
ContextId = convService.ConversationId,
|
||||
MessageId = message.MessageId
|
||||
}, path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
using SQLitePCL;
|
||||
|
||||
namespace BotSharp.Plugin.WebDriver.Functions;
|
||||
|
||||
public class OpenBrowserFn : IFunctionCallback
|
||||
|
|
@ -23,7 +25,17 @@ public class OpenBrowserFn : IFunctionCallback
|
|||
var url = webDriverService.ReplaceToken(args.Url);
|
||||
|
||||
url = url.Replace("https://https://", "https://");
|
||||
var result = await _browser.LaunchBrowser(convService.ConversationId, url);
|
||||
var msgInfo = new MessageInfo
|
||||
{
|
||||
AgentId = message.CurrentAgentId,
|
||||
ContextId = convService.ConversationId,
|
||||
MessageId = message.MessageId
|
||||
};
|
||||
var result = await _browser.LaunchBrowser(msgInfo);
|
||||
result = await _browser.GoToPage(msgInfo, new PageActionArgs
|
||||
{
|
||||
Url = url
|
||||
});
|
||||
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
|
|
@ -36,7 +48,12 @@ public class OpenBrowserFn : IFunctionCallback
|
|||
|
||||
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
|
||||
|
||||
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
|
||||
message.Data = await _browser.ScreenshotAsync(new MessageInfo
|
||||
{
|
||||
AgentId = message.CurrentAgentId,
|
||||
ContextId = convService.ConversationId,
|
||||
MessageId = message.MessageId
|
||||
}, path);
|
||||
|
||||
return result.IsSuccess;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,12 @@ public class ScreenshotFn : IFunctionCallback
|
|||
var webDriverService = _services.GetRequiredService<WebDriverService>();
|
||||
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
|
||||
|
||||
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
|
||||
message.Data = await _browser.ScreenshotAsync(new MessageInfo
|
||||
{
|
||||
AgentId = message.CurrentAgentId,
|
||||
ContextId = convService.ConversationId,
|
||||
MessageId = message.MessageId
|
||||
}, path);
|
||||
message.Content = "Took screenshot completed. You can take another screenshot if needed.";
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -22,13 +22,28 @@ public class ScrollPageFn : IFunctionCallback
|
|||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var agent = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
|
||||
message.Data = await _browser.ScrollPageAsync(new BrowserActionParams(agent, args, convService.ConversationId, message.MessageId));
|
||||
message.Data = await _browser.ScrollPage(new MessageInfo
|
||||
{
|
||||
AgentId = agent.Id,
|
||||
ContextId = convService.ConversationId,
|
||||
MessageId = message.MessageId
|
||||
}, new PageActionArgs
|
||||
{
|
||||
Action = BroswerActionEnum.Scroll,
|
||||
Direction = args.Direction,
|
||||
});
|
||||
|
||||
message.Content = "Scrolled. You can scroll more if needed.";
|
||||
|
||||
var webDriverService = _services.GetRequiredService<WebDriverService>();
|
||||
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
|
||||
|
||||
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
|
||||
message.Data = await _browser.ScreenshotAsync(new MessageInfo
|
||||
{
|
||||
AgentId = message.CurrentAgentId,
|
||||
ContextId = convService.ConversationId,
|
||||
MessageId = message.MessageId
|
||||
}, path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
44
src/Plugins/BotSharp.Plugin.WebDriver/WebPageHelper.cs
Normal file
44
src/Plugins/BotSharp.Plugin.WebDriver/WebPageHelper.cs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
using HtmlAgilityPack;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace BotSharp.Plugin.WebDriver;
|
||||
|
||||
public static class WebPageHelper
|
||||
{
|
||||
public static string RemoveElements(string html, string selector)
|
||||
{
|
||||
var htmlDoc = new HtmlDocument();
|
||||
htmlDoc.LoadHtml(html);
|
||||
|
||||
var nodesToRemove = htmlDoc.DocumentNode.SelectNodes(selector);
|
||||
|
||||
if (nodesToRemove != null)
|
||||
{
|
||||
foreach (var node in nodesToRemove)
|
||||
{
|
||||
node.Remove();
|
||||
}
|
||||
}
|
||||
|
||||
return htmlDoc.DocumentNode.OuterHtml;
|
||||
}
|
||||
|
||||
public static string RemoveAttribute(string html, string attrName)
|
||||
{
|
||||
var htmlDoc = new HtmlDocument();
|
||||
htmlDoc.LoadHtml(html);
|
||||
|
||||
// Select all elements with a style attribute
|
||||
var nodesWithStyle = htmlDoc.DocumentNode.SelectNodes($"//*[@{attrName}]");
|
||||
|
||||
if (nodesWithStyle != null)
|
||||
{
|
||||
foreach (var node in nodesWithStyle)
|
||||
{
|
||||
node.Attributes.Remove(attrName);
|
||||
}
|
||||
}
|
||||
|
||||
return htmlDoc.DocumentNode.OuterHtml;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue