From dff77f0ffe94e5654bf733c799311ef0830f5c75 Mon Sep 17 00:00:00 2001 From: Ruri Date: Sat, 3 Aug 2024 19:00:13 +0200 Subject: [PATCH 01/19] Added try/catch in ReadNetworkUsage due to a macOS issue Closes #1079 --- .../Services/PerformanceMonitorService.cs | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/OpenBullet2.Web/Services/PerformanceMonitorService.cs b/OpenBullet2.Web/Services/PerformanceMonitorService.cs index 47936714e..25dd4e854 100644 --- a/OpenBullet2.Web/Services/PerformanceMonitorService.cs +++ b/OpenBullet2.Web/Services/PerformanceMonitorService.cs @@ -142,20 +142,27 @@ private static async Task ReadCpuUsageAsync(CancellationToken cancellati private static async Task<(long upload, long download)> ReadNetworkUsage() { - if (!NetworkInterface.GetIsNetworkAvailable()) + try { - return (0, 0); - } - - var interfaces = NetworkInterface.GetAllNetworkInterfaces(); - var startUpload = GetCurrentNetUpload(interfaces); - var startDownload = GetCurrentNetDownload(interfaces); + if (!NetworkInterface.GetIsNetworkAvailable()) + { + return (0, 0); + } + + var interfaces = NetworkInterface.GetAllNetworkInterfaces(); + var startUpload = GetCurrentNetUpload(interfaces); + var startDownload = GetCurrentNetDownload(interfaces); - await Task.Delay(100); + await Task.Delay(100); - var netUpload = GetCurrentNetUpload(interfaces) - startUpload; - var netDownload = GetCurrentNetDownload(interfaces) - startDownload; - return (netUpload * 10, netDownload * 10); + var netUpload = GetCurrentNetUpload(interfaces) - startUpload; + var netDownload = GetCurrentNetDownload(interfaces) - startDownload; + return (netUpload * 10, netDownload * 10); + } + catch + { + return (0, 0); + } } private static long GetCurrentNetUpload(NetworkInterface[] interfaces) From 0d4e3a2f6f80069ac058a54bc85242fc30049cce Mon Sep 17 00:00:00 2001 From: Ruri Date: Sun, 4 Aug 2024 15:27:25 +0200 Subject: [PATCH 02/19] Small cleanup --- .../Repositories/DiskConfigRepository.cs | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/OpenBullet2.Core/Repositories/DiskConfigRepository.cs b/OpenBullet2.Core/Repositories/DiskConfigRepository.cs index 2ebee2bc3..132fc2d15 100644 --- a/OpenBullet2.Core/Repositories/DiskConfigRepository.cs +++ b/OpenBullet2.Core/Repositories/DiskConfigRepository.cs @@ -72,16 +72,17 @@ public async Task GetAsync(string id) { var file = GetFileName(id); - if (File.Exists(file)) + if (!File.Exists(file)) { - using var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read); - - var config = await ConfigPacker.UnpackAsync(fileStream); - config.Id = id; - return config; + throw new FileNotFoundException(); } + + await using var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read); + + var config = await ConfigPacker.UnpackAsync(fileStream); + config.Id = id; + return config; - throw new FileNotFoundException(); } /// @@ -89,16 +90,17 @@ public async Task GetBytesAsync(string id) { var file = GetFileName(id); - if (File.Exists(file)) + if (!File.Exists(file)) { - using FileStream fileStream = new(file, FileMode.Open, FileAccess.Read); - using var ms = new MemoryStream(); - await fileStream.CopyToAsync(ms); - - return ms.ToArray(); + throw new FileNotFoundException(); } + + await using FileStream fileStream = new(file, FileMode.Open, FileAccess.Read); + using var ms = new MemoryStream(); + await fileStream.CopyToAsync(ms); + + return ms.ToArray(); - throw new FileNotFoundException(); } /// @@ -129,7 +131,7 @@ public async Task UploadAsync(Stream stream, string fileName) else if (extension == ".loli") { using var ms = new MemoryStream(); - stream.CopyTo(ms); + await stream.CopyToAsync(ms); ms.Seek(0, SeekOrigin.Begin); var content = Encoding.UTF8.GetString(ms.ToArray()); var id = Path.GetFileNameWithoutExtension(fileName); From abf81204bcc4bf036774fdd14bbb3f8f7534e3bf Mon Sep 17 00:00:00 2001 From: Ruri Date: Sun, 4 Aug 2024 19:42:56 +0200 Subject: [PATCH 03/19] [build] Upgraded CaptchaSharp to 2.0.0 and added new blocks and services Closes #1087 --- .../Converters/BooleanConverter.cs | 60 +- .../ViewModels/RLSettingsViewModel.cs | 824 ++++++++++-------- .../Views/Pages/RLSettings.xaml | 166 +++- .../Views/Pages/RLSettings.xaml.cs | 99 +-- RuriLib/Blocks/Captchas/Methods.cs | 669 +++++++++----- .../Captchas/CaptchaServiceFactory.cs | 99 ++- .../Functions/Captchas/CaptchaServiceType.cs | 141 +-- RuriLib/Legacy/Blocks/BlockSolveCaptcha.cs | 800 +++++++++-------- RuriLib/Legacy/LS/BlockReportCaptcha.cs | 150 ++-- RuriLib/Models/Bots/BotData.cs | 240 ++--- RuriLib/Models/Jobs/MultiRunJob.cs | 3 +- RuriLib/Models/Settings/CaptchaSettings.cs | 79 +- .../Captchas/CaptchaSharpProvider.cs | 176 ++-- .../Providers/Captchas/ICaptchaProvider.cs | 132 ++- RuriLib/RuriLib.csproj | 4 +- .../rl-settings/rl-settings.component.html | 192 +++- .../rl-settings/rl-settings.component.ts | 19 +- .../app/main/dtos/settings/rl-settings.dto.ts | 39 +- 18 files changed, 2379 insertions(+), 1513 deletions(-) diff --git a/OpenBullet2.Native/Converters/BooleanConverter.cs b/OpenBullet2.Native/Converters/BooleanConverter.cs index e20e64f95..33d1073bf 100644 --- a/OpenBullet2.Native/Converters/BooleanConverter.cs +++ b/OpenBullet2.Native/Converters/BooleanConverter.cs @@ -3,53 +3,51 @@ using System.Globalization; using System.Windows; using System.Windows.Data; -using System.Windows.Media; -namespace OpenBullet2.Native.Converters +namespace OpenBullet2.Native.Converters; + +// From https://stackoverflow.com/a/5182660/4332314 +public class BooleanConverter : IValueConverter { - // From https://stackoverflow.com/a/5182660/4332314 - public class BooleanConverter : IValueConverter + public BooleanConverter(T trueValue, T falseValue) { - public BooleanConverter(T trueValue, T falseValue) - { - True = trueValue; - False = falseValue; - } + True = trueValue; + False = falseValue; + } - public T True { get; set; } - public T False { get; set; } + public T True { get; set; } + public T False { get; set; } - public virtual object Convert(object value, Type targetType, object parameter, CultureInfo culture) - => value is bool b && b ? True : False; + public virtual object Convert(object value, Type targetType, object parameter, CultureInfo culture) + => value is bool b && b ? True : False; - public virtual object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - => value is T convertedValue && EqualityComparer.Default.Equals(convertedValue, True); - } + public virtual object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + => value is T convertedValue && EqualityComparer.Default.Equals(convertedValue, True); +} - public sealed class BoolToVisibilityConverter : BooleanConverter +public sealed class BoolToVisibilityConverter : BooleanConverter +{ + public BoolToVisibilityConverter() : + base(Visibility.Visible, Visibility.Collapsed) { - public BoolToVisibilityConverter() : - base(Visibility.Visible, Visibility.Collapsed) - { - } } +} - public sealed class BoolToThicknessConverter : BooleanConverter +public sealed class BoolToThicknessConverter : BooleanConverter +{ + public BoolToThicknessConverter() : + base(new Thickness(1), new Thickness(0)) { - public BoolToThicknessConverter() : - base(new Thickness(1), new Thickness(0)) - { - } } +} - public sealed class BoolToTextWrappingConverter : BooleanConverter +public sealed class BoolToTextWrappingConverter : BooleanConverter +{ + public BoolToTextWrappingConverter() : + base(TextWrapping.Wrap, TextWrapping.NoWrap) { - public BoolToTextWrappingConverter() : - base(TextWrapping.Wrap, TextWrapping.NoWrap) - { - } } } diff --git a/OpenBullet2.Native/ViewModels/RLSettingsViewModel.cs b/OpenBullet2.Native/ViewModels/RLSettingsViewModel.cs index 75887e3d6..e473c8a14 100644 --- a/OpenBullet2.Native/ViewModels/RLSettingsViewModel.cs +++ b/OpenBullet2.Native/ViewModels/RLSettingsViewModel.cs @@ -7,504 +7,618 @@ using System.Linq; using System.Threading.Tasks; -namespace OpenBullet2.Native.ViewModels -{ - public class RLSettingsViewModel : ViewModelBase - { - private RuriLibSettingsService service; - private GeneralSettings General => service.RuriLibSettings.GeneralSettings; - private ProxySettings Proxy => service.RuriLibSettings.ProxySettings; - private CaptchaSettings Captcha => service.RuriLibSettings.CaptchaSettings; - private PuppeteerSettings Puppeteer => service.RuriLibSettings.PuppeteerSettings; - private SeleniumSettings Selenium => service.RuriLibSettings.SeleniumSettings; +namespace OpenBullet2.Native.ViewModels; - public event Action CaptchaServiceChanged; +public class RLSettingsViewModel : ViewModelBase +{ + private readonly RuriLibSettingsService _service = SP.GetService(); + private GeneralSettings General => _service.RuriLibSettings.GeneralSettings; + private ProxySettings Proxy => _service.RuriLibSettings.ProxySettings; + private CaptchaSettings Captcha => _service.RuriLibSettings.CaptchaSettings; + private PuppeteerSettings Puppeteer => _service.RuriLibSettings.PuppeteerSettings; + private SeleniumSettings Selenium => _service.RuriLibSettings.SeleniumSettings; - public RLSettingsViewModel() - { - service = SP.GetService(); - } + public event Action CaptchaServiceChanged; - public IEnumerable ParallelizerTypes => Enum.GetValues(typeof(ParallelizerType)).Cast(); + public IEnumerable ParallelizerTypes => Enum.GetValues(typeof(ParallelizerType)).Cast(); - public ParallelizerType ParallelizerType + public ParallelizerType ParallelizerType + { + get => General.ParallelizerType; + set { - get => General.ParallelizerType; - set - { - General.ParallelizerType = value; - OnPropertyChanged(); - } + General.ParallelizerType = value; + OnPropertyChanged(); } + } - public bool LogJobActivityToFile + public bool LogJobActivityToFile + { + get => General.LogJobActivityToFile; + set { - get => General.LogJobActivityToFile; - set - { - General.LogJobActivityToFile = value; - OnPropertyChanged(); - } + General.LogJobActivityToFile = value; + OnPropertyChanged(); } + } - public bool LogAllResults + public bool LogAllResults + { + get => General.LogAllResults; + set { - get => General.LogAllResults; - set - { - General.LogAllResults = value; - OnPropertyChanged(); - } + General.LogAllResults = value; + OnPropertyChanged(); } + } - public bool EnableBotLogging + public bool EnableBotLogging + { + get => General.EnableBotLogging; + set { - get => General.EnableBotLogging; - set - { - General.EnableBotLogging = value; - OnPropertyChanged(); - } + General.EnableBotLogging = value; + OnPropertyChanged(); } + } - public bool VerboseMode + public bool VerboseMode + { + get => General.VerboseMode; + set { - get => General.VerboseMode; - set - { - General.VerboseMode = value; - OnPropertyChanged(); - } + General.VerboseMode = value; + OnPropertyChanged(); } + } - public bool RestrictBlocksToCWD + public bool RestrictBlocksToCWD + { + get => General.RestrictBlocksToCWD; + set { - get => General.RestrictBlocksToCWD; - set - { - General.RestrictBlocksToCWD = value; - OnPropertyChanged(); - } + General.RestrictBlocksToCWD = value; + OnPropertyChanged(); } + } - public bool UseCustomUserAgentsList + public bool UseCustomUserAgentsList + { + get => General.UseCustomUserAgentsList; + set { - get => General.UseCustomUserAgentsList; - set - { - General.UseCustomUserAgentsList = value; - OnPropertyChanged(); - } + General.UseCustomUserAgentsList = value; + OnPropertyChanged(); } + } - public List UserAgents + public List UserAgents + { + get => General.UserAgents; + set { - get => General.UserAgents; - set - { - General.UserAgents = value; - OnPropertyChanged(); - } + General.UserAgents = value; + OnPropertyChanged(); } + } - public int ProxyConnectTimeoutMilliseconds + public int ProxyConnectTimeoutMilliseconds + { + get => Proxy.ProxyConnectTimeoutMilliseconds; + set { - get => Proxy.ProxyConnectTimeoutMilliseconds; - set - { - Proxy.ProxyConnectTimeoutMilliseconds = value; - OnPropertyChanged(); - } + Proxy.ProxyConnectTimeoutMilliseconds = value; + OnPropertyChanged(); } + } - public int ProxyReadWriteTimeoutMilliseconds + public int ProxyReadWriteTimeoutMilliseconds + { + get => Proxy.ProxyReadWriteTimeoutMilliseconds; + set { - get => Proxy.ProxyReadWriteTimeoutMilliseconds; - set - { - Proxy.ProxyReadWriteTimeoutMilliseconds = value; - OnPropertyChanged(); - } + Proxy.ProxyReadWriteTimeoutMilliseconds = value; + OnPropertyChanged(); } + } - public List GlobalBanKeys + public List GlobalBanKeys + { + get => Proxy.GlobalBanKeys; + set { - get => Proxy.GlobalBanKeys; - set - { - Proxy.GlobalBanKeys = value; - OnPropertyChanged(); - } + Proxy.GlobalBanKeys = value; + OnPropertyChanged(); } + } - public List GlobalRetryKeys + public List GlobalRetryKeys + { + get => Proxy.GlobalRetryKeys; + set { - get => Proxy.GlobalRetryKeys; - set - { - Proxy.GlobalRetryKeys = value; - OnPropertyChanged(); - } + Proxy.GlobalRetryKeys = value; + OnPropertyChanged(); } + } - public int CaptchaTimeoutSeconds + public int CaptchaTimeoutSeconds + { + get => Captcha.TimeoutSeconds; + set { - get => Captcha.TimeoutSeconds; - set - { - Captcha.TimeoutSeconds = value; - OnPropertyChanged(); - } + Captcha.TimeoutSeconds = value; + OnPropertyChanged(); } + } - public int CaptchaPollingIntervalMilliseconds + public int CaptchaPollingIntervalMilliseconds + { + get => Captcha.PollingIntervalMilliseconds; + set { - get => Captcha.PollingIntervalMilliseconds; - set - { - Captcha.PollingIntervalMilliseconds = value; - OnPropertyChanged(); - } + Captcha.PollingIntervalMilliseconds = value; + OnPropertyChanged(); } + } - public bool CheckBalanceBeforeSolving + public bool CheckBalanceBeforeSolving + { + get => Captcha.CheckBalanceBeforeSolving; + set { - get => Captcha.CheckBalanceBeforeSolving; - set - { - Captcha.CheckBalanceBeforeSolving = value; - OnPropertyChanged(); - } + Captcha.CheckBalanceBeforeSolving = value; + OnPropertyChanged(); } + } - public IEnumerable CaptchaServiceTypes => Enum.GetValues(typeof(CaptchaServiceType)).Cast(); + public IEnumerable CaptchaServiceTypes => Enum.GetValues(typeof(CaptchaServiceType)).Cast(); - public CaptchaServiceType CurrentCaptchaService + public CaptchaServiceType CurrentCaptchaService + { + get => Captcha.CurrentService; + set { - get => Captcha.CurrentService; - set - { - Captcha.CurrentService = value; - OnPropertyChanged(); - CaptchaServiceChanged?.Invoke(value); - } + Captcha.CurrentService = value; + OnPropertyChanged(); + CaptchaServiceChanged?.Invoke(value); } + } - public string AntiCaptchaApiKey + public string AntiCaptchaApiKey + { + get => Captcha.AntiCaptchaApiKey; + set { - get => Captcha.AntiCaptchaApiKey; - set - { - Captcha.AntiCaptchaApiKey = value; - OnPropertyChanged(); - } + Captcha.AntiCaptchaApiKey = value; + OnPropertyChanged(); } + } - public string AZCaptchaApiKey + public string AzCaptchaApiKey + { + get => Captcha.AZCaptchaApiKey; + set { - get => Captcha.AZCaptchaApiKey; - set - { - Captcha.AZCaptchaApiKey = value; - OnPropertyChanged(); - } + Captcha.AZCaptchaApiKey = value; + OnPropertyChanged(); } + } - public string CapMonsterHost + public string CapMonsterHost + { + get => Captcha.CapMonsterHost; + set { - get => Captcha.CapMonsterHost; - set - { - Captcha.CapMonsterHost = value; - OnPropertyChanged(); - } + Captcha.CapMonsterHost = value; + OnPropertyChanged(); } + } - public int CapMonsterPort + public int CapMonsterPort + { + get => Captcha.CapMonsterPort; + set { - get => Captcha.CapMonsterPort; - set - { - Captcha.CapMonsterPort = value; - OnPropertyChanged(); - } + Captcha.CapMonsterPort = value; + OnPropertyChanged(); } + } - public string CaptchasDotIoApiKey + public string CaptchasDotIoApiKey + { + get => Captcha.CaptchasDotIoApiKey; + set { - get => Captcha.CaptchasDotIoApiKey; - set - { - Captcha.CaptchasDotIoApiKey = value; - OnPropertyChanged(); - } + Captcha.CaptchasDotIoApiKey = value; + OnPropertyChanged(); } + } - public string CustomTwoCaptchaApiKey + public string CustomTwoCaptchaApiKey + { + get => Captcha.CustomTwoCaptchaApiKey; + set { - get => Captcha.CustomTwoCaptchaApiKey; - set - { - Captcha.CustomTwoCaptchaApiKey = value; - OnPropertyChanged(); - } + Captcha.CustomTwoCaptchaApiKey = value; + OnPropertyChanged(); } + } - public string CustomTwoCaptchaDomain + public string CustomTwoCaptchaDomain + { + get => Captcha.CustomTwoCaptchaDomain; + set { - get => Captcha.CustomTwoCaptchaDomain; - set - { - Captcha.CustomTwoCaptchaDomain = value; - OnPropertyChanged(); - } + Captcha.CustomTwoCaptchaDomain = value; + OnPropertyChanged(); } + } - public int CustomTwoCaptchaPort + public int CustomTwoCaptchaPort + { + get => Captcha.CustomTwoCaptchaPort; + set { - get => Captcha.CustomTwoCaptchaPort; - set - { - Captcha.CustomTwoCaptchaPort = value; - OnPropertyChanged(); - } + Captcha.CustomTwoCaptchaPort = value; + OnPropertyChanged(); } + } - public bool CustomTwoCaptchaOverrideHostHeader + public bool CustomTwoCaptchaOverrideHostHeader + { + get => Captcha.CustomTwoCaptchaOverrideHostHeader; + set { - get => Captcha.CustomTwoCaptchaOverrideHostHeader; - set - { - Captcha.CustomTwoCaptchaOverrideHostHeader = value; - OnPropertyChanged(); - } + Captcha.CustomTwoCaptchaOverrideHostHeader = value; + OnPropertyChanged(); } + } - public string DeathByCaptchaUsername + public string DeathByCaptchaUsername + { + get => Captcha.DeathByCaptchaUsername; + set { - get => Captcha.DeathByCaptchaUsername; - set - { - Captcha.DeathByCaptchaUsername = value; - OnPropertyChanged(); - } + Captcha.DeathByCaptchaUsername = value; + OnPropertyChanged(); } + } - public string DeathByCaptchaPassword + public string DeathByCaptchaPassword + { + get => Captcha.DeathByCaptchaPassword; + set { - get => Captcha.DeathByCaptchaPassword; - set - { - Captcha.DeathByCaptchaPassword = value; - OnPropertyChanged(); - } + Captcha.DeathByCaptchaPassword = value; + OnPropertyChanged(); } - - public string DeCaptcherUsername + } + + public string CaptchaCoderApiKey + { + get => Captcha.CaptchaCoderApiKey; + set { - get => Captcha.DeCaptcherUsername; - set - { - Captcha.DeCaptcherUsername = value; - OnPropertyChanged(); - } + Captcha.CaptchaCoderApiKey = value; + OnPropertyChanged(); } - - public string DeCaptcherPassword + } + + public string HumanCoderApiKey + { + get => Captcha.HumanCoderApiKey; + set { - get => Captcha.DeCaptcherPassword; - set - { - Captcha.DeCaptcherPassword = value; - OnPropertyChanged(); - } + Captcha.HumanCoderApiKey = value; + OnPropertyChanged(); } + } - public string ImageTyperzApiKey + public string ImageTyperzApiKey + { + get => Captcha.ImageTyperzApiKey; + set { - get => Captcha.ImageTyperzApiKey; - set - { - Captcha.ImageTyperzApiKey = value; - OnPropertyChanged(); - } + Captcha.ImageTyperzApiKey = value; + OnPropertyChanged(); } + } - public string RuCaptchaApiKey + public string RuCaptchaApiKey + { + get => Captcha.RuCaptchaApiKey; + set { - get => Captcha.RuCaptchaApiKey; - set - { - Captcha.RuCaptchaApiKey = value; - OnPropertyChanged(); - } + Captcha.RuCaptchaApiKey = value; + OnPropertyChanged(); } + } - public string SolveCaptchaApiKey + public string SolveCaptchaApiKey + { + get => Captcha.SolveCaptchaApiKey; + set { - get => Captcha.SolveCaptchaApiKey; - set - { - Captcha.SolveCaptchaApiKey = value; - OnPropertyChanged(); - } + Captcha.SolveCaptchaApiKey = value; + OnPropertyChanged(); } + } - public string SolveRecaptchaApiKey + public string TrueCaptchaApiKey + { + get => Captcha.TrueCaptchaApiKey; + set { - get => Captcha.SolveRecaptchaApiKey; - set - { - Captcha.SolveRecaptchaApiKey = value; - OnPropertyChanged(); - } + Captcha.TrueCaptchaApiKey = value; + OnPropertyChanged(); } + } - public string TrueCaptchaApiKey + public string TrueCaptchaUsername + { + get => Captcha.TrueCaptchaUsername; + set { - get => Captcha.TrueCaptchaApiKey; - set - { - Captcha.TrueCaptchaApiKey = value; - OnPropertyChanged(); - } + Captcha.TrueCaptchaUsername = value; + OnPropertyChanged(); } + } - public string TrueCaptchaUsername + public string TwoCaptchaApiKey + { + get => Captcha.TwoCaptchaApiKey; + set { - get => Captcha.TrueCaptchaUsername; - set - { - Captcha.TrueCaptchaUsername = value; - OnPropertyChanged(); - } + Captcha.TwoCaptchaApiKey = value; + OnPropertyChanged(); } + } - public string TwoCaptchaApiKey + public string NineKwApiKey + { + get => Captcha.NineKWApiKey; + set { - get => Captcha.TwoCaptchaApiKey; - set - { - Captcha.TwoCaptchaApiKey = value; - OnPropertyChanged(); - } + Captcha.NineKWApiKey = value; + OnPropertyChanged(); } + } - public string NineKWApiKey + public string CustomAntiCaptchaApiKey + { + get => Captcha.CustomAntiCaptchaApiKey; + set { - get => Captcha.NineKWApiKey; - set - { - Captcha.NineKWApiKey = value; - OnPropertyChanged(); - } + Captcha.CustomAntiCaptchaApiKey = value; + OnPropertyChanged(); } + } - public string CustomAntiCaptchaApiKey + public string CustomAntiCaptchaDomain + { + get => Captcha.CustomAntiCaptchaDomain; + set { - get => Captcha.CustomAntiCaptchaApiKey; - set - { - Captcha.CustomAntiCaptchaApiKey = value; - OnPropertyChanged(); - } + Captcha.CustomAntiCaptchaDomain = value; + OnPropertyChanged(); } + } - public string CustomAntiCaptchaDomain + public int CustomAntiCaptchaPort + { + get => Captcha.CustomAntiCaptchaPort; + set { - get => Captcha.CustomAntiCaptchaDomain; - set - { - Captcha.CustomAntiCaptchaDomain = value; - OnPropertyChanged(); - } + Captcha.CustomAntiCaptchaPort = value; + OnPropertyChanged(); } + } - public int CustomAntiCaptchaPort + public string CapSolverApiKey + { + get => Captcha.CapSolverApiKey; + set { - get => Captcha.CustomAntiCaptchaPort; - set - { - Captcha.CustomAntiCaptchaPort = value; - OnPropertyChanged(); - } + Captcha.CapSolverApiKey = value; + OnPropertyChanged(); } - - public string AnyCaptchaApiKey + } + + public string CapMonsterCloudApiKey + { + get => Captcha.CapMonsterCloudApiKey; + set { - get => Captcha.AnyCaptchaApiKey; - set - { - Captcha.AnyCaptchaApiKey = value; - OnPropertyChanged(); - } + Captcha.CapMonsterCloudApiKey = value; + OnPropertyChanged(); } - - public string CapSolverApiKey + } + + public string MetaBypassTechClientId + { + get => Captcha.MetaBypassTechClientId; + set + { + Captcha.MetaBypassTechClientId = value; + OnPropertyChanged(); + } + } + + public string MetaBypassTechClientSecret + { + get => Captcha.MetaBypassTechClientSecret; + set + { + Captcha.MetaBypassTechClientSecret = value; + OnPropertyChanged(); + } + } + + public string MetaBypassTechUsername + { + get => Captcha.MetaBypassTechUsername; + set + { + Captcha.MetaBypassTechUsername = value; + OnPropertyChanged(); + } + } + + public string MetaBypassTechPassword + { + get => Captcha.MetaBypassTechPassword; + set + { + Captcha.MetaBypassTechPassword = value; + OnPropertyChanged(); + } + } + + public string NextCaptchaApiKey + { + get => Captcha.NextCaptchaApiKey; + set + { + Captcha.NextCaptchaApiKey = value; + OnPropertyChanged(); + } + } + + public string NoCaptchaAiApiKey + { + get => Captcha.NoCaptchaAiApiKey; + set + { + Captcha.NoCaptchaAiApiKey = value; + OnPropertyChanged(); + } + } + + public string NopechaApiKey + { + get => Captcha.NopechaApiKey; + set { - get => Captcha.CapSolverApiKey; - set - { - Captcha.CapSolverApiKey = value; - OnPropertyChanged(); - } + Captcha.NopechaApiKey = value; + OnPropertyChanged(); } + } + + public string BestCaptchaSolverApiKey + { + get => Captcha.BestCaptchaSolverApiKey; + set + { + Captcha.BestCaptchaSolverApiKey = value; + OnPropertyChanged(); + } + } + + public string CaptchaAiApiKey + { + get => Captcha.CaptchaAiApiKey; + set + { + Captcha.CaptchaAiApiKey = value; + OnPropertyChanged(); + } + } + + public string EzCaptchaApiKey + { + get => Captcha.EzCaptchaApiKey; + set + { + Captcha.EzCaptchaApiKey = value; + OnPropertyChanged(); + } + } + + public string EndCaptchaUsername + { + get => Captcha.EndCaptchaUsername; + set + { + Captcha.EndCaptchaUsername = value; + OnPropertyChanged(); + } + } + + public string EndCaptchaPassword + { + get => Captcha.EndCaptchaPassword; + set + { + Captcha.EndCaptchaPassword = value; + OnPropertyChanged(); + } + } + + public string CapGuruApiKey + { + get => Captcha.CapGuruApiKey; + set + { + Captcha.CapGuruApiKey = value; + OnPropertyChanged(); + } + } - public string PuppeteerChromeBinaryLocation + public string PuppeteerChromeBinaryLocation + { + get => Puppeteer.ChromeBinaryLocation; + set { - get => Puppeteer.ChromeBinaryLocation; - set - { - Puppeteer.ChromeBinaryLocation = value; - OnPropertyChanged(); - } + Puppeteer.ChromeBinaryLocation = value; + OnPropertyChanged(); } + } - public IEnumerable SeleniumBrowserTypes => Enum.GetValues(typeof(SeleniumBrowserType)).Cast(); + public IEnumerable SeleniumBrowserTypes => Enum.GetValues(typeof(SeleniumBrowserType)).Cast(); - public SeleniumBrowserType SeleniumBrowserType + public SeleniumBrowserType SeleniumBrowserType + { + get => Selenium.BrowserType; + set { - get => Selenium.BrowserType; - set - { - Selenium.BrowserType = value; - OnPropertyChanged(); - } + Selenium.BrowserType = value; + OnPropertyChanged(); } + } - public string SeleniumChromeBinaryLocation + public string SeleniumChromeBinaryLocation + { + get => Selenium.ChromeBinaryLocation; + set { - get => Selenium.ChromeBinaryLocation; - set - { - Selenium.ChromeBinaryLocation = value; - OnPropertyChanged(); - } + Selenium.ChromeBinaryLocation = value; + OnPropertyChanged(); } + } - public string SeleniumFirefoxBinaryLocation + public string SeleniumFirefoxBinaryLocation + { + get => Selenium.FirefoxBinaryLocation; + set { - get => Selenium.FirefoxBinaryLocation; - set - { - Selenium.FirefoxBinaryLocation = value; - OnPropertyChanged(); - } + Selenium.FirefoxBinaryLocation = value; + OnPropertyChanged(); } + } - public Task CheckCaptchaBalance() => CaptchaServiceFactory.GetService(Captcha).GetBalanceAsync(); + public Task CheckCaptchaBalance() => CaptchaServiceFactory.GetService(Captcha).GetBalanceAsync(); - public Task Save() => service.Save(); + public Task Save() => _service.Save(); - public void Reset() - { - service.RuriLibSettings = new GlobalSettings(); + public void Reset() + { + _service.RuriLibSettings = new GlobalSettings(); - // Call OnPropertyChanged on all public properties - foreach (var property in GetType().GetProperties()) - { - OnPropertyChanged(property.Name); - } + // Call OnPropertyChanged on all public properties + foreach (var property in GetType().GetProperties()) + { + OnPropertyChanged(property.Name); } } } diff --git a/OpenBullet2.Native/Views/Pages/RLSettings.xaml b/OpenBullet2.Native/Views/Pages/RLSettings.xaml index 2daff4491..812aa97a0 100644 --- a/OpenBullet2.Native/Views/Pages/RLSettings.xaml +++ b/OpenBullet2.Native/Views/Pages/RLSettings.xaml @@ -208,17 +208,12 @@ - + - - - - - - Api Key + @@ -255,11 +250,11 @@ - + - @@ -291,15 +286,6 @@ - - - - - - - - @@ -321,7 +307,7 @@ - @@ -352,23 +338,153 @@ - + - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OpenBullet2.Native/Views/Pages/RLSettings.xaml.cs b/OpenBullet2.Native/Views/Pages/RLSettings.xaml.cs index 00fcf9ba7..dbd25ec7e 100644 --- a/OpenBullet2.Native/Views/Pages/RLSettings.xaml.cs +++ b/OpenBullet2.Native/Views/Pages/RLSettings.xaml.cs @@ -1,5 +1,4 @@ -using OpenBullet2.Native.Extensions; -using OpenBullet2.Native.Helpers; +using OpenBullet2.Native.Helpers; using OpenBullet2.Native.Services; using OpenBullet2.Native.ViewModels; using RuriLib.Functions.Captchas; @@ -7,71 +6,69 @@ using System.Linq; using System.Windows; using System.Windows.Controls; -using System.Windows.Media; -namespace OpenBullet2.Native.Views.Pages +namespace OpenBullet2.Native.Views.Pages; + +/// +/// Interaction logic for RLSettings.xaml +/// +public partial class RLSettings : Page { - /// - /// Interaction logic for RLSettings.xaml - /// - public partial class RLSettings : Page + private readonly RLSettingsViewModel vm; + + public RLSettings() { - private readonly RLSettingsViewModel vm; + vm = SP.GetService().RLSettings; + vm.CaptchaServiceChanged += UpdateCaptchaTabControl; + DataContext = vm; - public RLSettings() - { - vm = SP.GetService().RLSettings; - vm.CaptchaServiceChanged += UpdateCaptchaTabControl; - DataContext = vm; + InitializeComponent(); - InitializeComponent(); + UpdateCaptchaTabControl(vm.CurrentCaptchaService); + SetMultiLineTextBoxContents(); + } - UpdateCaptchaTabControl(vm.CurrentCaptchaService); - SetMultiLineTextBoxContents(); - } + private void CustomUserAgentsChanged(object sender, TextChangedEventArgs e) + => vm.UserAgents = customUserAgentsListTextBox.Text.Split(Environment.NewLine).ToList(); - private void CustomUserAgentsChanged(object sender, TextChangedEventArgs e) - => vm.UserAgents = customUserAgentsListTextBox.Text.Split(Environment.NewLine).ToList(); + private void GlobalBanKeysChanged(object sender, TextChangedEventArgs e) + => vm.GlobalBanKeys = globalBanKeysTextBox.Text.Split(Environment.NewLine).ToList(); - private void GlobalBanKeysChanged(object sender, TextChangedEventArgs e) - => vm.GlobalBanKeys = globalBanKeysTextBox.Text.Split(Environment.NewLine).ToList(); + private void GlobalRetryKeysChanged(object sender, TextChangedEventArgs e) + => vm.GlobalRetryKeys = globalRetryKeysTextBox.Text.Split(Environment.NewLine).ToList(); - private void GlobalRetryKeysChanged(object sender, TextChangedEventArgs e) - => vm.GlobalRetryKeys = globalRetryKeysTextBox.Text.Split(Environment.NewLine).ToList(); + private async void Save(object sender, RoutedEventArgs e) => await vm.Save(); - private async void Save(object sender, RoutedEventArgs e) => await vm.Save(); + private void Reset(object sender, RoutedEventArgs e) + { + vm.Reset(); + SetMultiLineTextBoxContents(); + } - private void Reset(object sender, RoutedEventArgs e) + private async void CheckCaptchaBalance(object sender, RoutedEventArgs e) + { + try { - vm.Reset(); - SetMultiLineTextBoxContents(); + var balance = await vm.CheckCaptchaBalance(); + Alert.Success("Success", $"Balance: {balance}"); } - - private async void CheckCaptchaBalance(object sender, RoutedEventArgs e) + catch (Exception ex) { - try - { - var balance = await vm.CheckCaptchaBalance(); - Alert.Success("Success", $"Balance: {balance}"); - } - catch (Exception ex) - { - Alert.Exception(ex); - } + Alert.Exception(ex); } + } - private void UpdateCaptchaTabControl(CaptchaServiceType service) - { - var values = Enum.GetValues(typeof(CaptchaServiceType)).Cast().ToList(); - var index = values.IndexOf(service); - captchaServiceTabControl.SelectedIndex = index; - } + private void UpdateCaptchaTabControl(CaptchaServiceType service) + { + var values = Enum.GetValues(typeof(CaptchaServiceType)).Cast().ToList(); + var index = values.IndexOf(service); + captchaServiceTabControl.SelectedIndex = index; + } - private void SetMultiLineTextBoxContents() - { - customUserAgentsListTextBox.Text = string.Join(Environment.NewLine, vm.UserAgents); - globalBanKeysTextBox.Text = string.Join(Environment.NewLine, vm.GlobalBanKeys); - globalRetryKeysTextBox.Text = string.Join(Environment.NewLine, vm.GlobalRetryKeys); - } + private void SetMultiLineTextBoxContents() + { + customUserAgentsListTextBox.Text = string.Join(Environment.NewLine, vm.UserAgents); + globalBanKeysTextBox.Text = string.Join(Environment.NewLine, vm.GlobalBanKeys); + globalRetryKeysTextBox.Text = string.Join(Environment.NewLine, vm.GlobalRetryKeys); } } diff --git a/RuriLib/Blocks/Captchas/Methods.cs b/RuriLib/Blocks/Captchas/Methods.cs index edca24283..967f90406 100644 --- a/RuriLib/Blocks/Captchas/Methods.cs +++ b/RuriLib/Blocks/Captchas/Methods.cs @@ -6,249 +6,508 @@ using RuriLib.Models.Captchas; using System; using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; +using CaptchaSharp.Models.CaptchaOptions; -namespace RuriLib.Blocks.Captchas +namespace RuriLib.Blocks.Captchas; + +[BlockCategory("Captchas", "Blocks for solving captchas", "#7df9ff")] +public static class Methods { - [BlockCategory("Captchas", "Blocks for solving captchas", "#7df9ff")] - public static class Methods - { - [Block("Solves a text captcha")] - public static async Task SolveTextCaptcha(BotData data, - [BlockParam("Question", "The description of the captcha to solve, e.g. What is 2+2?")] string question, - CaptchaLanguageGroup languageGroup = CaptchaLanguageGroup.NotSpecified, - CaptchaLanguage language = CaptchaLanguage.NotSpecified) - { - data.Logger.LogHeader(); - await CheckBalance(data).ConfigureAwait(false); - - var response = await data.Providers.Captcha.SolveTextCaptchaAsync(question, - new TextCaptchaOptions - { - CaptchaLanguage = language, - CaptchaLanguageGroup = languageGroup - }, data.CancellationToken).ConfigureAwait(false); - - AddCaptchaId(data, response.IdString, CaptchaType.TextCaptcha); - data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); - return response.Response; - } + [Block("Solves a text captcha")] + public static async Task SolveTextCaptcha(BotData data, + [BlockParam("Question", "The description of the captcha to solve, e.g. What is 2+2?")] string question, + CaptchaLanguageGroup languageGroup = CaptchaLanguageGroup.NotSpecified, + CaptchaLanguage language = CaptchaLanguage.NotSpecified) + { + data.Logger.LogHeader(); + await CheckBalanceAsync(data).ConfigureAwait(false); + + var response = await data.Providers.Captcha.SolveTextCaptchaAsync(question, + new TextCaptchaOptions + { + CaptchaLanguage = language, + CaptchaLanguageGroup = languageGroup + }, data.CancellationToken).ConfigureAwait(false); + + AddCaptchaId(data, response.Id, CaptchaType.TextCaptcha); + data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); + return response.Response; + } - [Block("Solves an image captcha")] - public static async Task SolveImageCaptcha(BotData data, string base64, - CaptchaLanguageGroup languageGroup = CaptchaLanguageGroup.NotSpecified, - CaptchaLanguage language = CaptchaLanguage.NotSpecified, bool isPhrase = false, bool caseSensitive = true, - bool requiresCalculation = false, CharacterSet characterSet = CharacterSet.NotSpecified, - int minLength = 0, int maxLength = 0, string textInstructions = "") - { - data.Logger.LogHeader(); - await CheckBalance(data).ConfigureAwait(false); - - var response = await data.Providers.Captcha.SolveImageCaptchaAsync(base64, - new ImageCaptchaOptions - { - CaptchaLanguage = language, - CaptchaLanguageGroup = languageGroup, - IsPhrase = isPhrase, - CaseSensitive = caseSensitive, - RequiresCalculation = requiresCalculation, - CharacterSet = characterSet, - MinLength = minLength, - MaxLength = maxLength, - TextInstructions = textInstructions - }, data.CancellationToken).ConfigureAwait(false); - - AddCaptchaId(data, response.IdString, CaptchaType.ImageCaptcha); - data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); - return response.Response; - } + [Block("Solves an image captcha")] + public static async Task SolveImageCaptcha(BotData data, string base64, + CaptchaLanguageGroup languageGroup = CaptchaLanguageGroup.NotSpecified, + CaptchaLanguage language = CaptchaLanguage.NotSpecified, bool isPhrase = false, bool caseSensitive = true, + bool requiresCalculation = false, CharacterSet characterSet = CharacterSet.NotSpecified, + int minLength = 0, int maxLength = 0, string textInstructions = "") + { + data.Logger.LogHeader(); + await CheckBalanceAsync(data).ConfigureAwait(false); - [Block("Solves a ReCaptcha V2")] - public static async Task SolveRecaptchaV2(BotData data, string siteKey, string siteUrl, - string sData = "", bool enterprise = false, bool isInvisible = false, bool useProxy = false, - string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36") - { - data.Logger.LogHeader(); - await CheckBalance(data).ConfigureAwait(false); + var response = await data.Providers.Captcha.SolveImageCaptchaAsync(base64, + new ImageCaptchaOptions + { + CaptchaLanguage = language, + CaptchaLanguageGroup = languageGroup, + IsPhrase = isPhrase, + CaseSensitive = caseSensitive, + RequiresCalculation = requiresCalculation, + CharacterSet = characterSet, + MinLength = minLength, + MaxLength = maxLength, + TextInstructions = textInstructions + }, data.CancellationToken).ConfigureAwait(false); + + AddCaptchaId(data, response.Id, CaptchaType.ImageCaptcha); + data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); + return response.Response; + } - var response = await data.Providers.Captcha.SolveRecaptchaV2Async(siteKey, siteUrl, sData, enterprise, isInvisible, - SetupProxy(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); + [Block("Solves a ReCaptcha v2")] + public static async Task SolveRecaptchaV2(BotData data, string siteKey, string siteUrl, + string sData = "", bool enterprise = false, bool isInvisible = false, bool useProxy = false, + string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36") + { + data.Logger.LogHeader(); + await CheckBalanceAsync(data).ConfigureAwait(false); - AddCaptchaId(data, response.IdString, CaptchaType.ReCaptchaV2); - data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); - return response.Response; - } + var response = await data.Providers.Captcha.SolveRecaptchaV2Async(siteKey, siteUrl, sData, enterprise, isInvisible, + CreateSessionParams(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); - // For backwards compatibility - public static Task SolveRecaptchaV2(BotData data, string siteKey, string siteUrl, bool isInvisible = false, bool useProxy = false, - string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36") - => SolveRecaptchaV2(data, siteKey, siteUrl, "", false, isInvisible, useProxy, userAgent); + AddCaptchaId(data, response.Id, CaptchaType.ReCaptchaV2); + data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); + return response.Response; + } - [Block("Solves a ReCaptcha V3")] - public static async Task SolveRecaptchaV3(BotData data, string siteKey, string siteUrl, string action, - float minScore = 0.3F, bool enterprise = false, bool useProxy = false, - string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36") - { - data.Logger.LogHeader(); - await CheckBalance(data).ConfigureAwait(false); + // For backwards compatibility + public static Task SolveRecaptchaV2(BotData data, string siteKey, string siteUrl, bool isInvisible = false, bool useProxy = false, + string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36") + => SolveRecaptchaV2(data, siteKey, siteUrl, "", false, isInvisible, useProxy, userAgent); - var response = await data.Providers.Captcha.SolveRecaptchaV3Async(siteKey, siteUrl, action, minScore, enterprise, - SetupProxy(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); + [Block("Solves a ReCaptcha v3")] + public static async Task SolveRecaptchaV3(BotData data, string siteKey, string siteUrl, string action, + float minScore = 0.3F, bool enterprise = false, bool useProxy = false, + string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36") + { + data.Logger.LogHeader(); + await CheckBalanceAsync(data).ConfigureAwait(false); - AddCaptchaId(data, response.IdString, CaptchaType.ReCaptchaV3); - data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); - return response.Response; - } + var response = await data.Providers.Captcha.SolveRecaptchaV3Async(siteKey, siteUrl, action, minScore, enterprise, + CreateSessionParams(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); - // For backwards compatibility - public static Task SolveRecaptchaV3(BotData data, string siteKey, string siteUrl, string action, float minScore = 0.3F, bool useProxy = false, - string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36") - => SolveRecaptchaV3(data, siteKey, siteUrl, action, minScore, false, useProxy, userAgent); + AddCaptchaId(data, response.Id, CaptchaType.ReCaptchaV3); + data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); + return response.Response; + } - [Block("Solves a FunCaptcha")] - public static async Task SolveFunCaptcha(BotData data, string publicKey, string serviceUrl, string siteUrl, - bool noJS = false, bool useProxy = false, - string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36") - { - data.Logger.LogHeader(); - await CheckBalance(data).ConfigureAwait(false); + // For backwards compatibility + public static Task SolveRecaptchaV3(BotData data, string siteKey, string siteUrl, string action, float minScore = 0.3F, bool useProxy = false, + string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36") + => SolveRecaptchaV3(data, siteKey, siteUrl, action, minScore, false, useProxy, userAgent); - var response = await data.Providers.Captcha.SolveFuncaptchaAsync(publicKey, serviceUrl, siteUrl, noJS, - SetupProxy(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); + [Block("Solves a FunCaptcha")] + public static async Task SolveFunCaptcha(BotData data, string publicKey, string serviceUrl, string siteUrl, + bool noJS = false, string? extraData = null, bool useProxy = false, + string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36") + { + data.Logger.LogHeader(); + await CheckBalanceAsync(data).ConfigureAwait(false); - AddCaptchaId(data, response.IdString, CaptchaType.FunCaptcha); - data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); - return response.Response; - } + var response = await data.Providers.Captcha.SolveFuncaptchaAsync(publicKey, serviceUrl, siteUrl, noJS, + extraData, CreateSessionParams(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); - [Block("Solves a HCaptcha")] - public static async Task SolveHCaptcha(BotData data, string siteKey, string siteUrl, - bool useProxy = false, - string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36") - { - data.Logger.LogHeader(); - await CheckBalance(data).ConfigureAwait(false); + AddCaptchaId(data, response.Id, CaptchaType.FunCaptcha); + data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); + return response.Response; + } + + // For backwards compatibility + public static async Task SolveFunCaptcha(BotData data, string publicKey, string serviceUrl, string siteUrl, + bool noJS = false, bool useProxy = false, + string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36") + => await SolveFunCaptcha(data, publicKey, serviceUrl, siteUrl, noJS, extraData: null, useProxy, userAgent); + + [Block("Solves a HCaptcha")] + public static async Task SolveHCaptcha(BotData data, string siteKey, string siteUrl, + string? enterprisePayload = null, bool isInvisible = false, bool useProxy = false, + string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36") + { + data.Logger.LogHeader(); + await CheckBalanceAsync(data).ConfigureAwait(false); - var response = await data.Providers.Captcha.SolveHCaptchaAsync(siteKey, siteUrl, - SetupProxy(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); + var response = await data.Providers.Captcha.SolveHCaptchaAsync(siteKey, siteUrl, isInvisible, enterprisePayload, + CreateSessionParams(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); - AddCaptchaId(data, response.IdString, CaptchaType.HCaptcha); - data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); - return response.Response; - } + AddCaptchaId(data, response.Id, CaptchaType.HCaptcha); + data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); + return response.Response; + } + + // For backwards compatibility + public static async Task SolveHCaptcha(BotData data, string siteKey, string siteUrl, + bool useProxy = false, + string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36") + => await SolveHCaptcha(data, siteKey, siteUrl, enterprisePayload: null, isInvisible: false, useProxy, userAgent); + + [Block("Solves a KeyCaptcha")] + public static async Task SolveKeyCaptcha(BotData data, string userId, string sessionId, + string webServerSign1, string webServerSign2, string siteUrl, bool useProxy = false, + string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36") + { + data.Logger.LogHeader(); + await CheckBalanceAsync(data).ConfigureAwait(false); - [Block("Solves a Capy captcha")] - public static async Task> SolveCapyCaptcha(BotData data, string siteKey, string siteUrl, - bool useProxy = false, - string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36") - { - data.Logger.LogHeader(); - await CheckBalance(data).ConfigureAwait(false); - - var response = await data.Providers.Captcha.SolveCapyAsync(siteKey, siteUrl, - SetupProxy(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); - - AddCaptchaId(data, response.IdString, CaptchaType.Capy); - data.Logger.Log($"Got solution!", LogColors.ElectricBlue); - data.Logger.Log($"Challenge Key: {response.ChallengeKey}", LogColors.ElectricBlue); - data.Logger.Log($"Captcha Key: {response.CaptchaKey}", LogColors.ElectricBlue); - data.Logger.Log($"Answer: {response.Answer}", LogColors.ElectricBlue); - return new List { response.ChallengeKey, response.CaptchaKey, response.Answer }; - } + var response = await data.Providers.Captcha.SolveKeyCaptchaAsync(userId, sessionId, webServerSign1, webServerSign2, siteUrl, + CreateSessionParams(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); + + AddCaptchaId(data, response.Id, CaptchaType.KeyCaptcha); + data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); + return response.Response; + } + + [Block("Solves a GeeTest v3 captcha", + extraInfo = "The response will be a list and its elements are (in order) challenge, validate, seccode")] + public static async Task> SolveGeeTestCaptcha(BotData data, string gt, string apiChallenge, + string apiServer, string siteUrl, bool useProxy = false, + string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36") + { + data.Logger.LogHeader(); + await CheckBalanceAsync(data).ConfigureAwait(false); + + var response = await data.Providers.Captcha.SolveGeeTestAsync(gt, apiChallenge, siteUrl, apiServer, + CreateSessionParams(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); + + AddCaptchaId(data, response.Id, CaptchaType.GeeTest); + data.Logger.Log("Got solution!", LogColors.ElectricBlue); + data.Logger.Log($"Challenge: {response.Challenge}", LogColors.ElectricBlue); + data.Logger.Log($"Validate: {response.Validate}", LogColors.ElectricBlue); + data.Logger.Log($"SecCode: {response.SecCode}", LogColors.ElectricBlue); + return [response.Challenge, response.Validate, response.SecCode]; + } + + [Block("Solves a Capy captcha")] + public static async Task> SolveCapyCaptcha(BotData data, string siteKey, string siteUrl, + bool useProxy = false, + string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36") + { + data.Logger.LogHeader(); + await CheckBalanceAsync(data).ConfigureAwait(false); + + var response = await data.Providers.Captcha.SolveCapyAsync(siteKey, siteUrl, + CreateSessionParams(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); + + AddCaptchaId(data, response.Id, CaptchaType.Capy); + data.Logger.Log("Got solution!", LogColors.ElectricBlue); + data.Logger.Log($"Challenge Key: {response.ChallengeKey}", LogColors.ElectricBlue); + data.Logger.Log($"Captcha Key: {response.CaptchaKey}", LogColors.ElectricBlue); + data.Logger.Log($"Answer: {response.Answer}", LogColors.ElectricBlue); + return [response.ChallengeKey, response.CaptchaKey, response.Answer]; + } + + [Block("Solves a DataDome captcha")] + public static async Task SolveDataDomeCaptcha(BotData data, string captchaUrl, string siteUrl, + bool useProxy = false, + string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36") + { + data.Logger.LogHeader(); + await CheckBalanceAsync(data).ConfigureAwait(false); + + var response = await data.Providers.Captcha.SolveDataDomeAsync(siteUrl, captchaUrl, + CreateSessionParams(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); + + AddCaptchaId(data, response.Id, CaptchaType.DataDome); + data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); + return response.Response; + } + + [Block("Solves a Cloudflare Turnstile captcha")] + public static async Task SolveCloudflareTurnstileCaptcha(BotData data, string siteKey, string siteUrl, + string? action = null, string? cData = null, string? pageData = null, bool useProxy = false, + string userAgent = + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36") + { + data.Logger.LogHeader(); + await CheckBalanceAsync(data).ConfigureAwait(false); + + var response = await data.Providers.Captcha.SolveCloudflareTurnstileAsync(siteKey, siteUrl, action, cData, pageData, + CreateSessionParams(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); + + AddCaptchaId(data, response.Id, CaptchaType.CloudflareTurnstile); + data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); + return response.Response; + } + + [Block("Solves a Lemin Cropped captcha", + extraInfo = "The response will be a list and its elements are (in order) answer, challenge ID")] + public static async Task> SolveLeminCroppedCaptcha(BotData data, string captchaId, string siteUrl, + string apiServer = "https://api.leminnow.com/", string? divId = null, bool useProxy = false, + string userAgent = + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36") + { + data.Logger.LogHeader(); + await CheckBalanceAsync(data).ConfigureAwait(false); + + var response = await data.Providers.Captcha.SolveLeminCroppedAsync(captchaId, siteUrl, apiServer, divId, + CreateSessionParams(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); + + AddCaptchaId(data, response.Id, CaptchaType.LeminCropped); + data.Logger.Log("Got solution!", LogColors.ElectricBlue); + data.Logger.Log($"Answer: {response.Answer}", LogColors.ElectricBlue); + data.Logger.Log($"Challenge ID: {response.ChallengeId}", LogColors.ElectricBlue); + return [response.Answer, response.ChallengeId]; + } + + [Block("Solves an Amazon WAF captcha")] + public static async Task SolveAmazonWafCaptcha(BotData data, string siteKey, string siteUrl, + string iv, string context, string? challengeScript = null, string? captchaScript = null, bool useProxy = false, + string userAgent = + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36") + { + data.Logger.LogHeader(); + await CheckBalanceAsync(data).ConfigureAwait(false); + + var response = await data.Providers.Captcha.SolveAmazonWafAsync(siteKey, iv, context, siteUrl, challengeScript, + captchaScript, CreateSessionParams(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); + + AddCaptchaId(data, response.Id, CaptchaType.AmazonWaf); + data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); + return response.Response; + } + + [Block("Solves a Cyber SiARA captcha")] + public static async Task SolveCyberSiAraCaptcha(BotData data, string masterUrlId, string siteUrl, + bool useProxy = false, + string userAgent = + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36") + { + data.Logger.LogHeader(); + await CheckBalanceAsync(data).ConfigureAwait(false); + + var response = await data.Providers.Captcha.SolveCyberSiAraAsync(masterUrlId, siteUrl, + CreateSessionParams(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); + + AddCaptchaId(data, response.Id, CaptchaType.CyberSiAra); + data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); + return response.Response; + } + + [Block("Solves an MT captcha")] + public static async Task SolveMtCaptcha(BotData data, string siteKey, string siteUrl, + bool useProxy = false, string userAgent = + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36") + { + data.Logger.LogHeader(); + await CheckBalanceAsync(data).ConfigureAwait(false); + + var response = await data.Providers.Captcha.SolveMtCaptchaAsync(siteKey, siteUrl, + CreateSessionParams(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); + + AddCaptchaId(data, response.Id, CaptchaType.MtCaptcha); + data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); + return response.Response; + } + + [Block("Solves a CutCaptcha")] + public static async Task SolveCutCaptcha(BotData data, string miseryKey, string apiKey, string siteUrl, + bool useProxy = false, string userAgent = + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36") + { + data.Logger.LogHeader(); + await CheckBalanceAsync(data).ConfigureAwait(false); + + var response = await data.Providers.Captcha.SolveCutCaptchaAsync(miseryKey, apiKey, siteUrl, + CreateSessionParams(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); + + AddCaptchaId(data, response.Id, CaptchaType.CutCaptcha); + data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); + return response.Response; + } + + [Block("Solves a Friendly captcha")] + public static async Task SolveFriendlyCaptcha(BotData data, string siteKey, string siteUrl, + bool useProxy = false, string userAgent = + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36") + { + data.Logger.LogHeader(); + await CheckBalanceAsync(data).ConfigureAwait(false); + + var response = await data.Providers.Captcha.SolveFriendlyCaptchaAsync(siteKey, siteUrl, + CreateSessionParams(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); + + AddCaptchaId(data, response.Id, CaptchaType.FriendlyCaptcha); + data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); + return response.Response; + } + + [Block("Solves an atb captcha")] + public static async Task SolveAtbCaptcha(BotData data, string appId, string apiServer, string siteUrl, + bool useProxy = false, string userAgent = + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36") + { + data.Logger.LogHeader(); + await CheckBalanceAsync(data).ConfigureAwait(false); + + var response = await data.Providers.Captcha.SolveAtbCaptchaAsync(appId, apiServer, siteUrl, + CreateSessionParams(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); + + AddCaptchaId(data, response.Id, CaptchaType.AtbCaptcha); + data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); + return response.Response; + } + + [Block("Solves a Tencent captcha", + extraInfo = "The response will be a list and its elements are (in order) app id, ticket, return code, random string")] + public static async Task> SolveTencentCaptcha(BotData data, string appId, string siteUrl, + bool useProxy = false, string userAgent = + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36") + { + data.Logger.LogHeader(); + await CheckBalanceAsync(data).ConfigureAwait(false); + + var response = await data.Providers.Captcha.SolveTencentCaptchaAsync(appId, siteUrl, + CreateSessionParams(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); + + AddCaptchaId(data, response.Id, CaptchaType.TencentCaptcha); + data.Logger.Log("Got solution!", LogColors.ElectricBlue); + data.Logger.Log($"App ID: {response.AppId}", LogColors.ElectricBlue); + data.Logger.Log($"Ticket: {response.Ticket}", LogColors.ElectricBlue); + data.Logger.Log($"Return Code: {response.ReturnCode}", LogColors.ElectricBlue); + data.Logger.Log($"Random String: {response.RandomString}", LogColors.ElectricBlue); + return [response.AppId, response.Ticket, response.ReturnCode.ToString(), response.RandomString]; + } - [Block("Solves a KeyCaptcha")] - public static async Task SolveKeyCaptcha(BotData data, string userId, string sessionId, - string webServerSign1, string webServerSign2, string siteUrl, bool useProxy = false, - string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36") + [Block("Solves an audio captcha")] + public static async Task SolveAudioCaptcha(BotData data, string base64, + CaptchaLanguage language = CaptchaLanguage.NotSpecified) + { + data.Logger.LogHeader(); + await CheckBalanceAsync(data).ConfigureAwait(false); + + var response = await data.Providers.Captcha.SolveAudioCaptchaAsync(base64, new AudioCaptchaOptions { - data.Logger.LogHeader(); - await CheckBalance(data).ConfigureAwait(false); + CaptchaLanguage = language + }, data.CancellationToken).ConfigureAwait(false); + + AddCaptchaId(data, response.Id, CaptchaType.AudioCaptcha); + data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); + return response.Response; + } - var response = await data.Providers.Captcha.SolveKeyCaptchaAsync(userId, sessionId, webServerSign1, webServerSign2, siteUrl, - SetupProxy(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); + [Block("Solves a ReCaptcha Mobile")] + public static async Task SolveRecaptchaMobile(BotData data, string appPackageName, string appKey, + string appAction, bool useProxy = false, string userAgent = + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36") + { + data.Logger.LogHeader(); + await CheckBalanceAsync(data).ConfigureAwait(false); + + var response = await data.Providers.Captcha.SolveRecaptchaMobileAsync(appPackageName, appKey, appAction, + CreateSessionParams(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); + + AddCaptchaId(data, response.Id, CaptchaType.ReCaptchaMobile); + data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); + return response.Response; + } - AddCaptchaId(data, response.IdString, CaptchaType.KeyCaptcha); - data.Logger.Log($"Got solution: {response.Response}", LogColors.ElectricBlue); - return response.Response; + [Block("Solves a GeeTest v4 captcha", + extraInfo = + "The response will be a list and its elements are (in order) captcha id, lot number, pass token, gen time, captcha output")] + public static async Task> SolveGeeTestV4Captcha(BotData data, string captchaId, + string siteUrl, string userAgent = + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36") + { + data.Logger.LogHeader(); + await CheckBalanceAsync(data).ConfigureAwait(false); + + var response = await data.Providers.Captcha.SolveGeeTestV4Async(captchaId, siteUrl, + CreateSessionParams(data, useProxy: false, userAgent), data.CancellationToken).ConfigureAwait(false); + + AddCaptchaId(data, response.Id, CaptchaType.GeeTestV4); + data.Logger.Log("Got solution!", LogColors.ElectricBlue); + data.Logger.Log($"Captcha ID: {response.CaptchaId}", LogColors.ElectricBlue); + data.Logger.Log($"Lot Number: {response.LotNumber}", LogColors.ElectricBlue); + data.Logger.Log($"Pass Token: {response.PassToken}", LogColors.ElectricBlue); + data.Logger.Log($"Gen Time: {response.GenTime}", LogColors.ElectricBlue); + data.Logger.Log($"Captcha Output: {response.CaptchaOutput}", LogColors.ElectricBlue); + return [response.CaptchaId, response.LotNumber, response.PassToken, response.GenTime, response.CaptchaOutput]; + } + + [Block("Reports an incorrectly solved captcha to the service in order to get funds back")] + public static async Task ReportLastSolution(BotData data) + { + var lastCaptcha = data.TryGetObject("lastCaptchaInfo"); + + data.Logger.LogHeader(); + + if (lastCaptcha is null) + { + data.Logger.Log("No captcha has been solved yet", LogColors.ElectricBlue); + return; } - [Block("Solves a GeeTest captcha", - extraInfo = "The response will be a list and its elements are (in order) challenge, validate, seccode")] - public static async Task> SolveGeeTestCaptcha(BotData data, string gt, string apiChallenge, - string apiServer, string siteUrl, bool useProxy = false, - string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36") + try + { + await data.Providers.Captcha.ReportSolutionAsync( + lastCaptcha.Id, lastCaptcha.Type, false, data.CancellationToken).ConfigureAwait(false); + + data.Logger.Log($"Solution of task {lastCaptcha.Id} reported correctly!", LogColors.ElectricBlue); + } + catch (Exception ex) { - data.Logger.LogHeader(); - await CheckBalance(data).ConfigureAwait(false); - - var response = await data.Providers.Captcha.SolveGeeTestAsync(gt, apiChallenge, apiServer, siteUrl, - SetupProxy(data, useProxy, userAgent), data.CancellationToken).ConfigureAwait(false); - - AddCaptchaId(data, response.IdString, CaptchaType.GeeTest); - data.Logger.Log($"Got solution!", LogColors.ElectricBlue); - data.Logger.Log($"Challenge: {response.Challenge}", LogColors.ElectricBlue); - data.Logger.Log($"Validate: {response.Validate}", LogColors.ElectricBlue); - data.Logger.Log($"SecCode: {response.SecCode}", LogColors.ElectricBlue); - return new List { response.Challenge, response.Validate, response.SecCode }; + data.Logger.Log( + $"Could not report the solution of task {lastCaptcha.Id} to the service: {ex.Message}", + LogColors.ElectricBlue); } + } - [Block("Reports an incorrectly solved captcha to the service in order to get funds back")] - public static async Task ReportLastSolution(BotData data) + private static async Task CheckBalanceAsync(BotData data) + { + if (!data.Providers.Captcha.CheckBalanceBeforeSolving) { - var lastCaptcha = data.TryGetObject("lastCaptchaInfo"); + return; + } - data.Logger.LogHeader(); + try + { + data.CaptchaCredit = await data.Providers.Captcha.GetBalanceAsync(data.CancellationToken).ConfigureAwait(false); + data.Logger.Log($"[{data.Providers.Captcha.ServiceType}] Balance: ${data.CaptchaCredit}", LogColors.ElectricBlue); - try - { - // TODO: Create a ReportSolution method that accepts strings in CaptchaSharp! For now we will do it like this - // since the only service which has string-based captcha IDs does not support reporting bad solutions. - await data.Providers.Captcha.ReportSolution(long.Parse(lastCaptcha.Id), lastCaptcha.Type, false, data.CancellationToken).ConfigureAwait(false); - data.Logger.Log($"Solution of task {lastCaptcha.Id} reported correctly!", LogColors.ElectricBlue); - } - catch (Exception ex) + if (data.CaptchaCredit < (decimal)0.002) + throw new Exception("The remaining balance is too low!"); + } + catch (Exception ex) // This unwraps aggregate exceptions + { + if (ex is AggregateException { InnerException: not null } aggEx) { - data.Logger.Log($"Could not report the solution of task {lastCaptcha.Id} to the service: {ex.Message}", LogColors.ElectricBlue); + throw aggEx.InnerException; } + + throw; } + } - private static async Task CheckBalance(BotData data) - { - if (!data.Providers.Captcha.CheckBalanceBeforeSolving) - return; + private static void AddCaptchaId(BotData data, string id, CaptchaType type) + => data.SetObject("lastCaptchaInfo", new CaptchaInfo { Id = id, Type = type }); - try - { - data.CaptchaCredit = await data.Providers.Captcha.GetBalanceAsync(data.CancellationToken).ConfigureAwait(false); - data.Logger.Log($"[{data.Providers.Captcha.ServiceType}] Balance: ${data.CaptchaCredit}", LogColors.ElectricBlue); - - if (data.CaptchaCredit < (decimal)0.002) - throw new Exception("The remaining balance is too low!"); - } - catch (Exception ex) // This unwraps aggregate exceptions + private static SessionParams CreateSessionParams(BotData data, bool useProxy, string userAgent) + { + var proxy = data.UseProxy && useProxy && data.Proxy is not null + ? new Proxy { - if (ex is AggregateException) throw ex.InnerException; - else throw; + Host = data.Proxy.Host, + Port = data.Proxy.Port, + Type = Enum.Parse(data.Proxy.Type.ToString(), true), + Username = data.Proxy.Username, + Password = data.Proxy.Password } - } + : null; - private static void AddCaptchaId(BotData data, string id, CaptchaType type) - => data.SetObject("lastCaptchaInfo", new CaptchaInfo { Id = id, Type = type }); - - private static Proxy SetupProxy(BotData data, bool useProxy, string userAgent) - => data.UseProxy && useProxy - ? new Proxy - { - Host = data.Proxy.Host, - Port = data.Proxy.Port, - Type = Enum.Parse(data.Proxy.Type.ToString(), true), - Username = data.Proxy.Username, - Password = data.Proxy.Password, - UserAgent = userAgent, - Cookies = data.COOKIES - .Select(c => (c.Key, c.Value)).ToArray() - } - : null; + return new SessionParams + { + Proxy = proxy, + UserAgent = userAgent, + Cookies = data.COOKIES + }; } } diff --git a/RuriLib/Functions/Captchas/CaptchaServiceFactory.cs b/RuriLib/Functions/Captchas/CaptchaServiceFactory.cs index 60a3dc05f..5d603464a 100644 --- a/RuriLib/Functions/Captchas/CaptchaServiceFactory.cs +++ b/RuriLib/Functions/Captchas/CaptchaServiceFactory.cs @@ -1,58 +1,65 @@ -using CaptchaSharp; -using CaptchaSharp.Services; -using CaptchaSharp.Services.More; +using CaptchaSharp.Services; using RuriLib.Models.Settings; using System; -namespace RuriLib.Functions.Captchas +namespace RuriLib.Functions.Captchas; + +public class CaptchaServiceFactory { - public class CaptchaServiceFactory + /// + /// Gets a to be used for solving captcha challenges. + /// + public static CaptchaService GetService(CaptchaSettings settings) { - /// - /// Gets a to be used for solving captcha challenges. - /// - public static CaptchaService GetService(CaptchaSettings settings) + CaptchaService service = settings.CurrentService switch { - CaptchaService service = settings.CurrentService switch - { - CaptchaServiceType.AntiCaptcha => new AntiCaptchaService(settings.AntiCaptchaApiKey), - CaptchaServiceType.AzCaptcha => new AzCaptchaService(settings.AZCaptchaApiKey), - CaptchaServiceType.CaptchasIO => new CaptchasIOService(settings.CaptchasDotIoApiKey), - CaptchaServiceType.CustomTwoCaptcha => new CustomTwoCaptchaService(settings.CustomTwoCaptchaApiKey, - GetUri(settings.CustomTwoCaptchaDomain, settings.CustomTwoCaptchaPort), - null, settings.CustomTwoCaptchaOverrideHostHeader), - CaptchaServiceType.CapMonster => new CapMonsterService(string.Empty, - GetUri(settings.CapMonsterHost, settings.CapMonsterPort)), - CaptchaServiceType.DeathByCaptcha => new DeathByCaptchaService(settings.DeathByCaptchaUsername, settings.DeathByCaptchaPassword), - CaptchaServiceType.DeCaptcher => new DeCaptcherService(settings.DeCaptcherUsername, settings.DeCaptcherPassword), - CaptchaServiceType.ImageTyperz => new ImageTyperzService(settings.ImageTyperzApiKey), - CaptchaServiceType.RuCaptcha => new RuCaptchaService(settings.RuCaptchaApiKey), - CaptchaServiceType.SolveCaptcha => new SolveCaptchaService(settings.SolveCaptchaApiKey), - CaptchaServiceType.SolveRecaptcha => new SolveRecaptchaService(settings.SolveRecaptchaApiKey), - CaptchaServiceType.TrueCaptcha => new TrueCaptchaService(settings.TrueCaptchaUsername, settings.TrueCaptchaApiKey), - CaptchaServiceType.TwoCaptcha => new TwoCaptchaService(settings.TwoCaptchaApiKey), - CaptchaServiceType.NineKW => new NineKWService(settings.NineKWApiKey), - CaptchaServiceType.CustomAntiCaptcha => new CustomAntiCaptchaService(settings.CustomAntiCaptchaApiKey, - GetUri(settings.CustomAntiCaptchaDomain, settings.CustomAntiCaptchaPort)), - CaptchaServiceType.AnyCaptcha => new AnyCaptchaService(settings.AnyCaptchaApiKey), - CaptchaServiceType.CapSolver => new CapSolverService(settings.CapSolverApiKey), - _ => throw new NotSupportedException(), - }; + CaptchaServiceType.TwoCaptcha => new TwoCaptchaService(settings.TwoCaptchaApiKey), + CaptchaServiceType.AntiCaptcha => new AntiCaptchaService(settings.AntiCaptchaApiKey), + CaptchaServiceType.CustomTwoCaptcha => new CustomTwoCaptchaService(settings.CustomTwoCaptchaApiKey, + GetUri(settings.CustomTwoCaptchaDomain, settings.CustomTwoCaptchaPort), + null, settings.CustomTwoCaptchaOverrideHostHeader), + CaptchaServiceType.DeathByCaptcha => new DeathByCaptchaService(settings.DeathByCaptchaUsername, settings.DeathByCaptchaPassword), + CaptchaServiceType.CaptchaCoder => new CaptchaCoderService(settings.CaptchaCoderApiKey), + CaptchaServiceType.ImageTyperz => new ImageTyperzService(settings.ImageTyperzApiKey), + CaptchaServiceType.CapMonster => new CapMonsterService(string.Empty, + GetUri(settings.CapMonsterHost, settings.CapMonsterPort)), + CaptchaServiceType.AzCaptcha => new AzCaptchaService(settings.AZCaptchaApiKey), + CaptchaServiceType.CaptchasIo => new CaptchasIoService(settings.CaptchasDotIoApiKey), + CaptchaServiceType.RuCaptcha => new RuCaptchaService(settings.RuCaptchaApiKey), + CaptchaServiceType.SolveCaptcha => new SolveCaptchaService(settings.SolveCaptchaApiKey), + CaptchaServiceType.TrueCaptcha => new TrueCaptchaService(settings.TrueCaptchaUsername, settings.TrueCaptchaApiKey), + CaptchaServiceType.NineKw => new NineKwService(settings.NineKWApiKey), + CaptchaServiceType.CustomAntiCaptcha => new CustomAntiCaptchaService(settings.CustomAntiCaptchaApiKey, + GetUri(settings.CustomAntiCaptchaDomain, settings.CustomAntiCaptchaPort)), + CaptchaServiceType.CapSolver => new CapSolverService(settings.CapSolverApiKey), + CaptchaServiceType.CapMonsterCloud => new CapMonsterCloudService(settings.CapMonsterCloudApiKey), + CaptchaServiceType.HumanCoder => new HumanCoderService(settings.HumanCoderApiKey), + CaptchaServiceType.Nopecha => new NopechaService(settings.NopechaApiKey), + CaptchaServiceType.NoCaptchaAi => new NoCaptchaAiService(settings.NoCaptchaAiApiKey), + CaptchaServiceType.MetaBypassTech => new MetaBypassTechService(settings.MetaBypassTechClientId, + settings.MetaBypassTechClientSecret, settings.MetaBypassTechUsername, settings.MetaBypassTechPassword), + CaptchaServiceType.CaptchaAi => new CaptchaAiService(settings.CaptchaAiApiKey), + CaptchaServiceType.NextCaptcha => new NextCaptchaService(settings.NextCaptchaApiKey), + CaptchaServiceType.EzCaptcha => new EzCaptchaService(settings.EzCaptchaApiKey), + CaptchaServiceType.EndCaptcha => new EndCaptchaService(settings.EndCaptchaUsername, settings.EndCaptchaPassword), + CaptchaServiceType.BestCaptchaSolver => new BestCaptchaSolverService(settings.BestCaptchaSolverApiKey), + CaptchaServiceType.CapGuru => new CapGuruService(settings.CapGuruApiKey), + _ => throw new NotSupportedException(), + }; - service.Timeout = TimeSpan.FromSeconds(settings.TimeoutSeconds); - service.PollingInterval = TimeSpan.FromMilliseconds(settings.PollingIntervalMilliseconds); - return service; - } + service.Timeout = TimeSpan.FromSeconds(settings.TimeoutSeconds); + service.PollingInterval = TimeSpan.FromMilliseconds(settings.PollingIntervalMilliseconds); + return service; + } - private static Uri GetUri(string host, int port) + private static Uri GetUri(string host, int port) + { + // If there is no http(s) then add http by default + if (!host.StartsWith("http")) { - // If there is no http(s) then add http by default - if (!host.StartsWith("http")) - { - host = $"http://{host}"; - } - - return new Uri($"{host}:{port}"); + host = $"http://{host}"; } + + return new Uri($"{host}:{port}"); } } diff --git a/RuriLib/Functions/Captchas/CaptchaServiceType.cs b/RuriLib/Functions/Captchas/CaptchaServiceType.cs index 7210478d0..083ed8976 100644 --- a/RuriLib/Functions/Captchas/CaptchaServiceType.cs +++ b/RuriLib/Functions/Captchas/CaptchaServiceType.cs @@ -1,57 +1,88 @@ -namespace RuriLib.Functions.Captchas -{ - /// The available captcha solving service providers. - public enum CaptchaServiceType - { - /// The service provided by 2captcha.com - TwoCaptcha, - - /// The service provided by anti-captcha.com - AntiCaptcha, - - /// A service that implements the 2captcha API. - CustomTwoCaptcha, - - /// The service provided by deathbycaptcha.com - DeathByCaptcha, - - /// The service provided by de-captcher.com - DeCaptcher, - - /// The service provided by imagetyperz.com - ImageTyperz, - - /// The service provided by the CapMonster OCR application by ZennoLab. - CapMonster, - - /// The service provided by azcaptcha.com - AzCaptcha, - - /// The service provided by captchas.io - CaptchasIO, +namespace RuriLib.Functions.Captchas; - /// The service provided by rucaptcha.com - RuCaptcha, - - /// The service provided by solvecaptcha.com - SolveCaptcha, - - /// The service provided by solverecaptcha.com - SolveRecaptcha, - - /// The service provided by apitruecaptcha.org - TrueCaptcha, - - /// The service provided by 9kw.eu - NineKW, - - /// A service that implements the anti-captcha API. - CustomAntiCaptcha, - - /// The service provided by anycaptcha.com - AnyCaptcha, - - /// The service provided by capsolver.com - CapSolver - } +/// +/// The available captcha solving service providers. +/// +public enum CaptchaServiceType +{ + // IMPORTANT: The enum values should not be changed because they are + // used to identify the service in the settings file. + + /// The service provided by https://2captcha.com/ + TwoCaptcha = 0, + + /// The service provided by https://anti-captcha.com/ + AntiCaptcha = 1, + + /// A service that implements the 2captcha API. + CustomTwoCaptcha = 2, + + /// The service provided by https://deathbycaptcha.com/ + DeathByCaptcha = 3, + + /// The service provided by https://captchacoder.com/ + CaptchaCoder = 4, + + /// The service provided by https://www.imagetyperz.com/ + ImageTyperz = 5, + + /// The service provided by the CapMonster OCR application by ZennoLab. + CapMonster = 6, + + /// The service provided by https://azcaptcha.com/ + AzCaptcha = 7, + + /// The service provided by https://captchas.io/ + CaptchasIo = 8, + + /// The service provided by https://rucaptcha.com/ + RuCaptcha = 9, + + /// The service provided by https://solvecaptcha.net/ + SolveCaptcha = 10, + + /// The service provided by https://truecaptcha.com/ + TrueCaptcha = 12, + + /// The service provided by https://www.9kw.eu/ + NineKw = 13, + + /// A service that implements the anti-captcha API. + CustomAntiCaptcha = 14, + + /// The service provided by https://capsolver.com/ + CapSolver = 16, + + /// The service provided by https://capmonster.cloud/ + CapMonsterCloud = 17, + + /// The service provided by https://humancoder.com/ + HumanCoder = 18, + + /// The service provided by https://nopecha.com/ + Nopecha = 19, + + /// The service provided by https://nocaptchaai.com/ + NoCaptchaAi = 20, + + /// The service provided by https://metabypass.tech/ + MetaBypassTech = 21, + + /// The service provided by https://captchai.com/ + CaptchaAi = 22, + + /// The service provided by https://nextcaptcha.com/ + NextCaptcha = 23, + + /// The service provided by https://ez-captcha.com/ + EzCaptcha = 24, + + /// The service provided by https://endcaptcha.com/ + EndCaptcha = 25, + + /// The service provided by https://bestcaptchasolver.com/ + BestCaptchaSolver = 26, + + /// The service provided by https://cap.guru/ + CapGuru = 27, } diff --git a/RuriLib/Legacy/Blocks/BlockSolveCaptcha.cs b/RuriLib/Legacy/Blocks/BlockSolveCaptcha.cs index 44359a810..dc0154e2d 100644 --- a/RuriLib/Legacy/Blocks/BlockSolveCaptcha.cs +++ b/RuriLib/Legacy/Blocks/BlockSolveCaptcha.cs @@ -6,477 +6,503 @@ using RuriLib.Legacy.LS; using RuriLib.Legacy.Models; using System.Threading.Tasks; +using CaptchaSharp.Models.CaptchaOptions; +using CaptchaSharp.Models.CaptchaResponses; using RuriLib.Logging; using RuriLib.Models.Captchas; -namespace RuriLib.Legacy.Blocks +namespace RuriLib.Legacy.Blocks; + +/// +/// A block that solves a captcha challenge using a remote solving service. +/// +public class BlockSolveCaptcha : BlockBase { - /// - /// A block that solves a captcha challenge using a remote solving service. - /// - public class BlockSolveCaptcha : BlockBase - { - #region General - /// The type of captcha to solve. - public CaptchaType Type { get; set; } = CaptchaType.ReCaptchaV2; + #region General + /// The type of captcha to solve. + public CaptchaType Type { get; set; } = CaptchaType.ReCaptchaV2; - /// Whether to tell the service to use your proxy to solve captchas. - public bool UseProxy { get; set; } = false; + /// Whether to tell the service to use your proxy to solve captchas. + public bool UseProxy { get; set; } = false; - /// The user agent that the service will use (should be the same as yours). - public string UserAgent { get; set; } = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36"; - #endregion + /// The user agent that the service will use (should be the same as yours). + public string UserAgent { get; set; } = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36"; + #endregion - #region TextCaptcha - /// The captcha question to answer. - public string Question { get; set; } = ""; + #region TextCaptcha + /// The captcha question to answer. + public string Question { get; set; } = ""; - /// The language group of the captcha text. - public CaptchaLanguageGroup LanguageGroup { get; set; } = CaptchaLanguageGroup.NotSpecified; + /// The language group of the captcha text. + public CaptchaLanguageGroup LanguageGroup { get; set; } = CaptchaLanguageGroup.NotSpecified; - /// The language group of the captcha text. - public CaptchaLanguage Language { get; set; } = CaptchaLanguage.NotSpecified; - #endregion + /// The language group of the captcha text. + public CaptchaLanguage Language { get; set; } = CaptchaLanguage.NotSpecified; + #endregion - #region ImageCaptcha - /// The captcha image as a base64 encoded string. - public string Base64 { get; set; } = ""; + #region ImageCaptcha + /// The captcha image as a base64 encoded string. + public string Base64 { get; set; } = ""; - /// Whether the captcha has multiple words. - public bool IsPhrase { get; set; } = false; + /// Whether the captcha has multiple words. + public bool IsPhrase { get; set; } = false; - /// Whether the captcha solution should be case sensitive. - public bool CaseSensitive { get; set; } = false; + /// Whether the captcha solution should be case-sensitive. + public bool CaseSensitive { get; set; } = false; - /// The type of characters that can appear in the image. - public CharacterSet CharSet { get; set; } = CharacterSet.NotSpecified; + /// The type of characters that can appear in the image. + public CharacterSet CharSet { get; set; } = CharacterSet.NotSpecified; - /// Whether the captcha requires mathematical calculations. - public bool RequiresCalculation { get; set; } = false; + /// Whether the captcha requires mathematical calculations. + public bool RequiresCalculation { get; set; } = false; - /// The minimum length of the solution (0 is unspecified). - public int MinLength { get; set; } = 0; + /// The minimum length of the solution (0 is unspecified). + public int MinLength { get; set; } - /// The maximum length of the solution (0 is unspecified). - public int MaxLength { get; set; } = 0; + /// The maximum length of the solution (0 is unspecified). + public int MaxLength { get; set; } - /// Any additional instructions useful to the solution. - public string TextInstructions { get; set; } = ""; - #endregion + /// Any additional instructions useful to the solution. + public string TextInstructions { get; set; } = ""; + #endregion - #region Token Captchas - /// The site key. - public string SiteKey { get; set; } = ""; + #region Token Captchas + /// The site key. + public string SiteKey { get; set; } = ""; - /// The site URL. - public string SiteUrl { get; set; } = ""; + /// The site URL. + public string SiteUrl { get; set; } = ""; - /// Whether the ReCaptchaV2 is invisible. - public bool IsInvisible { get; set; } = false; + /// Whether the ReCaptchaV2 is invisible. + public bool IsInvisible { get; set; } = false; - /// The ReCaptchaV3 action. - public string Action { get; set; } = ""; + /// The ReCaptchaV3 action. + public string Action { get; set; } = ""; - /// The ReCaptchaV3 minimum required score. - public string MinScore { get; set; } = "0.3"; - #endregion + /// The ReCaptchaV3 minimum required score. + public string MinScore { get; set; } = "0.3"; + #endregion - #region FunCaptcha - /// The public key of the website. - public string PublicKey { get; set; } = ""; + #region FunCaptcha + /// The public key of the website. + public string PublicKey { get; set; } = ""; - /// The service URL of the website. - public string ServiceUrl { get; set; } = ""; + /// The service URL of the website. + public string ServiceUrl { get; set; } = ""; - /// Whether to solve the FunCaptcha with JS disabled. - public bool NoJS { get; set; } = false; - #endregion + /// Whether to solve the FunCaptcha with JS disabled. + public bool NoJS { get; set; } = false; + #endregion - #region KeyCaptcha - /// The user ID. - public string UserId { get; set; } = ""; + #region KeyCaptcha + /// The user ID. + public string UserId { get; set; } = ""; - /// The session ID. - public string SessionId { get; set; } = ""; + /// The session ID. + public string SessionId { get; set; } = ""; - /// The WebServerSign1. - public string WebServerSign1 { get; set; } = ""; + /// The WebServerSign1. + public string WebServerSign1 { get; set; } = ""; - /// The WebServerSign2. - public string WebServerSign2 { get; set; } = ""; - #endregion + /// The WebServerSign2. + public string WebServerSign2 { get; set; } = ""; + #endregion - #region GeeTest - /// The gt static key. - public string GT { get; set; } = ""; + #region GeeTest + /// The gt static key. + public string GT { get; set; } = ""; - /// The challenge dynamic key. - public string Challenge { get; set; } = ""; + /// The challenge dynamic key. + public string Challenge { get; set; } = ""; - /// The api server domain. - public string ApiServer { get; set; } = ""; - #endregion + /// The api server domain. + public string ApiServer { get; set; } = ""; + #endregion - /// - /// Creates a SolveCaptcha block. - /// - public BlockSolveCaptcha() - { - Label = "SOLVE CAPTCHA"; - } - - /// - public override BlockBase FromLS(string line) - { - // Trim the line - var input = line.Trim(); - - // Parse the label - if (input.StartsWith("#")) - Label = LineParser.ParseLabel(ref input); + /// + /// Creates a SolveCaptcha block. + /// + public BlockSolveCaptcha() + { + Label = "SOLVE CAPTCHA"; + } - Type = (CaptchaType)LineParser.ParseEnum(ref input, "TYPE", typeof(CaptchaType)); + /// + public override BlockBase FromLS(string line) + { + // Trim the line + var input = line.Trim(); - switch (Type) - { - case CaptchaType.TextCaptcha: - // SOLVECAPTCHA TextCaptcha "question?" LANGUAGEGROUP LANGUAGE - Question = LineParser.ParseLiteral(ref input, "QUESTION"); - LanguageGroup = (CaptchaLanguageGroup)LineParser.ParseEnum(ref input, "LANG GROUP", typeof(CaptchaLanguageGroup)); - Language = (CaptchaLanguage)LineParser.ParseEnum(ref input, "LANG", typeof(CaptchaLanguage)); - break; - - case CaptchaType.ImageCaptcha: - // SOLVECAPTCHA ImageCaptcha "base64" LANGUAGEGROUP LANGUAGE MINLEN MAXLEN CHARSET "instructions" - // [IsPhrase?] [CaseSensitive?] [RequiresCalculation?] - Base64 = LineParser.ParseLiteral(ref input, "BASE64"); - LanguageGroup = (CaptchaLanguageGroup)LineParser.ParseEnum(ref input, "LANG GROUP", typeof(CaptchaLanguageGroup)); - Language = (CaptchaLanguage)LineParser.ParseEnum(ref input, "LANG", typeof(CaptchaLanguage)); - MinLength = LineParser.ParseInt(ref input, "MIN LEN"); - MaxLength = LineParser.ParseInt(ref input, "MAX LEN"); - CharSet = (CharacterSet)LineParser.ParseEnum(ref input, "CHARSET", typeof(CharacterSet)); - TextInstructions = LineParser.ParseLiteral(ref input, "INSTRUCTIONS"); - while (LineParser.Lookahead(ref input) == TokenType.Boolean) - LineParser.SetBool(ref input, this); - break; - - case CaptchaType.ReCaptchaV2: - // SOLVECAPTCHA ReCaptchaV2 "sitekey" "siteurl" [IsInvisible?] - SiteKey = LineParser.ParseLiteral(ref input, "SITE KEY"); - SiteUrl = LineParser.ParseLiteral(ref input, "SITE URL"); - while (LineParser.Lookahead(ref input) == TokenType.Boolean) - LineParser.SetBool(ref input, this); - break; - - case CaptchaType.ReCaptchaV3: - // SOLVECAPTCHA ReCaptchaV3 "sitekey" "siteurl" "action" "minscore" - SiteKey = LineParser.ParseLiteral(ref input, "SITE KEY"); - SiteUrl = LineParser.ParseLiteral(ref input, "SITE URL"); - Action = LineParser.ParseLiteral(ref input, "ACTION"); - MinScore = LineParser.ParseLiteral(ref input, "MIN SCORE"); - break; - - case CaptchaType.FunCaptcha: - // SOLVECAPTCHA FunCaptcha "pkey" "serviceurl" [NoJS?] - SiteUrl = LineParser.ParseLiteral(ref input, "SITE URL"); - PublicKey = LineParser.ParseLiteral(ref input, "PUBLIC KEY"); - ServiceUrl = LineParser.ParseLiteral(ref input, "SERVICE URL"); - while (LineParser.Lookahead(ref input) == TokenType.Boolean) - LineParser.SetBool(ref input, this); - break; - - case CaptchaType.KeyCaptcha: - // SOLVECAPTCHA KeyCaptcha "userid" "sessionid" "wss1" "wss2" - SiteUrl = LineParser.ParseLiteral(ref input, "SITE URL"); - UserId = LineParser.ParseLiteral(ref input, "USER ID"); - SessionId = LineParser.ParseLiteral(ref input, "SESSION ID"); - WebServerSign1 = LineParser.ParseLiteral(ref input, "WEBSERVER SIGN 1"); - WebServerSign2 = LineParser.ParseLiteral(ref input, "WEBSERVER SIGN 2"); - break; - - case CaptchaType.HCaptcha: - // SOLVECAPTCHA HCaptcha "sitekey" "siteurl" - SiteKey = LineParser.ParseLiteral(ref input, "SITE KEY"); - SiteUrl = LineParser.ParseLiteral(ref input, "SITE URL"); - break; - - case CaptchaType.GeeTest: - // SOLVECAPTCHA GeeTest "siteurl" "gt" "challenge" "apiserver" - SiteUrl = LineParser.ParseLiteral(ref input, "SITE URL"); - GT = LineParser.ParseLiteral(ref input, "GT"); - Challenge = LineParser.ParseLiteral(ref input, "CHALLENGE"); - ApiServer = LineParser.ParseLiteral(ref input, "API SERVER"); - break; - - case CaptchaType.Capy: - // SOLVECAPTCHA Capy "sitekey" "siteurl" - SiteKey = LineParser.ParseLiteral(ref input, "SITE KEY"); - SiteUrl = LineParser.ParseLiteral(ref input, "SITE URL"); - break; - } + // Parse the label + if (input.StartsWith("#")) + Label = LineParser.ParseLabel(ref input); - while (LineParser.Lookahead(ref input) == TokenType.Boolean) - LineParser.SetBool(ref input, this); + Type = (CaptchaType)LineParser.ParseEnum(ref input, "TYPE", typeof(CaptchaType)); - if (LineParser.Lookahead(ref input) == TokenType.Literal) - UserAgent = LineParser.ParseLiteral(ref input, "USER AGENT"); + switch (Type) + { + case CaptchaType.TextCaptcha: + // SOLVECAPTCHA TextCaptcha "question?" LANGUAGEGROUP LANGUAGE + Question = LineParser.ParseLiteral(ref input, "QUESTION"); + LanguageGroup = (CaptchaLanguageGroup)LineParser.ParseEnum(ref input, "LANG GROUP", typeof(CaptchaLanguageGroup)); + Language = (CaptchaLanguage)LineParser.ParseEnum(ref input, "LANG", typeof(CaptchaLanguage)); + break; + + case CaptchaType.ImageCaptcha: + // SOLVECAPTCHA ImageCaptcha "base64" LANGUAGEGROUP LANGUAGE MINLEN MAXLEN CHARSET "instructions" + // [IsPhrase?] [CaseSensitive?] [RequiresCalculation?] + Base64 = LineParser.ParseLiteral(ref input, "BASE64"); + LanguageGroup = (CaptchaLanguageGroup)LineParser.ParseEnum(ref input, "LANG GROUP", typeof(CaptchaLanguageGroup)); + Language = (CaptchaLanguage)LineParser.ParseEnum(ref input, "LANG", typeof(CaptchaLanguage)); + MinLength = LineParser.ParseInt(ref input, "MIN LEN"); + MaxLength = LineParser.ParseInt(ref input, "MAX LEN"); + CharSet = (CharacterSet)LineParser.ParseEnum(ref input, "CHARSET", typeof(CharacterSet)); + TextInstructions = LineParser.ParseLiteral(ref input, "INSTRUCTIONS"); + while (LineParser.Lookahead(ref input) == TokenType.Boolean) + LineParser.SetBool(ref input, this); + break; + + case CaptchaType.ReCaptchaV2: + // SOLVECAPTCHA ReCaptchaV2 "sitekey" "siteurl" [IsInvisible?] + SiteKey = LineParser.ParseLiteral(ref input, "SITE KEY"); + SiteUrl = LineParser.ParseLiteral(ref input, "SITE URL"); + while (LineParser.Lookahead(ref input) == TokenType.Boolean) + LineParser.SetBool(ref input, this); + break; + + case CaptchaType.ReCaptchaV3: + // SOLVECAPTCHA ReCaptchaV3 "sitekey" "siteurl" "action" "minscore" + SiteKey = LineParser.ParseLiteral(ref input, "SITE KEY"); + SiteUrl = LineParser.ParseLiteral(ref input, "SITE URL"); + Action = LineParser.ParseLiteral(ref input, "ACTION"); + MinScore = LineParser.ParseLiteral(ref input, "MIN SCORE"); + break; + + case CaptchaType.FunCaptcha: + // SOLVECAPTCHA FunCaptcha "pkey" "serviceurl" [NoJS?] + SiteUrl = LineParser.ParseLiteral(ref input, "SITE URL"); + PublicKey = LineParser.ParseLiteral(ref input, "PUBLIC KEY"); + ServiceUrl = LineParser.ParseLiteral(ref input, "SERVICE URL"); + while (LineParser.Lookahead(ref input) == TokenType.Boolean) + LineParser.SetBool(ref input, this); + break; + + case CaptchaType.KeyCaptcha: + // SOLVECAPTCHA KeyCaptcha "userid" "sessionid" "wss1" "wss2" + SiteUrl = LineParser.ParseLiteral(ref input, "SITE URL"); + UserId = LineParser.ParseLiteral(ref input, "USER ID"); + SessionId = LineParser.ParseLiteral(ref input, "SESSION ID"); + WebServerSign1 = LineParser.ParseLiteral(ref input, "WEBSERVER SIGN 1"); + WebServerSign2 = LineParser.ParseLiteral(ref input, "WEBSERVER SIGN 2"); + break; + + case CaptchaType.HCaptcha: + // SOLVECAPTCHA HCaptcha "sitekey" "siteurl" + SiteKey = LineParser.ParseLiteral(ref input, "SITE KEY"); + SiteUrl = LineParser.ParseLiteral(ref input, "SITE URL"); + break; + + case CaptchaType.GeeTest: + // SOLVECAPTCHA GeeTest "siteurl" "gt" "challenge" "apiserver" + SiteUrl = LineParser.ParseLiteral(ref input, "SITE URL"); + GT = LineParser.ParseLiteral(ref input, "GT"); + Challenge = LineParser.ParseLiteral(ref input, "CHALLENGE"); + ApiServer = LineParser.ParseLiteral(ref input, "API SERVER"); + break; + + case CaptchaType.Capy: + // SOLVECAPTCHA Capy "sitekey" "siteurl" + SiteKey = LineParser.ParseLiteral(ref input, "SITE KEY"); + SiteUrl = LineParser.ParseLiteral(ref input, "SITE URL"); + break; + + default: + throw new NotSupportedException( + $"The currently selected service does not support tasks of type {Type}"); + } - return this; + while (LineParser.Lookahead(ref input) == TokenType.Boolean) + { + LineParser.SetBool(ref input, this); } - /// - public override string ToLS(bool indent = true) + if (LineParser.Lookahead(ref input) == TokenType.Literal) { - var writer = new BlockWriter(GetType(), indent, Disabled); - writer - .Label(Label) - .Token("SOLVECAPTCHA") - .Token(Type); + UserAgent = LineParser.ParseLiteral(ref input, "USER AGENT"); + } - switch (Type) - { - case CaptchaType.TextCaptcha: - writer - .Literal(Question) - .Token(LanguageGroup) - .Token(Language); - break; - - case CaptchaType.ImageCaptcha: - writer - .Literal(Base64) - .Token(LanguageGroup) - .Token(Language) - .Integer(MinLength) - .Integer(MaxLength) - .Token(CharSet) - .Literal(TextInstructions) - .Boolean(IsPhrase, nameof(IsPhrase)) - .Boolean(CaseSensitive, nameof(CaseSensitive)) - .Boolean(RequiresCalculation, nameof(RequiresCalculation)); - break; - - case CaptchaType.ReCaptchaV2: - writer - .Literal(SiteKey) - .Literal(SiteUrl) - .Boolean(IsInvisible, nameof(IsInvisible)); - break; - - case CaptchaType.ReCaptchaV3: - writer - .Literal(SiteKey) - .Literal(SiteUrl) - .Literal(Action) - .Literal(MinScore); - break; - - case CaptchaType.FunCaptcha: - writer - .Literal(SiteUrl) - .Literal(PublicKey) - .Literal(ServiceUrl) - .Boolean(NoJS, nameof(NoJS)); - break; - - case CaptchaType.KeyCaptcha: - writer - .Literal(SiteUrl) - .Literal(UserId) - .Literal(SessionId) - .Literal(WebServerSign1) - .Literal(WebServerSign2); - break; - - case CaptchaType.Capy: - case CaptchaType.HCaptcha: - writer - .Literal(SiteKey) - .Literal(SiteUrl); - break; - - case CaptchaType.GeeTest: - writer - .Literal(SiteUrl) - .Literal(GT) - .Literal(Challenge) - .Literal(ApiServer); - break; - } + return this; + } - writer - .Boolean(UseProxy, nameof(UseProxy)) - .Literal(UserAgent, nameof(UserAgent)); + /// + public override string ToLS(bool indent = true) + { + var writer = new BlockWriter(GetType(), indent, Disabled); + writer + .Label(Label) + .Token("SOLVECAPTCHA") + .Token(Type); - return writer.ToString(); + switch (Type) + { + case CaptchaType.TextCaptcha: + writer + .Literal(Question) + .Token(LanguageGroup) + .Token(Language); + break; + + case CaptchaType.ImageCaptcha: + writer + .Literal(Base64) + .Token(LanguageGroup) + .Token(Language) + .Integer(MinLength) + .Integer(MaxLength) + .Token(CharSet) + .Literal(TextInstructions) + .Boolean(IsPhrase, nameof(IsPhrase)) + .Boolean(CaseSensitive, nameof(CaseSensitive)) + .Boolean(RequiresCalculation, nameof(RequiresCalculation)); + break; + + case CaptchaType.ReCaptchaV2: + writer + .Literal(SiteKey) + .Literal(SiteUrl) + .Boolean(IsInvisible, nameof(IsInvisible)); + break; + + case CaptchaType.ReCaptchaV3: + writer + .Literal(SiteKey) + .Literal(SiteUrl) + .Literal(Action) + .Literal(MinScore); + break; + + case CaptchaType.FunCaptcha: + writer + .Literal(SiteUrl) + .Literal(PublicKey) + .Literal(ServiceUrl) + .Boolean(NoJS, nameof(NoJS)); + break; + + case CaptchaType.KeyCaptcha: + writer + .Literal(SiteUrl) + .Literal(UserId) + .Literal(SessionId) + .Literal(WebServerSign1) + .Literal(WebServerSign2); + break; + + case CaptchaType.Capy: + case CaptchaType.HCaptcha: + writer + .Literal(SiteKey) + .Literal(SiteUrl); + break; + + case CaptchaType.GeeTest: + writer + .Literal(SiteUrl) + .Literal(GT) + .Literal(Challenge) + .Literal(ApiServer); + break; } - /// - public override async Task Process(LSGlobals ls) - { - var data = ls.BotData; - await base.Process(ls); + writer + .Boolean(UseProxy, nameof(UseProxy)) + .Literal(UserAgent, nameof(UserAgent)); - string errorMessage; + return writer.ToString(); + } - Proxy proxy = data.UseProxy && UseProxy - ? proxy = new Proxy - { - Host = data.Proxy.Host, - Port = data.Proxy.Port, - Type = (ProxyType)Enum.Parse(typeof(ProxyType), data.Proxy.Type.ToString()), - Username = data.Proxy.Username, - Password = data.Proxy.Password, - UserAgent = UserAgent, - Cookies = data.COOKIES.ToList().Concat(ls.GlobalCookies.ToList()).Select(p => (p.Key, p.Value)).ToArray() - } - : null; + /// + public override async Task Process(LSGlobals ls) + { + var data = ls.BotData; + await base.Process(ls); - var provider = data.Providers.Captcha; + string errorMessage; - if (provider.CheckBalanceBeforeSolving) + var proxy = data.UseProxy && UseProxy + ? new Proxy { - try - { - try - { - data.CaptchaCredit = await provider.GetBalanceAsync(); - data.Logger.Log($"[{provider.ServiceType}] Balance: ${data.CaptchaCredit}"); - - if (data.CaptchaCredit < (decimal)0.002) - { - throw new Exception("The remaining balance is too low!"); - } - } - catch (Exception ex) // This unwraps aggregate exceptions - { - if (ex is AggregateException) - { - throw ex.InnerException; - } - else - { - throw; - } - } - } - catch (BadAuthenticationException ex) - { - data.Logger.Log($"Bad credentials! {ex.Message}", LogColors.Tomato); - return; - } - catch (Exception ex) - { - data.Logger.Log($"An error occurred! {ex.Message}", LogColors.Tomato); - } + Host = data.Proxy.Host, + Port = data.Proxy.Port, + Type = (ProxyType)Enum.Parse(typeof(ProxyType), data.Proxy.Type.ToString()), + Username = data.Proxy.Username, + Password = data.Proxy.Password, } + : null; + + var cookies = data.COOKIES.ToDictionary(cookie => cookie.Key, cookie => cookie.Value); + + foreach (var cookie in ls.GlobalCookies) + { + cookies[cookie.Key] = cookie.Value; + } + + var sessionParams = new SessionParams + { + Proxy = proxy, + UserAgent = UserAgent, + Cookies = cookies + }; + var provider = data.Providers.Captcha; + + if (provider.CheckBalanceBeforeSolving) + { try { try { - var response = await GetResponseAsync(ls, proxy); - - InsertVariable(ls, false, response.Id.ToString(), "CAPTCHAID"); + data.CaptchaCredit = await provider.GetBalanceAsync(); + data.Logger.Log($"[{provider.ServiceType}] Balance: ${data.CaptchaCredit}"); - switch (response) + if (data.CaptchaCredit < (decimal)0.002) { - case StringResponse r: - InsertVariable(ls, false, r.Response, "SOLUTION"); - data.Logger.Log($"Captcha solved successfully! Id: {r.IdString} Solution: {r.Response}", LogColors.GreenYellow); - break; - - case GeeTestResponse r: - InsertVariable(ls, false, r.Challenge, "GT_CHALLENGE"); - InsertVariable(ls, false, r.Validate, "GT_VALIDATE"); - InsertVariable(ls, false, r.SecCode, "GT_SECCODE"); - data.Logger.Log($"Captcha solved successfully! Id: {r.IdString} Challenge: {r.Challenge}\r\nValidate: {r.Validate}\r\nSecCode: {r.SecCode}", LogColors.GreenYellow); - break; + throw new Exception("The remaining balance is too low!"); } - - // Save the captcha id for reporting - data.SetObject("lastCaptchaInfo", new CaptchaInfo { Id = response.IdString, Type = Type }); - - return; } catch (Exception ex) // This unwraps aggregate exceptions { - if (ex is AggregateException) + if (ex is AggregateException { InnerException: not null } aggEx) { - throw ex.InnerException; - } - else - { - throw; + throw aggEx.InnerException; } + + throw; } } - catch (NotSupportedException ex) + catch (BadAuthenticationException ex) { - errorMessage = $"The currently selected service ({provider.ServiceType}) does not support this task! {ex.Message}"; - } - catch (TaskCreationException ex) - { - errorMessage = $"Could not create the captcha task! {ex.Message}"; - } - catch (TaskSolutionException ex) - { - errorMessage = $"Could not solve the captcha! {ex.Message}"; + data.Logger.Log($"Bad credentials! {ex.Message}", LogColors.Tomato); + return; } catch (Exception ex) { - errorMessage = $"An error occurred! {ex.Message}"; - } - - if (!string.IsNullOrEmpty(errorMessage)) - { - data.Logger.Log(errorMessage, LogColors.Tomato); + data.Logger.Log($"An error occurred! {ex.Message}", LogColors.Tomato); } } - private async Task GetResponseAsync(LSGlobals ls, Proxy proxy) + try { - var provider = ls.BotData.Providers.Captcha; - - return Type switch + try { - CaptchaType.TextCaptcha => await provider.SolveTextCaptchaAsync(ReplaceValues(Question, ls), new TextCaptchaOptions - { CaptchaLanguage = Language, CaptchaLanguageGroup = LanguageGroup }), + var response = await GetResponseAsync(ls, sessionParams); - CaptchaType.ImageCaptcha => await provider.SolveImageCaptchaAsync(ReplaceValues(Base64, ls), new ImageCaptchaOptions - { - CaptchaLanguage = Language, - CaptchaLanguageGroup = LanguageGroup, - IsPhrase = IsPhrase, - CaseSensitive = CaseSensitive, - RequiresCalculation = RequiresCalculation, - CharacterSet = CharSet, - MinLength = MinLength, - MaxLength = MaxLength, - TextInstructions = ReplaceValues(TextInstructions, ls) - }), + InsertVariable(ls, false, response.Id, "CAPTCHAID"); - CaptchaType.ReCaptchaV2 => await provider.SolveRecaptchaV2Async(ReplaceValues(SiteKey, ls), ReplaceValues(SiteUrl, ls), - "", false, IsInvisible, proxy), + switch (response) + { + case StringResponse r: + InsertVariable(ls, false, r.Response, "SOLUTION"); + data.Logger.Log($"Captcha solved successfully! Id: {r.Id} Solution: {r.Response}", LogColors.GreenYellow); + break; + + case GeeTestResponse r: + InsertVariable(ls, false, r.Challenge, "GT_CHALLENGE"); + InsertVariable(ls, false, r.Validate, "GT_VALIDATE"); + InsertVariable(ls, false, r.SecCode, "GT_SECCODE"); + data.Logger.Log($"Captcha solved successfully! Id: {r.Id} Challenge: {r.Challenge}\r\nValidate: {r.Validate}\r\nSecCode: {r.SecCode}", LogColors.GreenYellow); + break; + } - CaptchaType.ReCaptchaV3 => await provider.SolveRecaptchaV3Async(ReplaceValues(SiteKey, ls), ReplaceValues(SiteUrl, ls), - ReplaceValues(Action, ls), float.Parse(ReplaceValues(MinScore, ls)), false, proxy), + // Save the captcha id for reporting + data.SetObject("lastCaptchaInfo", new CaptchaInfo { Id = response.Id, Type = Type }); - CaptchaType.FunCaptcha => await provider.SolveFuncaptchaAsync(ReplaceValues(PublicKey, ls), ReplaceValues(ServiceUrl, ls), - ReplaceValues(SiteUrl, ls), NoJS, proxy), + return; + } + catch (Exception ex) // This unwraps aggregate exceptions + { + if (ex is AggregateException { InnerException: not null } aggEx) + { + throw aggEx.InnerException; + } - CaptchaType.HCaptcha => await provider.SolveHCaptchaAsync(ReplaceValues(SiteKey, ls), ReplaceValues(SiteUrl, ls), proxy), + throw; + } + } + catch (NotSupportedException ex) + { + errorMessage = $"The currently selected service ({provider.ServiceType}) does not support this task! {ex.Message}"; + } + catch (TaskCreationException ex) + { + errorMessage = $"Could not create the captcha task! {ex.Message}"; + } + catch (TaskSolutionException ex) + { + errorMessage = $"Could not solve the captcha! {ex.Message}"; + } + catch (Exception ex) + { + errorMessage = $"An error occurred! {ex.Message}"; + } - CaptchaType.Capy => await provider.SolveCapyAsync(ReplaceValues(SiteKey, ls), ReplaceValues(SiteUrl, ls), proxy), + if (!string.IsNullOrEmpty(errorMessage)) + { + data.Logger.Log(errorMessage, LogColors.Tomato); + } + } - CaptchaType.KeyCaptcha => await provider.SolveKeyCaptchaAsync(ReplaceValues(UserId, ls), ReplaceValues(SessionId, ls), - ReplaceValues(WebServerSign1, ls), ReplaceValues(WebServerSign2, ls), ReplaceValues(SiteUrl, ls), proxy), + private async Task GetResponseAsync(LSGlobals ls, SessionParams sessionParams) + { + var provider = ls.BotData.Providers.Captcha; - CaptchaType.GeeTest => await provider.SolveGeeTestAsync(ReplaceValues(GT, ls), ReplaceValues(Challenge, ls), - ReplaceValues(ApiServer, ls), ReplaceValues(SiteUrl, ls), proxy), + return Type switch + { + CaptchaType.TextCaptcha => await provider.SolveTextCaptchaAsync(ReplaceValues(Question, ls), new TextCaptchaOptions + { CaptchaLanguage = Language, CaptchaLanguageGroup = LanguageGroup }), - _ => throw new NotSupportedException(), - }; - } + CaptchaType.ImageCaptcha => await provider.SolveImageCaptchaAsync(ReplaceValues(Base64, ls), new ImageCaptchaOptions + { + CaptchaLanguage = Language, + CaptchaLanguageGroup = LanguageGroup, + IsPhrase = IsPhrase, + CaseSensitive = CaseSensitive, + RequiresCalculation = RequiresCalculation, + CharacterSet = CharSet, + MinLength = MinLength, + MaxLength = MaxLength, + TextInstructions = ReplaceValues(TextInstructions, ls) + }), + + CaptchaType.ReCaptchaV2 => await provider.SolveRecaptchaV2Async( + ReplaceValues(SiteKey, ls), ReplaceValues(SiteUrl, ls), "", false, IsInvisible, sessionParams), + + CaptchaType.ReCaptchaV3 => await provider.SolveRecaptchaV3Async( + ReplaceValues(SiteKey, ls), ReplaceValues(SiteUrl, ls), + ReplaceValues(Action, ls), float.Parse(ReplaceValues(MinScore, ls)), false, sessionParams), + + CaptchaType.FunCaptcha => await provider.SolveFuncaptchaAsync( + ReplaceValues(PublicKey, ls), ReplaceValues(ServiceUrl, ls), + ReplaceValues(SiteUrl, ls), NoJS, data: null, sessionParams), + + CaptchaType.HCaptcha => await provider.SolveHCaptchaAsync( + ReplaceValues(SiteKey, ls), ReplaceValues(SiteUrl, ls), + invisible: false, enterprisePayload: null, sessionParams), + + CaptchaType.Capy => await provider.SolveCapyAsync( + ReplaceValues(SiteKey, ls), ReplaceValues(SiteUrl, ls), sessionParams), + + CaptchaType.KeyCaptcha => await provider.SolveKeyCaptchaAsync( + ReplaceValues(UserId, ls), ReplaceValues(SessionId, ls), + ReplaceValues(WebServerSign1, ls), ReplaceValues(WebServerSign2, ls), + ReplaceValues(SiteUrl, ls), sessionParams), + + CaptchaType.GeeTest => await provider.SolveGeeTestAsync( + ReplaceValues(GT, ls), ReplaceValues(Challenge, ls), + ReplaceValues(ApiServer, ls), ReplaceValues(SiteUrl, ls), sessionParams), + + _ => throw new NotSupportedException( + $"The currently selected service ({provider.ServiceType}) does not support tasks of type {Type}") + }; } } diff --git a/RuriLib/Legacy/LS/BlockReportCaptcha.cs b/RuriLib/Legacy/LS/BlockReportCaptcha.cs index d4f4be1eb..7edce5f35 100644 --- a/RuriLib/Legacy/LS/BlockReportCaptcha.cs +++ b/RuriLib/Legacy/LS/BlockReportCaptcha.cs @@ -6,101 +6,97 @@ using System; using System.Threading.Tasks; -namespace RuriLib.Legacy.Blocks +namespace RuriLib.Legacy.Blocks; + +/// +/// A block that reports a captcha as incorrectly solved. +/// +public class BlockReportCaptcha : BlockBase { + /// The type of captcha to report. + public CaptchaType Type { get; set; } = CaptchaType.ImageCaptcha; + + /// The ID of the captcha to report. + public string CaptchaId { get; set; } = ""; + /// - /// A block that reports a captcha as incorrectly solved. + /// Creates a ReportCaptcha block. /// - public class BlockReportCaptcha : BlockBase + public BlockReportCaptcha() { - /// The type of captcha to report. - public CaptchaType Type { get; set; } = CaptchaType.ImageCaptcha; + Label = "REPORT CAPTCHA"; + } - /// The ID of the captcha to report. - public string CaptchaId { get; set; } = ""; + /// + public override BlockBase FromLS(string line) + { + // Trim the line + var input = line.Trim(); - /// - /// Creates a ReportCaptcha block. - /// - public BlockReportCaptcha() - { - Label = "REPORT CAPTCHA"; - } + // Parse the label + if (input.StartsWith("#")) + Label = LineParser.ParseLabel(ref input); - /// - public override BlockBase FromLS(string line) - { - // Trim the line - var input = line.Trim(); + Type = (CaptchaType)LineParser.ParseEnum(ref input, "TYPE", typeof(CaptchaType)); + CaptchaId = LineParser.ParseLiteral(ref input, "CAPTCHA ID"); + return this; + } - // Parse the label - if (input.StartsWith("#")) - Label = LineParser.ParseLabel(ref input); + /// + public override string ToLS(bool indent = true) + { + return new BlockWriter(GetType(), indent, Disabled) + .Label(Label) + .Token("REPORTCAPTCHA") + .Token(Type) + .Literal(CaptchaId) + .ToString(); + } - Type = (CaptchaType)LineParser.ParseEnum(ref input, "TYPE", typeof(CaptchaType)); - CaptchaId = LineParser.ParseLiteral(ref input, "CAPTCHA ID"); - return this; - } + /// + public override async Task Process(LSGlobals ls) + { + var data = ls.BotData; + await base.Process(ls); - /// - public override string ToLS(bool indent = true) - { - return new BlockWriter(GetType(), indent, Disabled) - .Label(Label) - .Token("REPORTCAPTCHA") - .Token(Type) - .Literal(CaptchaId) - .ToString(); - } + string errorMessage; + var provider = data.Providers.Captcha; - /// - public override async Task Process(LSGlobals ls) + try { - var data = ls.BotData; - await base.Process(ls); - - string errorMessage; - var provider = data.Providers.Captcha; - try { - try - { - var replacedId = ReplaceValues(CaptchaId, ls); - await provider.ReportSolution(long.Parse(replacedId), Type); - data.Logger.Log($"Captcha reported successfully!", LogColors.GreenYellow); - return; - } - catch (Exception ex) // This unwraps aggregate exceptions - { - if (ex is AggregateException) - { - throw ex.InnerException; - } - else - { - throw; - } - } - } - catch (TaskReportException ex) - { - errorMessage = $"The captcha report was not accepted! {ex.Message}"; - } - catch (NotSupportedException ex) - { - errorMessage = $"The currently selected service ({provider.ServiceType}) does not support reports! {ex.Message}"; + var replacedId = ReplaceValues(CaptchaId, ls); + await provider.ReportSolutionAsync(replacedId, Type); + data.Logger?.Log("Captcha reported successfully!", LogColors.GreenYellow); + return; } - catch (Exception ex) + catch (Exception ex) // This unwraps aggregate exceptions { - errorMessage = $"An error occurred! {ex.Message}"; - } - + if (ex is AggregateException { InnerException: not null } aggEx) + { + throw aggEx.InnerException; + } - if (!string.IsNullOrEmpty(errorMessage)) - { - data.Logger.Log(errorMessage, LogColors.Tomato); + throw; } } + catch (TaskReportException ex) + { + errorMessage = $"The captcha report was not accepted! {ex.Message}"; + } + catch (NotSupportedException ex) + { + errorMessage = $"The currently selected service ({provider.ServiceType}) does not support reports! {ex.Message}"; + } + catch (Exception ex) + { + errorMessage = $"An error occurred! {ex.Message}"; + } + + if (!string.IsNullOrEmpty(errorMessage)) + { + data.Logger?.Log(errorMessage, LogColors.Tomato); + } } } diff --git a/RuriLib/Models/Bots/BotData.cs b/RuriLib/Models/Bots/BotData.cs index bdb6ea397..97499de2a 100644 --- a/RuriLib/Models/Bots/BotData.cs +++ b/RuriLib/Models/Bots/BotData.cs @@ -1,5 +1,4 @@ -using AngleSharp.Common; -using AngleSharp.Text; +using AngleSharp.Text; using RuriLib.Helpers; using RuriLib.Logging; using RuriLib.Models.Configs; @@ -10,149 +9,152 @@ using System.Linq; using System.Threading; -namespace RuriLib.Models.Bots +namespace RuriLib.Models.Bots; + +public class BotData { - public class BotData - { - public DataLine Line { get; set; } - public Proxy Proxy { get; set; } - public bool UseProxy { get; set; } - - public ConfigSettings ConfigSettings { get; } - public Providers Providers { get; } - public IBotLogger Logger { get; set; } - public Random Random { get; } - public CancellationToken CancellationToken { get; set; } - public AsyncLocker AsyncLocker { get; set; } - public Stepper Stepper { get; set; } - public decimal CaptchaCredit { get; set; } = 0; - public string ExecutionInfo { get; set; } = "IDLE"; - - // Fixed properties - public string STATUS { get; set; } = "NONE"; - public string SOURCE { get; set; } = string.Empty; - public byte[] RAWSOURCE { get; set; } = Array.Empty(); - public string ADDRESS { get; set; } = string.Empty; - public int RESPONSECODE { get; set; } = 0; - public Dictionary COOKIES { get; set; } = new Dictionary(); - public Dictionary HEADERS { get; set; } = new Dictionary(); - public string ERROR { get; set; } = string.Empty; - public int BOTNUM { get; set; } = 0; - - // This dictionary will hold stateful objects like a captcha provider, a TCP client, a selenium webdriver... - private readonly Dictionary objects = new Dictionary(); + public DataLine Line { get; set; } + public Proxy? Proxy { get; set; } + public bool UseProxy { get; set; } + + public ConfigSettings ConfigSettings { get; } + public Providers Providers { get; } + public IBotLogger Logger { get; set; } + public Random Random { get; } + public CancellationToken CancellationToken { get; set; } + public AsyncLocker? AsyncLocker { get; set; } + public Stepper? Stepper { get; set; } + public decimal CaptchaCredit { get; set; } = 0; + public string ExecutionInfo { get; set; } = "IDLE"; + + // Fixed properties + public string STATUS { get; set; } = "NONE"; + public string SOURCE { get; set; } = string.Empty; + public byte[] RAWSOURCE { get; set; } = []; + public string ADDRESS { get; set; } = string.Empty; + public int RESPONSECODE { get; set; } = 0; + public Dictionary COOKIES { get; set; } = new(); + public Dictionary HEADERS { get; set; } = new(); + public string ERROR { get; set; } = string.Empty; + public int BOTNUM { get; set; } = 0; + + // This dictionary will hold stateful objects like a captcha provider, a TCP client, a selenium webdriver... + private readonly Dictionary _objects = new(); - [Obsolete("Do not use this property, it's only here for retro compatibility but it can cause memory leaks." + - " Use the SetObject and TryGetObject methods instead!")] - public Dictionary Objects => objects; + [Obsolete("Do not use this property, it's only here for retro compatibility but it can cause memory leaks." + + " Use the SetObject and TryGetObject methods instead!")] + public Dictionary Objects => _objects; - // This list will hold the names of all variables that are marked for capture - public List MarkedForCapture { get; } = new List(); + // This list will hold the names of all variables that are marked for capture + public List MarkedForCapture { get; } = new List(); - public BotData(Providers providers, ConfigSettings configSettings, IBotLogger logger, - DataLine line, Proxy proxy = null, bool useProxy = false) - { - Providers = providers; - ConfigSettings = configSettings; - Logger = logger; - - // Create a new local RNG seeded with a random seed from the global RNG - // This is needed because when multiple threads try to access the same RNG it stops giving - // random values after a while! - Random = providers.RNG.GetNew(); - - Line = line; - Proxy = proxy; - UseProxy = useProxy; - } + public BotData(Providers providers, ConfigSettings configSettings, IBotLogger logger, + DataLine line, Proxy? proxy = null, bool useProxy = false) + { + Providers = providers; + ConfigSettings = configSettings; + Logger = logger; + + // Create a new local RNG seeded with a random seed from the global RNG + // This is needed because when multiple threads try to access the same RNG it stops giving + // random values after a while! + Random = providers.RNG.GetNew(); + + Line = line; + Proxy = proxy; + UseProxy = useProxy; + } - public void LogVariableAssignment(string name) - => Logger.Log($"Assigned value to variable '{name}'", LogColors.Yellow); + public void LogVariableAssignment(string name) + => Logger.Log($"Assigned value to variable '{name}'", LogColors.Yellow); - public void MarkForCapture(string name) + public void MarkForCapture(string name) + { + if (string.IsNullOrWhiteSpace(name)) { - if (string.IsNullOrWhiteSpace(name)) - throw new ArgumentException("Name cannot be null or empty"); - - if (!MarkedForCapture.Contains(name)) - { - MarkedForCapture.Add(name); - Logger.Log($"Variable '{name}' marked for capture", LogColors.Tomato); - } + throw new ArgumentException("Name cannot be null or empty"); } - public void UnmarkCapture(string name) + if (MarkedForCapture.Contains(name)) { - if (string.IsNullOrWhiteSpace(name)) - throw new ArgumentException("Name cannot be null or empty"); - - if (MarkedForCapture.Contains(name)) - { - MarkedForCapture.Remove(name); - Logger.Log($"Variable '{name}' removed from capture", LogColors.Yellow); - } + return; } + + MarkedForCapture.Add(name); + Logger.Log($"Variable '{name}' marked for capture", LogColors.Tomato); + } - public void ExecutingBlock(string label) + public void UnmarkCapture(string name) + { + if (string.IsNullOrWhiteSpace(name)) + throw new ArgumentException("Name cannot be null or empty"); + + if (!MarkedForCapture.Contains(name)) { - ExecutionInfo = $"Executing block {label}"; - - if (Logger != null) - { - Logger.ExecutingBlock = label; - } + return; } + + MarkedForCapture.Remove(name); + Logger.Log($"Variable '{name}' removed from capture", LogColors.Yellow); + } - public void ResetState() + public void ExecutingBlock(string label) + { + ExecutionInfo = $"Executing block {label}"; + + if (Logger != null) { - ExecutionInfo = "Retrying"; - STATUS = "NONE"; - SOURCE = string.Empty; - RAWSOURCE = Array.Empty(); - ADDRESS = string.Empty; - ERROR = string.Empty; - RESPONSECODE = 0; - COOKIES.Clear(); - HEADERS.Clear(); - MarkedForCapture.Clear(); - - // We need to dispose of objects created in each retry, because jobs should - // only dispose of them after the bot has completed its work - DisposeObjectsExcept(new[] { "puppeteer", "puppeteerPage", "puppeteerFrame", "httpClient", "ironPyEngine" }); + Logger.ExecutingBlock = label; } + } - public void SetObject(string name, object obj, bool disposeExisting = true) + public void ResetState() + { + ExecutionInfo = "Retrying"; + STATUS = "NONE"; + SOURCE = string.Empty; + RAWSOURCE = []; + ADDRESS = string.Empty; + ERROR = string.Empty; + RESPONSECODE = 0; + COOKIES.Clear(); + HEADERS.Clear(); + MarkedForCapture.Clear(); + + // We need to dispose of objects created in each retry, because jobs should + // only dispose of them after the bot has completed its work + DisposeObjectsExcept(["puppeteer", "puppeteerPage", "puppeteerFrame", "httpClient", "ironPyEngine"]); + } + + public void SetObject(string name, object obj, bool disposeExisting = true) + { + if (_objects.TryGetValue(name, out var existing)) { - if (objects.ContainsKey(name)) + if (existing is IDisposable d && disposeExisting) { - var existing = objects[name]; - - if (existing is IDisposable d && disposeExisting) - { - d.Dispose(); - } + d.Dispose(); } - - objects[name] = obj; } - public T TryGetObject(string name) where T : class - => objects.ContainsKey(name) && objects[name] is T t ? t : null; + _objects[name] = obj; + } - public void DisposeObjectsExcept(string[] except = null) - { - except ??= Array.Empty(); + public T? TryGetObject(string name) where T : class + => _objects.TryGetValue(name, out var value) && value is T t ? t : null; - foreach (var obj in objects.Where(o => o.Value is IDisposable && !except.Contains(o.Key))) + public void DisposeObjectsExcept(string[]? except = null) + { + except ??= []; + + foreach (var obj in _objects.Where(o => o.Value is IDisposable && !except.Contains(o.Key))) + { + try + { + (obj.Value as IDisposable)?.Dispose(); + } + catch { - try - { - (obj.Value as IDisposable).Dispose(); - } - catch - { - - } + // ignored } } } diff --git a/RuriLib/Models/Jobs/MultiRunJob.cs b/RuriLib/Models/Jobs/MultiRunJob.cs index fa026556b..fc8199a62 100644 --- a/RuriLib/Models/Jobs/MultiRunJob.cs +++ b/RuriLib/Models/Jobs/MultiRunJob.cs @@ -367,7 +367,8 @@ await input.BotData.AsyncLocker.Acquire(typeof(ProxyPool), nameof(ProxyPool.Relo { botData.ExecutingBlock("Reporting bad captcha upon RETRY status"); using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)); - await botData.Providers.Captcha.ReportSolution(long.Parse(lastCaptcha.Id), lastCaptcha.Type, false, cts.Token).ConfigureAwait(false); + await botData.Providers.Captcha.ReportSolutionAsync( + lastCaptcha.Id, lastCaptcha.Type, false, cts.Token).ConfigureAwait(false); botData.ExecutingBlock("Bad captcha reported!"); } catch diff --git a/RuriLib/Models/Settings/CaptchaSettings.cs b/RuriLib/Models/Settings/CaptchaSettings.cs index 692aac209..88722f00f 100644 --- a/RuriLib/Models/Settings/CaptchaSettings.cs +++ b/RuriLib/Models/Settings/CaptchaSettings.cs @@ -1,39 +1,50 @@ using RuriLib.Functions.Captchas; -namespace RuriLib.Models.Settings +namespace RuriLib.Models.Settings; + +public class CaptchaSettings { - public class CaptchaSettings - { - public CaptchaServiceType CurrentService { get; set; } = CaptchaServiceType.TwoCaptcha; - public int TimeoutSeconds { get; set; } = 120; - public int PollingIntervalMilliseconds { get; set; } = 5000; - public bool CheckBalanceBeforeSolving { get; set; } = true; + public CaptchaServiceType CurrentService { get; set; } = CaptchaServiceType.TwoCaptcha; + public int TimeoutSeconds { get; set; } = 120; + public int PollingIntervalMilliseconds { get; set; } = 5000; + public bool CheckBalanceBeforeSolving { get; set; } = true; - public string AntiCaptchaApiKey { get; set; } = ""; - public string AZCaptchaApiKey { get; set; } = ""; - public string CapMonsterHost { get; set; } = "127.0.0.3"; - public int CapMonsterPort { get; set; } = 80; - public string CaptchasDotIoApiKey { get; set; } = ""; - public string CustomTwoCaptchaApiKey { get; set; } = ""; - public string CustomTwoCaptchaDomain { get; set; } = ""; - public bool CustomTwoCaptchaOverrideHostHeader { get; set; } = true; - public int CustomTwoCaptchaPort { get; set; } = 80; - public string DeathByCaptchaUsername { get; set; } = ""; - public string DeathByCaptchaPassword { get; set; } = ""; - public string DeCaptcherUsername { get; set; } = ""; - public string DeCaptcherPassword { get; set; } = ""; - public string ImageTyperzApiKey { get; set; } = ""; - public string RuCaptchaApiKey { get; set; } = ""; - public string SolveCaptchaApiKey { get; set; } = ""; - public string SolveRecaptchaApiKey { get; set; } = ""; - public string TrueCaptchaUsername { get; set; } = ""; - public string TrueCaptchaApiKey { get; set; } = ""; - public string TwoCaptchaApiKey { get; set; } = ""; - public string NineKWApiKey { get; set; } = ""; - public string CustomAntiCaptchaApiKey { get; set; } = ""; - public string CustomAntiCaptchaDomain { get; set; } = ""; - public int CustomAntiCaptchaPort { get; set; } = 80; - public string AnyCaptchaApiKey { get; set; } = ""; - public string CapSolverApiKey { get; set; } = ""; - } + public string AntiCaptchaApiKey { get; set; } = ""; + public string AZCaptchaApiKey { get; set; } = ""; + public string CapMonsterHost { get; set; } = "127.0.0.3"; + public int CapMonsterPort { get; set; } = 80; + public string CaptchasDotIoApiKey { get; set; } = ""; + public string CustomTwoCaptchaApiKey { get; set; } = ""; + public string CustomTwoCaptchaDomain { get; set; } = ""; + public bool CustomTwoCaptchaOverrideHostHeader { get; set; } = true; + public int CustomTwoCaptchaPort { get; set; } = 80; + public string DeathByCaptchaUsername { get; set; } = ""; + public string DeathByCaptchaPassword { get; set; } = ""; + public string CaptchaCoderApiKey { get; set; } = ""; + public string HumanCoderApiKey { get; set; } = ""; + public string ImageTyperzApiKey { get; set; } = ""; + public string RuCaptchaApiKey { get; set; } = ""; + public string SolveCaptchaApiKey { get; set; } = ""; + public string TrueCaptchaUsername { get; set; } = ""; + public string TrueCaptchaApiKey { get; set; } = ""; + public string TwoCaptchaApiKey { get; set; } = ""; + public string NineKWApiKey { get; set; } = ""; + public string CustomAntiCaptchaApiKey { get; set; } = ""; + public string CustomAntiCaptchaDomain { get; set; } = ""; + public int CustomAntiCaptchaPort { get; set; } = 80; + public string CapSolverApiKey { get; set; } = ""; + public string CapMonsterCloudApiKey { get; set; } = ""; + public string MetaBypassTechClientId { get; set; } = ""; + public string MetaBypassTechClientSecret { get; set; } = ""; + public string MetaBypassTechUsername { get; set; } = ""; + public string MetaBypassTechPassword { get; set; } = ""; + public string NextCaptchaApiKey { get; set; } = ""; + public string NoCaptchaAiApiKey { get; set; } = ""; + public string NopechaApiKey { get; set; } = ""; + public string BestCaptchaSolverApiKey { get; set; } = ""; + public string CaptchaAiApiKey { get; set; } = ""; + public string EzCaptchaApiKey { get; set; } = ""; + public string EndCaptchaUsername { get; set; } = ""; + public string EndCaptchaPassword { get; set; } = ""; + public string CapGuruApiKey { get; set; } = ""; } diff --git a/RuriLib/Providers/Captchas/CaptchaSharpProvider.cs b/RuriLib/Providers/Captchas/CaptchaSharpProvider.cs index 6bdaed3df..e4a3fd722 100644 --- a/RuriLib/Providers/Captchas/CaptchaSharpProvider.cs +++ b/RuriLib/Providers/Captchas/CaptchaSharpProvider.cs @@ -1,66 +1,136 @@ -using CaptchaSharp; -using CaptchaSharp.Enums; +using CaptchaSharp.Enums; using CaptchaSharp.Models; using RuriLib.Functions.Captchas; using RuriLib.Services; using System; using System.Threading; using System.Threading.Tasks; +using CaptchaSharp.Models.CaptchaOptions; +using CaptchaSharp.Models.CaptchaResponses; +using CaptchaSharp.Services; -namespace RuriLib.Providers.Captchas -{ - public class CaptchaSharpProvider : ICaptchaProvider - { - private readonly CaptchaService service; - - public CaptchaSharpProvider(RuriLibSettingsService settings) - { - service = CaptchaServiceFactory.GetService(settings.RuriLibSettings.CaptchaSettings); - CheckBalanceBeforeSolving = settings.RuriLibSettings.CaptchaSettings.CheckBalanceBeforeSolving; - ServiceType = settings.RuriLibSettings.CaptchaSettings.CurrentService; - } - - public bool CheckBalanceBeforeSolving { get; } - public CaptchaServiceType ServiceType { get; } - public TimeSpan Timeout { get => service.Timeout; set => service.Timeout = value; } - public CaptchaServiceCapabilities Capabilities => service.Capabilities; - - public Task GetBalanceAsync(CancellationToken cancellationToken = default) - => service.GetBalanceAsync(cancellationToken); - - public Task ReportSolution(long id, CaptchaType type, bool correct = false, CancellationToken cancellationToken = default) - => service.ReportSolution(id, type, correct, cancellationToken); - - public Task SolveCapyAsync(string siteKey, string siteUrl, Proxy proxy = null, CancellationToken cancellationToken = default) - => service.SolveCapyAsync(siteKey, siteUrl, proxy, cancellationToken); +namespace RuriLib.Providers.Captchas; - public Task SolveFuncaptchaAsync(string publicKey, string serviceUrl, string siteUrl, - bool noJS = false, Proxy proxy = null, CancellationToken cancellationToken = default) - => service.SolveFuncaptchaAsync(publicKey, serviceUrl, siteUrl, noJS, proxy, cancellationToken); - - public Task SolveGeeTestAsync(string gt, string challenge, string apiServer, string siteUrl, - Proxy proxy = null, CancellationToken cancellationToken = default) - => service.SolveGeeTestAsync(gt, challenge, apiServer, siteUrl, proxy, cancellationToken); - - public Task SolveHCaptchaAsync(string siteKey, string siteUrl, Proxy proxy = null, CancellationToken cancellationToken = default) - => service.SolveHCaptchaAsync(siteKey, siteUrl, proxy, cancellationToken); - - public Task SolveImageCaptchaAsync(string base64, ImageCaptchaOptions options = null, CancellationToken cancellationToken = default) - => service.SolveImageCaptchaAsync(base64, options, cancellationToken); +public class CaptchaSharpProvider : ICaptchaProvider +{ + private readonly CaptchaService _service; - public Task SolveKeyCaptchaAsync(string userId, string sessionId, string webServerSign1, - string webServerSign2, string siteUrl, Proxy proxy = null, CancellationToken cancellationToken = default) - => service.SolveKeyCaptchaAsync(userId, sessionId, webServerSign1, webServerSign2, siteUrl, proxy, cancellationToken); + public CaptchaSharpProvider(RuriLibSettingsService settings) + { + _service = CaptchaServiceFactory.GetService(settings.RuriLibSettings.CaptchaSettings); + CheckBalanceBeforeSolving = settings.RuriLibSettings.CaptchaSettings.CheckBalanceBeforeSolving; + ServiceType = settings.RuriLibSettings.CaptchaSettings.CurrentService; + } - public Task SolveRecaptchaV2Async(string siteKey, string siteUrl, string sData = "", - bool enterprise = false, bool invisible = false, Proxy proxy = null, CancellationToken cancellationToken = default) - => service.SolveRecaptchaV2Async(siteKey, siteUrl, sData, enterprise, invisible, proxy, cancellationToken); + public bool CheckBalanceBeforeSolving { get; } + public CaptchaServiceType ServiceType { get; } + public TimeSpan Timeout { get => _service.Timeout; set => _service.Timeout = value; } + public CaptchaServiceCapabilities Capabilities => _service.Capabilities; - public Task SolveRecaptchaV3Async(string siteKey, string siteUrl, string action, float minScore, - bool enterprise = false, Proxy proxy = null, CancellationToken cancellationToken = default) - => service.SolveRecaptchaV3Async(siteKey, siteUrl, action, minScore, proxy, cancellationToken); + public Task GetBalanceAsync(CancellationToken cancellationToken = default) + => _service.GetBalanceAsync(cancellationToken); - public Task SolveTextCaptchaAsync(string text, TextCaptchaOptions options = null, CancellationToken cancellationToken = default) - => service.SolveTextCaptchaAsync(text, options, cancellationToken); - } + public Task SolveTextCaptchaAsync( + string text, TextCaptchaOptions? options = null, CancellationToken cancellationToken = default) + => _service.SolveTextCaptchaAsync(text, options, cancellationToken); + + public Task SolveImageCaptchaAsync( + string base64, ImageCaptchaOptions? options = null, CancellationToken cancellationToken = default) + => _service.SolveImageCaptchaAsync(base64, options, cancellationToken); + + public Task SolveRecaptchaV2Async( + string siteKey, string siteUrl, string dataS = "", bool enterprise = false, bool invisible = false, + SessionParams? sessionParams = null, CancellationToken cancellationToken = default) + => _service.SolveRecaptchaV2Async(siteKey, siteUrl, dataS, enterprise, invisible, sessionParams, cancellationToken); + + public Task SolveRecaptchaV3Async( + string siteKey, string siteUrl, string action = "verify", float minScore = 0.4f, + bool enterprise = false, SessionParams? sessionParams = null, CancellationToken cancellationToken = default) + => _service.SolveRecaptchaV3Async(siteKey, siteUrl, action, minScore, enterprise, sessionParams, cancellationToken); + + public Task SolveFuncaptchaAsync( + string publicKey, string serviceUrl, string siteUrl, + bool noJs = false, string? data = null, SessionParams? sessionParams = null, + CancellationToken cancellationToken = default) + => _service.SolveFuncaptchaAsync(publicKey, serviceUrl, siteUrl, noJs, data, sessionParams, cancellationToken); + + public Task SolveHCaptchaAsync( + string siteKey, string siteUrl, bool invisible = false, string? enterprisePayload = null, + SessionParams? sessionParams = null, CancellationToken cancellationToken = default) + => _service.SolveHCaptchaAsync(siteKey, siteUrl, invisible, enterprisePayload, sessionParams, cancellationToken); + + public Task SolveKeyCaptchaAsync( + string userId, string sessionId, string webServerSign1, string webServerSign2, string siteUrl, + SessionParams? sessionParams = null, CancellationToken cancellationToken = default) + => _service.SolveKeyCaptchaAsync(userId, sessionId, webServerSign1, webServerSign2, siteUrl, sessionParams, cancellationToken); + + public Task SolveGeeTestAsync( + string gt, string challenge, string siteUrl, string? apiServer = null, + SessionParams? sessionParams = null, CancellationToken cancellationToken = default) + => _service.SolveGeeTestAsync(gt, challenge, siteUrl, apiServer, sessionParams, cancellationToken); + + public Task SolveCapyAsync( + string siteKey, string siteUrl, SessionParams? sessionParams = null, CancellationToken cancellationToken = default) + => _service.SolveCapyAsync(siteKey, siteUrl, sessionParams, cancellationToken); + + public Task SolveDataDomeAsync( + string siteUrl, string captchaUrl, SessionParams? sessionParams = null, CancellationToken cancellationToken = default) + => _service.SolveDataDomeAsync(siteUrl, captchaUrl, sessionParams, cancellationToken); + + public Task SolveCloudflareTurnstileAsync( + string siteKey, string siteUrl, string? action = null, string? data = null, + string? pageData = null, SessionParams? sessionParams = null, CancellationToken cancellationToken = default) + => _service.SolveCloudflareTurnstileAsync(siteKey, siteUrl, action, data, pageData, sessionParams, cancellationToken); + + public Task SolveLeminCroppedAsync( + string captchaId, string siteUrl, string apiServer = "https://api.leminnow.com/", + string? divId = null, SessionParams? sessionParams = null, CancellationToken cancellationToken = default) + => _service.SolveLeminCroppedAsync(captchaId, siteUrl, apiServer, divId, sessionParams, cancellationToken); + + public Task SolveAmazonWafAsync( + string siteKey, string iv, string context, string siteUrl, + string? challengeScript = null, string? captchaScript = null, + SessionParams? sessionParams = null, CancellationToken cancellationToken = default) + => _service.SolveAmazonWafAsync(siteKey, iv, context, siteUrl, challengeScript, captchaScript, sessionParams, cancellationToken); + + public Task SolveCyberSiAraAsync( + string masterUrlId, string siteUrl, SessionParams? sessionParams = null, CancellationToken cancellationToken = default) + => _service.SolveCyberSiAraAsync(masterUrlId, siteUrl, sessionParams, cancellationToken); + + public Task SolveMtCaptchaAsync( + string siteKey, string siteUrl, SessionParams? sessionParams = null, CancellationToken cancellationToken = default) + => _service.SolveMtCaptchaAsync(siteKey, siteUrl, sessionParams, cancellationToken); + + public Task SolveCutCaptchaAsync( + string miseryKey, string apiKey, string siteUrl, SessionParams? sessionParams = null, CancellationToken cancellationToken = default) + => _service.SolveCutCaptchaAsync(miseryKey, apiKey, siteUrl, sessionParams, cancellationToken); + + public Task SolveFriendlyCaptchaAsync( + string siteKey, string siteUrl, SessionParams? sessionParams = null, CancellationToken cancellationToken = default) + => _service.SolveFriendlyCaptchaAsync(siteKey, siteUrl, sessionParams, cancellationToken); + + public Task SolveAtbCaptchaAsync( + string appId, string apiServer, string siteUrl, SessionParams? sessionParams = null, CancellationToken cancellationToken = default) + => _service.SolveAtbCaptchaAsync(appId, apiServer, siteUrl, sessionParams, cancellationToken); + + public Task SolveTencentCaptchaAsync( + string appId, string siteUrl, SessionParams? sessionParams = null, CancellationToken cancellationToken = default) + => _service.SolveTencentCaptchaAsync(appId, siteUrl, sessionParams, cancellationToken); + + public Task SolveAudioCaptchaAsync( + string base64, AudioCaptchaOptions? options = null, CancellationToken cancellationToken = default) + => _service.SolveAudioCaptchaAsync(base64, options, cancellationToken); + + public Task SolveRecaptchaMobileAsync( + string appPackageName, string appKey, string appAction, SessionParams? sessionParams = null, + CancellationToken cancellationToken = default) + => _service.SolveRecaptchaMobileAsync(appPackageName, appKey, appAction, sessionParams, cancellationToken); + + public Task SolveGeeTestV4Async( + string captchaId, string siteUrl, SessionParams? sessionParams = null, CancellationToken cancellationToken = default) + => _service.SolveGeeTestV4Async(captchaId, siteUrl, sessionParams, cancellationToken); + + public Task ReportSolutionAsync(string captchaId, CaptchaType type, bool correct, + CancellationToken cancellationToken = default) + => _service.ReportSolutionAsync(captchaId, type, correct, cancellationToken); } diff --git a/RuriLib/Providers/Captchas/ICaptchaProvider.cs b/RuriLib/Providers/Captchas/ICaptchaProvider.cs index b84eecccd..afcf66504 100644 --- a/RuriLib/Providers/Captchas/ICaptchaProvider.cs +++ b/RuriLib/Providers/Captchas/ICaptchaProvider.cs @@ -4,29 +4,115 @@ using System; using System.Threading; using System.Threading.Tasks; +using CaptchaSharp.Models.CaptchaOptions; +using CaptchaSharp.Models.CaptchaResponses; +using CaptchaSharp.Services; -namespace RuriLib.Providers.Captchas +namespace RuriLib.Providers.Captchas; + +/// +/// Wrapper for to avoid exposing API keys. +/// +public interface ICaptchaProvider { - /// - /// Wrapper for to avoid exposing API keys. - /// - public interface ICaptchaProvider - { - TimeSpan Timeout { get; set; } - bool CheckBalanceBeforeSolving { get; } - CaptchaServiceType ServiceType { get; } - CaptchaServiceCapabilities Capabilities { get; } - - Task GetBalanceAsync(CancellationToken cancellationToken = default); - Task SolveTextCaptchaAsync(string text, TextCaptchaOptions options = null, CancellationToken cancellationToken = default); - Task SolveImageCaptchaAsync(string base64, ImageCaptchaOptions options = null, CancellationToken cancellationToken = default); - Task SolveRecaptchaV2Async(string siteKey, string siteUrl, string sData = "", bool enterprise = false, bool invisible = false, Proxy proxy = null, CancellationToken cancellationToken = default); - Task SolveRecaptchaV3Async(string siteKey, string siteUrl, string action, float minScore, bool enterprise = false, Proxy proxy = null, CancellationToken cancellationToken = default); - Task SolveFuncaptchaAsync(string publicKey, string serviceUrl, string siteUrl, bool noJS = false, Proxy proxy = null, CancellationToken cancellationToken = default); - Task SolveHCaptchaAsync(string siteKey, string siteUrl, Proxy proxy = null, CancellationToken cancellationToken = default); - Task SolveKeyCaptchaAsync(string userId, string sessionId, string webServerSign1, string webServerSign2, string siteUrl, Proxy proxy = null, CancellationToken cancellationToken = default); - Task SolveGeeTestAsync(string gt, string challenge, string apiServer, string siteUrl, Proxy proxy = null, CancellationToken cancellationToken = default); - Task SolveCapyAsync(string siteKey, string siteUrl, Proxy proxy = null, CancellationToken cancellationToken = default); - Task ReportSolution(long id, CaptchaType type, bool correct = false, CancellationToken cancellationToken = default); - } + TimeSpan Timeout { get; set; } + bool CheckBalanceBeforeSolving { get; } + CaptchaServiceType ServiceType { get; } + CaptchaServiceCapabilities Capabilities { get; } + + Task GetBalanceAsync( + CancellationToken cancellationToken = default); + + Task SolveTextCaptchaAsync( + string text, TextCaptchaOptions? options = null, + CancellationToken cancellationToken = default); + + Task SolveImageCaptchaAsync( + string base64, ImageCaptchaOptions? options = null, + CancellationToken cancellationToken = default); + + Task SolveRecaptchaV2Async( + string siteKey, string siteUrl, string dataS = "", bool enterprise = false, bool invisible = false, + SessionParams? sessionParams = null, CancellationToken cancellationToken = default); + + Task SolveRecaptchaV3Async( + string siteKey, string siteUrl, string action = "verify", float minScore = 0.4f, + bool enterprise = false, SessionParams? sessionParams = null, CancellationToken cancellationToken = default); + + Task SolveFuncaptchaAsync( + string publicKey, string serviceUrl, string siteUrl, + bool noJs = false, string? data = null, SessionParams? sessionParams = null, + CancellationToken cancellationToken = default); + + Task SolveHCaptchaAsync( + string siteKey, string siteUrl, bool invisible = false, string? enterprisePayload = null, + SessionParams? sessionParams = null, CancellationToken cancellationToken = default); + + Task SolveKeyCaptchaAsync( + string userId, string sessionId, string webServerSign1, string webServerSign2, string siteUrl, + SessionParams? sessionParams = null, CancellationToken cancellationToken = default); + + Task SolveGeeTestAsync( + string gt, string challenge, string siteUrl, string? apiServer = null, + SessionParams? sessionParams = null, CancellationToken cancellationToken = default); + + Task SolveCapyAsync( + string siteKey, string siteUrl, SessionParams? sessionParams = null, + CancellationToken cancellationToken = default); + + Task SolveDataDomeAsync( + string siteUrl, string captchaUrl, SessionParams? sessionParams = null, + CancellationToken cancellationToken = default); + + Task SolveCloudflareTurnstileAsync( + string siteKey, string siteUrl, string? action = null, string? data = null, + string? pageData = null, SessionParams? sessionParams = null, CancellationToken cancellationToken = default); + + Task SolveLeminCroppedAsync( + string captchaId, string siteUrl, string apiServer = "https://api.leminnow.com/", + string? divId = null, SessionParams? sessionParams = null, CancellationToken cancellationToken = default); + + Task SolveAmazonWafAsync( + string siteKey, string iv, string context, string siteUrl, + string? challengeScript = null, string? captchaScript = null, + SessionParams? sessionParams = null, CancellationToken cancellationToken = default); + + Task SolveCyberSiAraAsync( + string masterUrlId, string siteUrl, SessionParams? sessionParams = null, + CancellationToken cancellationToken = default); + + Task SolveMtCaptchaAsync( + string siteKey, string siteUrl, SessionParams? sessionParams = null, + CancellationToken cancellationToken = default); + + Task SolveCutCaptchaAsync( + string miseryKey, string apiKey, string siteUrl, SessionParams? sessionParams = null, + CancellationToken cancellationToken = default); + + Task SolveFriendlyCaptchaAsync( + string siteKey, string siteUrl, SessionParams? sessionParams = null, + CancellationToken cancellationToken = default); + + Task SolveAtbCaptchaAsync( + string appId, string apiServer, string siteUrl, SessionParams? sessionParams = null, + CancellationToken cancellationToken = default); + + Task SolveTencentCaptchaAsync( + string appId, string siteUrl, SessionParams? sessionParams = null, + CancellationToken cancellationToken = default); + + Task SolveAudioCaptchaAsync( + string base64, AudioCaptchaOptions? options = null, + CancellationToken cancellationToken = default); + + Task SolveRecaptchaMobileAsync( + string appPackageName, string appKey, string appAction, SessionParams? sessionParams = null, + CancellationToken cancellationToken = default); + + Task SolveGeeTestV4Async( + string captchaId, string siteUrl, + SessionParams? sessionParams = null, CancellationToken cancellationToken = default); + + Task ReportSolutionAsync( + string id, CaptchaType type, bool correct = false, CancellationToken cancellationToken = default); } diff --git a/RuriLib/RuriLib.csproj b/RuriLib/RuriLib.csproj index 2be768eac..25b36fdd5 100644 --- a/RuriLib/RuriLib.csproj +++ b/RuriLib/RuriLib.csproj @@ -3,13 +3,13 @@ net8.0 Ruri + enable - - + diff --git a/openbullet2-web-client/src/app/main/components/rl-settings/rl-settings.component.html b/openbullet2-web-client/src/app/main/components/rl-settings/rl-settings.component.html index 0a2fd8376..832d176e7 100644 --- a/openbullet2-web-client/src/app/main/components/rl-settings/rl-settings.component.html +++ b/openbullet2-web-client/src/app/main/components/rl-settings/rl-settings.component.html @@ -267,22 +267,15 @@

Captchas

placeholder="PASSWORD" /> -
+
- DeCaptcher Username - - Password - CaptchaCoder API Key + + [(ngModel)]="settings.captchaSettings.captchaCoderApiKey" + placeholder="API_KEY" />
@@ -325,7 +318,7 @@

Captchas

placeholder="API_KEY" />
-
+
Captchas.IO API Key Captchas placeholder="API_KEY" />
-
-
- SolveRecaptcha API Key - -
-
TrueCaptcha API Key @@ -389,10 +371,10 @@

Captchas

placeholder="USERNAME" />
-
+
9kw API Key - Captchas placeholder="8080" />
-
+
- AnyCaptcha API Key - CapSolver API Key +
-
+
- CapSolver API Key - CapMonster Cloud API Key + +
+
+
+
+ HumanCoder API Key + +
+
+
+
+ Nopecha API Key + +
+
+
+
+ NoCaptcha AI API Key + +
+
+
+
+ MetaBypass Client ID + + Client Secret + +
+
+ Username + + Password + +
+
+
+
+ CaptchaAIO API Key + +
+
+
+
+ NextCaptcha API Key + +
+
+
+
+ EzCaptcha API Key + +
+
+
+
+ EzCaptcha Username + + Password + +
+
+
+
+ BestCaptchaSolver API Key + +
+
+
+
+ CapGuru API Key +
diff --git a/openbullet2-web-client/src/app/main/components/rl-settings/rl-settings.component.ts b/openbullet2-web-client/src/app/main/components/rl-settings/rl-settings.component.ts index 2d831ee99..8528a251a 100644 --- a/openbullet2-web-client/src/app/main/components/rl-settings/rl-settings.component.ts +++ b/openbullet2-web-client/src/app/main/components/rl-settings/rl-settings.component.ts @@ -52,19 +52,28 @@ export class RlSettingsComponent implements OnInit, DeactivatableComponent { CaptchaServiceType.AntiCaptcha, CaptchaServiceType.CustomTwoCaptcha, CaptchaServiceType.DeathByCaptcha, - CaptchaServiceType.DeCaptcher, + CaptchaServiceType.CaptchaCoder, CaptchaServiceType.ImageTyperz, CaptchaServiceType.CapMonster, CaptchaServiceType.AzCaptcha, - CaptchaServiceType.CaptchasIO, + CaptchaServiceType.CaptchasIo, CaptchaServiceType.RuCaptcha, CaptchaServiceType.SolveCaptcha, - CaptchaServiceType.SolveRecaptcha, CaptchaServiceType.TrueCaptcha, - CaptchaServiceType.NineKW, + CaptchaServiceType.NineKw, CaptchaServiceType.CustomAntiCaptcha, - CaptchaServiceType.AnyCaptcha, CaptchaServiceType.CapSolver, + CaptchaServiceType.CapMonsterCloud, + CaptchaServiceType.HumanCoder, + CaptchaServiceType.Nopecha, + CaptchaServiceType.NoCaptchaAi, + CaptchaServiceType.MetaBypassTech, + CaptchaServiceType.CaptchaAi, + CaptchaServiceType.NextCaptcha, + CaptchaServiceType.EzCaptcha, + CaptchaServiceType.EndCaptcha, + CaptchaServiceType.BestCaptchaSolver, + CaptchaServiceType.CapGuru, ]; CaptchaServiceType = CaptchaServiceType; diff --git a/openbullet2-web-client/src/app/main/dtos/settings/rl-settings.dto.ts b/openbullet2-web-client/src/app/main/dtos/settings/rl-settings.dto.ts index 1db3b7d47..9c1028bcf 100644 --- a/openbullet2-web-client/src/app/main/dtos/settings/rl-settings.dto.ts +++ b/openbullet2-web-client/src/app/main/dtos/settings/rl-settings.dto.ts @@ -9,19 +9,28 @@ export enum CaptchaServiceType { AntiCaptcha = 'antiCaptcha', CustomTwoCaptcha = 'customTwoCaptcha', DeathByCaptcha = 'deathByCaptcha', - DeCaptcher = 'deCaptcher', + CaptchaCoder = 'captchaCoder', ImageTyperz = 'imageTyperz', CapMonster = 'capMonster', AzCaptcha = 'azCaptcha', - CaptchasIO = 'captchasIO', + CaptchasIo = 'captchasIo', RuCaptcha = 'ruCaptcha', SolveCaptcha = 'solveCaptcha', - SolveRecaptcha = 'solveRecaptcha', TrueCaptcha = 'trueCaptcha', - NineKW = 'nineKW', + NineKw = 'nineKw', CustomAntiCaptcha = 'customAntiCaptcha', - AnyCaptcha = 'anyCaptcha', CapSolver = 'capSolver', + CapMonsterCloud = 'capMonsterCloud', + HumanCoder = 'humanCoder', + Nopecha = 'nopecha', + NoCaptchaAi = 'noCaptchaAi', + MetaBypassTech = 'metaBypassTech', + CaptchaAi = 'captchaAi', + NextCaptcha = 'nextCaptcha', + EzCaptcha = 'ezCaptcha', + EndCaptcha = 'endCaptcha', + BestCaptchaSolver = 'bestCaptchaSolver', + CapGuru = 'capGuru', } export enum BrowserType { @@ -64,12 +73,11 @@ export interface CaptchaRLSettings { customTwoCaptchaPort: number; deathByCaptchaUsername: string; deathByCaptchaPassword: string; - deCaptcherUsername: string; - deCaptcherPassword: string; + captchaCoderApiKey: string; + humanCoderApiKey: string; imageTyperzApiKey: string; ruCaptchaApiKey: string; solveCaptchaApiKey: string; - solveRecaptchaApiKey: string; trueCaptchaUsername: string; trueCaptchaApiKey: string; twoCaptchaApiKey: string; @@ -77,8 +85,21 @@ export interface CaptchaRLSettings { customAntiCaptchaApiKey: string; customAntiCaptchaDomain: string; customAntiCaptchaPort: number; - anyCaptchaApiKey: string; capSolverApiKey: string; + capMonsterCloudApiKey: string; + metaBypassTechClientId: string; + metaBypassTechClientSecret: string; + metaBypassTechUsername: string; + metaBypassTechPassword: string; + nextCaptchaApiKey: string; + noCaptchaAiApiKey: string; + nopechaApiKey: string; + bestCaptchaSolverApiKey: string; + captchaAiApiKey: string; + ezCaptchaApiKey: string; + endCaptchaUsername: string; + endCaptchaPassword: string; + capGuruApiKey: string; } export interface ProxyRLSettings { From 73714c9fd5acc3daee7f11248f8c4e9cf3a727d8 Mon Sep 17 00:00:00 2001 From: Ruri Date: Sun, 4 Aug 2024 19:48:05 +0200 Subject: [PATCH 04/19] Updated license year --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index b00048188..c37b5b5fd 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 openbullet +Copyright (c) 2024 openbullet Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 64f2b8255036a3a795dfe1e99961193c39f2886d Mon Sep 17 00:00:00 2001 From: Ruri Date: Sun, 4 Aug 2024 19:53:23 +0200 Subject: [PATCH 05/19] Updated readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 04306ca15..eb07d247b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![Logo](https://i.imgur.com/sToEkJC.png) -OpenBullet 2 is a cross platform automation suite powered by .NET core. It allows to perform requests towards a target webapp and offers a lot of tools to work with the results. This software can be used for **scraping** and **parsing data**, automated **pentesting** and much more. +OpenBullet 2 is a cross-platform automation suite powered by .NET. It allows to perform requests towards a target webapp and offers a lot of tools to work with the results. This software can be used for **scraping** and **parsing data**, automated **penetration testing** and much more. ## ⚠️ Disclaimer Performing (D)DoS or credential stuffing attacks on sites you do not have permission to test is **illegal!** The developer will not be held responsible for improper use of this software. From d9b1d1b1b2a143913d9b598fe0c805b33438a193 Mon Sep 17 00:00:00 2001 From: Ruri Date: Sun, 4 Aug 2024 20:03:18 +0200 Subject: [PATCH 06/19] [build] Only take first line from version.txt - Upgraded CaptchaSharp to version 2.0.0 and added new blocks and services - Added try/catch in ReadNetworkUsage due to a macOS issue --- .github/workflows/build-release.yml | 2 +- .github/workflows/build-staging.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index 1a43446d2..d2bf7c137 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -32,7 +32,7 @@ jobs: # Read the version - name: Read version - run: echo "VERSION=$(cat OpenBullet2.Web/version.txt)" >> $GITHUB_ENV + run: echo "VERSION=$(head -n 1 OpenBullet2.Web/version.txt)" >> $GITHUB_ENV # Build using docker - name: Build using docker diff --git a/.github/workflows/build-staging.yml b/.github/workflows/build-staging.yml index 7b07a5db9..c7675097e 100644 --- a/.github/workflows/build-staging.yml +++ b/.github/workflows/build-staging.yml @@ -51,7 +51,7 @@ jobs: # Read the version - name: Read version - run: echo "VERSION=$(cat OpenBullet2.Web/version.txt)" >> $GITHUB_ENV + run: echo "VERSION=$(head -n 1 OpenBullet2.Web/version.txt)" >> $GITHUB_ENV # Build using docker - name: Build using docker From eece1772d7e86f4a8862b25068234528971b17cd Mon Sep 17 00:00:00 2001 From: Ruri Date: Sun, 4 Aug 2024 20:27:24 +0200 Subject: [PATCH 07/19] [build] Fixed version in staging pipeline - Upgraded CaptchaSharp to version 2.0.0 and added new blocks and services - Added try/catch in ReadNetworkUsage due to a macOS issue --- .github/workflows/build-staging.yml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-staging.yml b/.github/workflows/build-staging.yml index c7675097e..eeb898ef0 100644 --- a/.github/workflows/build-staging.yml +++ b/.github/workflows/build-staging.yml @@ -34,13 +34,17 @@ jobs: - name: Get commit number run: echo "COMMIT_NUMBER=$(git rev-list --count HEAD)" >> $GITHUB_ENV - # Append the commit number to version.txt of the web client + # Read the version + - name: Read version + run: echo "VERSION=$(head -n 1 OpenBullet2.Web/version.txt)" >> $GITHUB_ENV + + # Overwrite the contents of version.txt with $VERSION.$COMMIT_NUMBER - name: Append commit number to version.txt - run: echo ".$COMMIT_NUMBER" >> OpenBullet2.Web/version.txt + run: echo "${{ env.VERSION }}.${{ env.COMMIT_NUMBER }}" > OpenBullet2.Web/version.txt - # Append the commit number to version.txt of the native client + # Do the same for the native client - name: Append commit number to version.txt - run: echo ".$COMMIT_NUMBER" >> OpenBullet2.Native/version.txt + run: echo "${{ env.VERSION }}.${{ env.COMMIT_NUMBER }}" > OpenBullet2.Native/version.txt # Get the commit description - name: Get commit description @@ -50,7 +54,7 @@ jobs: echo 'EOF' >> $GITHUB_ENV # Read the version - - name: Read version + - name: Read version again run: echo "VERSION=$(head -n 1 OpenBullet2.Web/version.txt)" >> $GITHUB_ENV # Build using docker From 041f7de6766599e4fba9208b743170bc3e97ee32 Mon Sep 17 00:00:00 2001 From: Ruri Date: Sun, 4 Aug 2024 20:30:01 +0200 Subject: [PATCH 08/19] Do not overwrite releases --- .github/workflows/build-release.yml | 2 +- .github/workflows/build-staging.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index d2bf7c137..368f90d42 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -70,7 +70,7 @@ jobs: file_glob: true release_name: ${{ env.VERSION }} tag: ${{ env.VERSION }} - overwrite: true + overwrite: false prerelease: false make_latest: true # Show ONLY the commit description in the release (without) diff --git a/.github/workflows/build-staging.yml b/.github/workflows/build-staging.yml index eeb898ef0..629fb5f02 100644 --- a/.github/workflows/build-staging.yml +++ b/.github/workflows/build-staging.yml @@ -93,7 +93,7 @@ jobs: file_glob: true release_name: ${{ env.VERSION }} tag: ${{ env.VERSION }} - overwrite: true + overwrite: false prerelease: true make_latest: true # Show ONLY the commit description in the release (without) From 439cf102889f0bec73a9c9d407afe738204f2b0c Mon Sep 17 00:00:00 2001 From: Ruri Date: Sun, 4 Aug 2024 22:35:43 +0200 Subject: [PATCH 09/19] Fixed auto word selection in native winforms RTB --- .../Views/Dialogs/BotLogDialog.xaml.cs | 13 +++++++++++-- .../Views/Pages/Shared/Debugger.xaml.cs | 14 ++++++++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/OpenBullet2.Native/Views/Dialogs/BotLogDialog.xaml.cs b/OpenBullet2.Native/Views/Dialogs/BotLogDialog.xaml.cs index a7c1a8755..d2d034393 100644 --- a/OpenBullet2.Native/Views/Dialogs/BotLogDialog.xaml.cs +++ b/OpenBullet2.Native/Views/Dialogs/BotLogDialog.xaml.cs @@ -24,6 +24,7 @@ public BotLogDialog(IBotLogger logger) logRTB.Font = new System.Drawing.Font("Consolas", 10); logRTB.BackColor = System.Drawing.Color.FromArgb(22, 22, 22); + logRTB.HandleCreated += (_, _) => FixAutoWordSelection(logRTB); if (logger is null) { @@ -45,9 +46,17 @@ public BotLogDialog(IBotLogger logger) } catch { - + // ignored } } + + private void FixAutoWordSelection(System.Windows.Forms.RichTextBox rtb) + { + // Stupid ass workaround because WinForms RichTextBox is broken + // https://stackoverflow.com/questions/3678620/c-sharp-richtextbox-selection-problem + rtb.AutoWordSelection = true; + rtb.AutoWordSelection = false; + } #region Search private void Search(object sender, RoutedEventArgs e) @@ -139,7 +148,7 @@ private void NextMatch(object sender, RoutedEventArgs e) } #endregion } - + public class BotLogDialogViewModel : ViewModelBase { private string searchString = string.Empty; diff --git a/OpenBullet2.Native/Views/Pages/Shared/Debugger.xaml.cs b/OpenBullet2.Native/Views/Pages/Shared/Debugger.xaml.cs index e72f34b92..cc5eecbd3 100644 --- a/OpenBullet2.Native/Views/Pages/Shared/Debugger.xaml.cs +++ b/OpenBullet2.Native/Views/Pages/Shared/Debugger.xaml.cs @@ -30,9 +30,19 @@ public Debugger() logRTB.Font = new System.Drawing.Font("Consolas", 10); logRTB.BackColor = System.Drawing.Color.FromArgb(22, 22, 22); - + logRTB.HandleCreated += (_, _) => FixAutoWordSelection(logRTB); + variablesRTB.Font = new System.Drawing.Font("Consolas", 10); variablesRTB.BackColor = System.Drawing.Color.FromArgb(22, 22, 22); + variablesRTB.HandleCreated += (_, _) => FixAutoWordSelection(variablesRTB); + } + + private void FixAutoWordSelection(System.Windows.Forms.RichTextBox rtb) + { + // Stupid ass workaround because WinForms RichTextBox is broken + // https://stackoverflow.com/questions/3678620/c-sharp-richtextbox-selection-problem + rtb.AutoWordSelection = true; + rtb.AutoWordSelection = false; } private void ShowLog(object sender, RoutedEventArgs e) => tabControl.SelectedIndex = 0; @@ -40,7 +50,7 @@ public Debugger() private void ShowHTML(object sender, RoutedEventArgs e) => tabControl.SelectedIndex = 2; private async void Start(object sender, RoutedEventArgs e) - { + { if (!vm.PersistLog) { logRTB.Clear(); From 6f309e623b7adec374767dd6b996d9cb0a9d773d Mon Sep 17 00:00:00 2001 From: Ruri Date: Sat, 10 Aug 2024 15:04:47 +0200 Subject: [PATCH 10/19] Removed label from auto block bool params --- .../config-stacker/block-info/block-info.component.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openbullet2-web-client/src/app/main/components/config/config-stacker/block-info/block-info.component.html b/openbullet2-web-client/src/app/main/components/config/config-stacker/block-info/block-info.component.html index e853d238a..9fb61e4cc 100644 --- a/openbullet2-web-client/src/app/main/components/config/config-stacker/block-info/block-info.component.html +++ b/openbullet2-web-client/src/app/main/components/config/config-stacker/block-info/block-info.component.html @@ -67,7 +67,9 @@
- + {{setting.name | pascalcase}} {{setting.type === BlockSettingType.ByteArray ? '(Base 64)' : ''}} Date: Sat, 10 Aug 2024 15:48:38 +0200 Subject: [PATCH 11/19] Added missing timeouts to NoProxyClient ProxySettings Partially addresses #814 --- RuriLib/Functions/Tcp/TcpClientFactory.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/RuriLib/Functions/Tcp/TcpClientFactory.cs b/RuriLib/Functions/Tcp/TcpClientFactory.cs index 85f5c7b6a..8e17db243 100644 --- a/RuriLib/Functions/Tcp/TcpClientFactory.cs +++ b/RuriLib/Functions/Tcp/TcpClientFactory.cs @@ -15,18 +15,22 @@ public static class TcpClientFactory /// Creates a socket that talks to the given on the given /// (optionally through a proxy) and returns the . /// - public static Task GetClientAsync(string host, int port, TimeSpan timeout, Proxy proxy = null, + public static Task GetClientAsync(string host, int port, TimeSpan timeout, Proxy? proxy = null, CancellationToken cancellationToken = default) { ProxyClient client; - if (proxy == null) + if (proxy is null) { - client = new NoProxyClient(new ProxySettings()); + client = new NoProxyClient(new ProxySettings + { + ConnectTimeout = timeout, + ReadWriteTimeOut = timeout + }); } else { - var settings = new ProxySettings() + var settings = new ProxySettings { Host = proxy.Host, Port = proxy.Port, From 97c4fc1b18cf6443bccf7179712150f1f8562489 Mon Sep 17 00:00:00 2001 From: Ruri Date: Mon, 12 Aug 2024 19:49:09 +0200 Subject: [PATCH 12/19] Removed CapSolver support upon written request from the service --- OpenBullet2.Native/ViewModels/RLSettingsViewModel.cs | 12 +----------- OpenBullet2.Native/Views/Pages/RLSettings.xaml | 4 +--- RuriLib/Functions/Captchas/CaptchaServiceFactory.cs | 3 ++- RuriLib/Models/Settings/CaptchaSettings.cs | 1 - .../rl-settings/rl-settings.component.html | 8 +------- .../src/app/main/dtos/settings/rl-settings.dto.ts | 1 - 6 files changed, 5 insertions(+), 24 deletions(-) diff --git a/OpenBullet2.Native/ViewModels/RLSettingsViewModel.cs b/OpenBullet2.Native/ViewModels/RLSettingsViewModel.cs index e473c8a14..de499c8da 100644 --- a/OpenBullet2.Native/ViewModels/RLSettingsViewModel.cs +++ b/OpenBullet2.Native/ViewModels/RLSettingsViewModel.cs @@ -414,17 +414,7 @@ public int CustomAntiCaptchaPort OnPropertyChanged(); } } - - public string CapSolverApiKey - { - get => Captcha.CapSolverApiKey; - set - { - Captcha.CapSolverApiKey = value; - OnPropertyChanged(); - } - } - + public string CapMonsterCloudApiKey { get => Captcha.CapMonsterCloudApiKey; diff --git a/OpenBullet2.Native/Views/Pages/RLSettings.xaml b/OpenBullet2.Native/Views/Pages/RLSettings.xaml index 812aa97a0..b86133f7b 100644 --- a/OpenBullet2.Native/Views/Pages/RLSettings.xaml +++ b/OpenBullet2.Native/Views/Pages/RLSettings.xaml @@ -342,9 +342,7 @@ - - + CapSolver itself explicitly asked to be removed from the software. Please choose another service. diff --git a/RuriLib/Functions/Captchas/CaptchaServiceFactory.cs b/RuriLib/Functions/Captchas/CaptchaServiceFactory.cs index 5d603464a..195905b5a 100644 --- a/RuriLib/Functions/Captchas/CaptchaServiceFactory.cs +++ b/RuriLib/Functions/Captchas/CaptchaServiceFactory.cs @@ -31,7 +31,8 @@ public static CaptchaService GetService(CaptchaSettings settings) CaptchaServiceType.NineKw => new NineKwService(settings.NineKWApiKey), CaptchaServiceType.CustomAntiCaptcha => new CustomAntiCaptchaService(settings.CustomAntiCaptchaApiKey, GetUri(settings.CustomAntiCaptchaDomain, settings.CustomAntiCaptchaPort)), - CaptchaServiceType.CapSolver => new CapSolverService(settings.CapSolverApiKey), + CaptchaServiceType.CapSolver => throw new NotSupportedException( + "CapSolver itself explicitly asked to be removed from the software. Please choose another service."), CaptchaServiceType.CapMonsterCloud => new CapMonsterCloudService(settings.CapMonsterCloudApiKey), CaptchaServiceType.HumanCoder => new HumanCoderService(settings.HumanCoderApiKey), CaptchaServiceType.Nopecha => new NopechaService(settings.NopechaApiKey), diff --git a/RuriLib/Models/Settings/CaptchaSettings.cs b/RuriLib/Models/Settings/CaptchaSettings.cs index 88722f00f..687fca6ae 100644 --- a/RuriLib/Models/Settings/CaptchaSettings.cs +++ b/RuriLib/Models/Settings/CaptchaSettings.cs @@ -32,7 +32,6 @@ public class CaptchaSettings public string CustomAntiCaptchaApiKey { get; set; } = ""; public string CustomAntiCaptchaDomain { get; set; } = ""; public int CustomAntiCaptchaPort { get; set; } = 80; - public string CapSolverApiKey { get; set; } = ""; public string CapMonsterCloudApiKey { get; set; } = ""; public string MetaBypassTechClientId { get; set; } = ""; public string MetaBypassTechClientSecret { get; set; } = ""; diff --git a/openbullet2-web-client/src/app/main/components/rl-settings/rl-settings.component.html b/openbullet2-web-client/src/app/main/components/rl-settings/rl-settings.component.html index 832d176e7..3538a7c5d 100644 --- a/openbullet2-web-client/src/app/main/components/rl-settings/rl-settings.component.html +++ b/openbullet2-web-client/src/app/main/components/rl-settings/rl-settings.component.html @@ -411,13 +411,7 @@

Captchas

- CapSolver API Key - + CapSolver itself explicitly asked to be removed from the software. Please choose another service.
diff --git a/openbullet2-web-client/src/app/main/dtos/settings/rl-settings.dto.ts b/openbullet2-web-client/src/app/main/dtos/settings/rl-settings.dto.ts index 9c1028bcf..03f86f811 100644 --- a/openbullet2-web-client/src/app/main/dtos/settings/rl-settings.dto.ts +++ b/openbullet2-web-client/src/app/main/dtos/settings/rl-settings.dto.ts @@ -85,7 +85,6 @@ export interface CaptchaRLSettings { customAntiCaptchaApiKey: string; customAntiCaptchaDomain: string; customAntiCaptchaPort: number; - capSolverApiKey: string; capMonsterCloudApiKey: string; metaBypassTechClientId: string; metaBypassTechClientSecret: string; From cd07dad2f5d6ae170a7b3046eed9ca987ff1d370 Mon Sep 17 00:00:00 2001 From: Ruri Date: Mon, 12 Aug 2024 23:17:54 +0200 Subject: [PATCH 13/19] [build] New staging version - Fixed auto word selection in native winforms RTB - Removed label from auto block bool params - Fixed hardcoded timeout when connecting with RL HTTP without a proxy - Removed CapSolver support - Upgraded CaptchaSharp to 2.1.0 - Added AYCD AutoSolve support - Added block to Solves a Cloudflare Challenge page --- .../ViewModels/RLSettingsViewModel.cs | 10 +++++++++ .../Views/Pages/RLSettings.xaml | 11 ++++++++++ RuriLib/Blocks/Captchas/Methods.cs | 22 +++++++++++++++++-- .../Captchas/CaptchaServiceFactory.cs | 1 + .../Functions/Captchas/CaptchaServiceType.cs | 3 +++ RuriLib/Models/Settings/CaptchaSettings.cs | 1 + .../Captchas/CaptchaSharpProvider.cs | 4 ++++ .../Providers/Captchas/ICaptchaProvider.cs | 4 ++++ RuriLib/RuriLib.csproj | 2 +- .../rl-settings/rl-settings.component.html | 11 ++++++++++ .../rl-settings/rl-settings.component.ts | 1 + .../app/main/dtos/settings/rl-settings.dto.ts | 2 ++ 12 files changed, 69 insertions(+), 3 deletions(-) diff --git a/OpenBullet2.Native/ViewModels/RLSettingsViewModel.cs b/OpenBullet2.Native/ViewModels/RLSettingsViewModel.cs index de499c8da..ba1fb5ab8 100644 --- a/OpenBullet2.Native/ViewModels/RLSettingsViewModel.cs +++ b/OpenBullet2.Native/ViewModels/RLSettingsViewModel.cs @@ -554,6 +554,16 @@ public string CapGuruApiKey OnPropertyChanged(); } } + + public string AycdApiKey + { + get => Captcha.AycdApiKey; + set + { + Captcha.AycdApiKey = value; + OnPropertyChanged(); + } + } public string PuppeteerChromeBinaryLocation { diff --git a/OpenBullet2.Native/Views/Pages/RLSettings.xaml b/OpenBullet2.Native/Views/Pages/RLSettings.xaml index b86133f7b..f7d5cc223 100644 --- a/OpenBullet2.Native/Views/Pages/RLSettings.xaml +++ b/OpenBullet2.Native/Views/Pages/RLSettings.xaml @@ -487,6 +487,17 @@ + + + + + + + + + +
+
+
+ AYCD API Key + +
+