diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..89541e5 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,353 @@ +[*.cs] + +#Core editorconfig formatting - indentation + +#use soft tabs (spaces) for indentation +indent_style = space + +#Formatting - indentation options + +#indent switch case contents. +csharp_indent_case_contents = true +#labels are placed at the same indent as the current context +csharp_indent_labels = no_change +#indent switch labels +csharp_indent_switch_labels = true + +#Formatting - new line options + +#place catch statements on a new line +csharp_new_line_before_catch = true +#place else statements on a new line +csharp_new_line_before_else = true +#require finally statements to be on a new line after the closing brace +csharp_new_line_before_finally = true +#require members of anonymous types to be on separate lines +csharp_new_line_before_members_in_anonymous_types = true +#require members of object intializers to be on separate lines +csharp_new_line_before_members_in_object_initializers = false +#require braces to be on a new line for object_collection_array_initializers, accessors, types, control_blocks, lambdas, methods, anonymous_types, and properties (also known as "Allman" style) + +#Formatting - organize using options + +#do not place System.* using directives before other using directives + +#Formatting - spacing options + +#require NO space between a cast and the value +csharp_space_after_cast = false +#require a space before the colon for bases or interfaces in a type declaration +csharp_space_after_colon_in_inheritance_clause = true +#require a space after a keyword in a control flow statement such as a for loop +csharp_space_after_keywords_in_control_flow_statements = true +#require a space before the colon for bases or interfaces in a type declaration +csharp_space_before_colon_in_inheritance_clause = true +#remove space within empty argument list parentheses +csharp_space_between_method_call_empty_parameter_list_parentheses = false +#remove space between method call name and opening parenthesis +csharp_space_between_method_call_name_and_opening_parenthesis = false +#do not place space characters after the opening parenthesis and before the closing parenthesis of a method call +csharp_space_between_method_call_parameter_list_parentheses = false +#remove space within empty parameter list parentheses for a method declaration +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +#place a space character after the opening parenthesis and before the closing parenthesis of a method declaration parameter list. +csharp_space_between_method_declaration_parameter_list_parentheses = false + +#Formatting - wrapping options + +#leave code block on single line +csharp_preserve_single_line_blocks = true +#leave statements and member declarations on the same line +csharp_preserve_single_line_statements = true + +#Style - Code block preferences + +#always prefer curly braces if allowed +csharp_prefer_braces = true:suggestion + +#Style - expression bodied member options + +#prefer expression-bodied members for accessors +csharp_style_expression_bodied_accessors = true:suggestion +#prefer block bodies for constructors +csharp_style_expression_bodied_constructors = false:suggestion +#prefer expression-bodied members for methods +csharp_style_expression_bodied_methods = true:suggestion +#prefer expression-bodied members for properties +csharp_style_expression_bodied_properties = true:suggestion + +#Style - expression level options + +#prefer out variables to be declared inline in the argument list of a method call when possible +csharp_style_inlined_variable_declaration = true:suggestion +#prefer the language keyword for member access expressions, instead of the type name, for types that have a keyword to represent them +dotnet_style_predefined_type_for_member_access = true:suggestion + +#Style - Expression-level preferences + +#prefer default over default(T) +csharp_prefer_simple_default_expression = true:suggestion +#prefer objects to be initialized using object initializers when possible +dotnet_style_object_initializer = true:suggestion +#prefer inferred anonymous type member names +dotnet_style_prefer_inferred_anonymous_type_member_names = false:suggestion +#prefer inferred tuple element names +dotnet_style_prefer_inferred_tuple_names = true:suggestion + +#Style - implicit and explicit types + +#prefer var over explicit type in all cases, unless overridden by another code style rule +csharp_style_var_elsewhere = true:suggestion +#prefer var is used to declare variables with built-in system types such as int +csharp_style_var_for_built_in_types = true:suggestion +#prefer var when the type is already mentioned on the right-hand side of a declaration expression +csharp_style_var_when_type_is_apparent = true:suggestion + +#Style - language keyword and framework type options + +#prefer the language keyword for local variables, method parameters, and class members, instead of the type name, for types that have a keyword to represent them +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion + +#Style - Miscellaneous preferences + +#prefer anonymous functions over local functions +csharp_style_pattern_local_over_anonymous_function = false:suggestion + +#Style - modifier options + +#prefer accessibility modifiers to be declared except for public interface members. This will currently not differ from always and will act as future proofing for if C# adds default interface methods. +dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion + +#Style - Modifier preferences + +#when this rule is set to a list of modifiers, prefer the specified ordering. +csharp_preferred_modifier_order = public, private, protected, internal, file, new, static, abstract, virtual, sealed, readonly, override, extern, unsafe, volatile, async, required:suggestion + +#Style - qualification options + +#prefer events not to be prefaced with this. or Me. in Visual Basic +dotnet_style_qualification_for_event = false:suggestion +#prefer fields not to be prefaced with this. or Me. in Visual Basic +dotnet_style_qualification_for_field = false:suggestion +#prefer methods not to be prefaced with this. or Me. in Visual Basic +dotnet_style_qualification_for_method = false:suggestion +#prefer properties not to be prefaced with this. or Me. in Visual Basic +dotnet_style_qualification_for_property = false:suggestion +csharp_using_directive_placement = outside_namespace:silent +csharp_prefer_simple_using_statement = true:suggestion +csharp_style_namespace_declarations = file_scoped:suggestion +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_top_level_statements = true:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = false:silent + +# Microsoft .NET properties +csharp_style_prefer_utf8_string_literals = true:suggestion +dotnet_naming_rule.private_constants_rule.import_to_resharper = True +dotnet_naming_rule.private_constants_rule.resharper_description = Constant fields (private) +dotnet_naming_rule.private_constants_rule.resharper_guid = 236f7aa5-7b06-43ca-bf2a-9b31bfcff09a +dotnet_naming_rule.private_constants_rule.severity = warning +dotnet_naming_rule.private_constants_rule.style = upper_camel_case_style +dotnet_naming_rule.private_constants_rule.symbols = private_constants_symbols +dotnet_naming_rule.private_instance_fields_rule.import_to_resharper = True +dotnet_naming_rule.private_instance_fields_rule.resharper_description = Instance fields (private) +dotnet_naming_rule.private_instance_fields_rule.resharper_guid = 4a98fdf6-7d98-4f5a-afeb-ea44ad98c70c +dotnet_naming_rule.private_instance_fields_rule.severity = warning +dotnet_naming_rule.private_instance_fields_rule.style = lower_camel_case_style +dotnet_naming_rule.private_instance_fields_rule.symbols = private_instance_fields_symbols +dotnet_naming_rule.private_static_fields_rule.import_to_resharper = True +dotnet_naming_rule.private_static_fields_rule.resharper_description = Static fields (private) +dotnet_naming_rule.private_static_fields_rule.resharper_guid = f9fce829-e6f4-4cb2-80f1-5497c44f51df +dotnet_naming_rule.private_static_fields_rule.severity = warning +dotnet_naming_rule.private_static_fields_rule.style = lower_camel_case_style +dotnet_naming_rule.private_static_fields_rule.symbols = private_static_fields_symbols +dotnet_naming_rule.private_static_readonly_rule.import_to_resharper = True +dotnet_naming_rule.private_static_readonly_rule.resharper_description = Static readonly fields (private) +dotnet_naming_rule.private_static_readonly_rule.resharper_guid = 15b5b1f1-457c-4ca6-b278-5615aedc07d3 +dotnet_naming_rule.private_static_readonly_rule.severity = warning +dotnet_naming_rule.private_static_readonly_rule.style = upper_camel_case_style +dotnet_naming_rule.private_static_readonly_rule.symbols = private_static_readonly_symbols +dotnet_naming_rule.unity_serialized_field_rule.import_to_resharper = True +dotnet_naming_rule.unity_serialized_field_rule.resharper_description = Unity serialized field +dotnet_naming_rule.unity_serialized_field_rule.resharper_guid = 5f0fdb63-c892-4d2c-9324-15c80b22a7ef +dotnet_naming_rule.unity_serialized_field_rule.severity = warning +dotnet_naming_rule.unity_serialized_field_rule.style = lower_camel_case_style +dotnet_naming_rule.unity_serialized_field_rule.symbols = unity_serialized_field_symbols +dotnet_naming_style.lower_camel_case_style.capitalization = camel_case +dotnet_naming_style.upper_camel_case_style.capitalization = pascal_case +dotnet_naming_symbols.private_constants_symbols.applicable_accessibilities = private +dotnet_naming_symbols.private_constants_symbols.applicable_kinds = field +dotnet_naming_symbols.private_constants_symbols.required_modifiers = const +dotnet_naming_symbols.private_constants_symbols.resharper_applicable_kinds = constant_field +dotnet_naming_symbols.private_constants_symbols.resharper_required_modifiers = any +dotnet_naming_symbols.private_instance_fields_symbols.applicable_accessibilities = private +dotnet_naming_symbols.private_instance_fields_symbols.applicable_kinds = field +dotnet_naming_symbols.private_instance_fields_symbols.resharper_applicable_kinds = field, readonly_field +dotnet_naming_symbols.private_instance_fields_symbols.resharper_required_modifiers = instance +dotnet_naming_symbols.private_static_fields_symbols.applicable_accessibilities = private +dotnet_naming_symbols.private_static_fields_symbols.applicable_kinds = field +dotnet_naming_symbols.private_static_fields_symbols.required_modifiers = static +dotnet_naming_symbols.private_static_fields_symbols.resharper_applicable_kinds = field +dotnet_naming_symbols.private_static_fields_symbols.resharper_required_modifiers = static +dotnet_naming_symbols.private_static_readonly_symbols.applicable_accessibilities = private +dotnet_naming_symbols.private_static_readonly_symbols.applicable_kinds = field +dotnet_naming_symbols.private_static_readonly_symbols.required_modifiers = readonly, static +dotnet_naming_symbols.private_static_readonly_symbols.resharper_applicable_kinds = readonly_field +dotnet_naming_symbols.private_static_readonly_symbols.resharper_required_modifiers = static +dotnet_naming_symbols.unity_serialized_field_symbols.applicable_accessibilities = * +dotnet_naming_symbols.unity_serialized_field_symbols.applicable_kinds = +dotnet_naming_symbols.unity_serialized_field_symbols.resharper_applicable_kinds = unity_serialised_field +dotnet_naming_symbols.unity_serialized_field_symbols.resharper_required_modifiers = instance +dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:none +dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none + +# ReSharper properties +resharper_autodetect_indent_settings = true +resharper_braces_for_for = not_required +resharper_braces_for_foreach = not_required +resharper_braces_for_ifelse = not_required_for_both +resharper_braces_for_while = not_required +resharper_braces_redundant = true +resharper_csharp_insert_final_newline = true +resharper_csharp_keep_existing_enum_arrangement = false +resharper_formatter_off_tag = @formatter:off +resharper_formatter_on_tag = @formatter:on +resharper_formatter_tags_enabled = true +resharper_keep_existing_declaration_block_arrangement = false +resharper_keep_existing_embedded_block_arrangement = false +resharper_method_or_operator_body = block_body +resharper_use_heuristics_for_body_style = true +resharper_use_indent_from_vs = false +resharper_xmldoc_indent_child_elements = RemoveIndent +resharper_xmldoc_indent_text = RemoveIndent + +# ReSharper inspection severities +resharper_arrange_constructor_or_destructor_body_highlighting = none +resharper_arrange_method_or_operator_body_highlighting = none +resharper_arrange_namespace_body_highlighting = hint +resharper_arrange_redundant_parentheses_highlighting = hint +resharper_arrange_this_qualifier_highlighting = hint +resharper_arrange_type_member_modifiers_highlighting = hint +resharper_arrange_type_modifiers_highlighting = hint +resharper_built_in_type_reference_style_for_member_access_highlighting = hint +resharper_built_in_type_reference_style_highlighting = hint +resharper_enforce_do_while_statement_braces_highlighting = none +resharper_enforce_fixed_statement_braces_highlighting = none +resharper_enforce_foreach_statement_braces_highlighting = none +resharper_enforce_for_statement_braces_highlighting = none +resharper_enforce_if_statement_braces_highlighting = none +resharper_enforce_lock_statement_braces_highlighting = none +resharper_enforce_using_statement_braces_highlighting = none +resharper_enforce_while_statement_braces_highlighting = none +resharper_redundant_base_qualifier_highlighting = warning +resharper_remove_redundant_braces_highlighting = none +resharper_suggest_var_or_type_built_in_types_highlighting = hint +resharper_suggest_var_or_type_elsewhere_highlighting = hint +resharper_suggest_var_or_type_simple_types_highlighting = hint +resharper_web_config_module_not_resolved_highlighting = warning +resharper_web_config_type_not_resolved_highlighting = warning +resharper_web_config_wrong_module_highlighting = warning + +[*.{cs,vb}] +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case +dotnet_style_operator_placement_when_wrapping = beginning_of_line +tab_width = 4 +indent_size = 4 +end_of_line = crlf +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = false:suggestion +dotnet_style_namespace_match_folder = true:suggestion +dotnet_style_readonly_field = true:suggestion +dotnet_style_qualification_for_field = false:suggestion + +dotnet_naming_style.camel_case_leading_underscore.capitalization = camel_case +dotnet_naming_style.camel_case_leading_underscore.required_prefix = _ + +dotnet_naming_symbols.private_fields.applicable_kinds = field +dotnet_naming_symbols.private_fields.applicable_accessibilities = private + +dotnet_naming_rule.private_fields_should_be_camel_case_leading_underscore.severity = warning +dotnet_naming_rule.private_fields_should_be_camel_case_leading_underscore.symbols = private_fields +dotnet_naming_rule.private_fields_should_be_camel_case_leading_underscore.style = camel_case_leading_underscore + +# SonarAnalyzer.CSharp + +# S2094: Remove this empty class, write its code or make it an "interface" +dotnet_diagnostic.s2094.severity = none + +# S1075: Refactor your code not to use hardcoded absolute paths or URIs. +dotnet_diagnostic.s1075.severity = none + +[*] +charset = utf-8 +end_of_line = crlf +trim_trailing_whitespace = false +insert_final_newline = true +indent_style = space +indent_size = 4 + +[{*.har,*.jsb2,*.jsb3,*.json,*.jsonc,*.postman_collection,*.postman_collection.json,*.postman_environment,*.postman_environment.json,.babelrc,.eslintrc,.prettierrc,.stylelintrc,bowerrc,jest.config}] +indent_style = space +indent_size = 2 + +[*.scss] +indent_style = space +indent_size = 2 + +[*.{appxmanifest,asax,ascx,aspx,axaml,build,c,c++,c++m,cc,ccm,cginc,compute,cp,cpp,cppm,cs,cshtml,cu,cuh,cxx,cxxm,dtd,fs,fsi,fsscript,fsx,fx,fxh,h,hh,hlsl,hlsli,hlslinc,hpp,hxx,inc,inl,ino,ipp,ixx,master,ml,mli,mpp,mq4,mq5,mqh,mxx,nuspec,paml,razor,resw,resx,shader,skin,tpp,usf,ush,uxml,vb,xaml,xamlx,xoml,xsd}] +indent_style = space +indent_size = 4 +tab_width = 4 diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml new file mode 100644 index 0000000..227a586 --- /dev/null +++ b/.github/workflows/publish.yaml @@ -0,0 +1,28 @@ +name: .NET Build and Publish Nuget Package + +on: + push: + tags: + - "v[0-9]+.[0-9]+.[0-9]+" + +defaults: + run: + working-directory: src + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Setup .NET + uses: actions/setup-dotnet@v2 + with: + dotnet-version: 8.0.x + + # Don't override the version of the package, trust the version in the project file + - name: Create Nuget Package + run: dotnet pack --output nupkgs --configuration Release + + - name: Upload Nuget Package + run: dotnet nuget push nupkgs/*.nupkg -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json diff --git a/CaptchaSharp.Services.More/AnyCaptchaService.cs b/CaptchaSharp.Services.More/AnyCaptchaService.cs deleted file mode 100644 index d5a7cf4..0000000 --- a/CaptchaSharp.Services.More/AnyCaptchaService.cs +++ /dev/null @@ -1,23 +0,0 @@ -using CaptchaSharp.Enums; -using System; -using System.Net.Http; - -namespace CaptchaSharp.Services.More -{ - /// The service provided by https://anycaptcha.com/ - public class AnyCaptchaService : CustomAntiCaptchaService - { - /// Initializes a using the given and - /// . If is null, a default one will be created. - public AnyCaptchaService(string apiKey, HttpClient httpClient = null) - : base(apiKey, new Uri("https://api.anycaptcha.com"), httpClient) - { - SupportedCaptchaTypes = - CaptchaType.ImageCaptcha | - CaptchaType.ReCaptchaV2 | - CaptchaType.ReCaptchaV3 | - CaptchaType.FunCaptcha | - CaptchaType.HCaptcha; - } - } -} diff --git a/CaptchaSharp.Services.More/AzCaptchaService.cs b/CaptchaSharp.Services.More/AzCaptchaService.cs deleted file mode 100644 index 4c2252e..0000000 --- a/CaptchaSharp.Services.More/AzCaptchaService.cs +++ /dev/null @@ -1,21 +0,0 @@ -using CaptchaSharp.Enums; -using System; -using System.Net.Http; - -namespace CaptchaSharp.Services.More -{ - /// The service provided by https://azcaptcha.com/ - public class AzCaptchaService : CustomTwoCaptchaService - { - /// Initializes a using the given and - /// . If is null, a default one will be created. - public AzCaptchaService(string apiKey, HttpClient httpClient = null) - : base(apiKey, new Uri("http://azcaptcha.com"), httpClient, false) - { - SupportedCaptchaTypes = - CaptchaType.ImageCaptcha | - CaptchaType.ReCaptchaV2 | - CaptchaType.ReCaptchaV3; - } - } -} diff --git a/CaptchaSharp.Services.More/CaptchaSharp.Services.More.csproj b/CaptchaSharp.Services.More/CaptchaSharp.Services.More.csproj deleted file mode 100644 index 1e11a30..0000000 --- a/CaptchaSharp.Services.More/CaptchaSharp.Services.More.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - netstandard2.0 - Adds additional services to CaptchaSharp. - MIT - Ruri - Ruri - https://github.com/openbullet/CaptchaSharp - Captcha, Solver, Service, API, 2Captcha, TwoCaptcha, AntiCaptcha, Anti-Captcha, DeathByCaptcha, DBC, DeCaptcher, ImageTyperz - https://github.com/openbullet/CaptchaSharp - 1.0.6 - True - - - - - - - diff --git a/CaptchaSharp.Services.More/CaptchasIOService.cs b/CaptchaSharp.Services.More/CaptchasIOService.cs deleted file mode 100644 index c94bed7..0000000 --- a/CaptchaSharp.Services.More/CaptchasIOService.cs +++ /dev/null @@ -1,21 +0,0 @@ -using CaptchaSharp.Enums; -using System; -using System.Net.Http; - -namespace CaptchaSharp.Services.More -{ - /// The service provided by https://captchas.io/ - public class CaptchasIOService : CustomTwoCaptchaService - { - /// Initializes a using the given and - /// . If is null, a default one will be created. - public CaptchasIOService(string apiKey, HttpClient httpClient = null) - : base(apiKey, new Uri("https://api.captchas.io"), httpClient, false) - { - SupportedCaptchaTypes = - CaptchaType.ImageCaptcha | - CaptchaType.ReCaptchaV2 | - CaptchaType.ReCaptchaV3; - } - } -} diff --git a/CaptchaSharp.Services.More/RuCaptchaService.cs b/CaptchaSharp.Services.More/RuCaptchaService.cs deleted file mode 100644 index 183e90b..0000000 --- a/CaptchaSharp.Services.More/RuCaptchaService.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Net.Http; - -namespace CaptchaSharp.Services.More -{ - /// The service provided by https://rucaptcha.com/ - public class RuCaptchaService : CustomTwoCaptchaService - { - /// Initializes a using the given and - /// . If is null, a default one will be created. - public RuCaptchaService(string apiKey, HttpClient httpClient = null) - : base(apiKey, new Uri("http://rucaptcha.com"), httpClient) { } - } -} diff --git a/CaptchaSharp.Services.More/SolveCaptchaService.cs b/CaptchaSharp.Services.More/SolveCaptchaService.cs deleted file mode 100644 index 9ff9644..0000000 --- a/CaptchaSharp.Services.More/SolveCaptchaService.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using CaptchaSharp.Enums; -using System.Net.Http; - -namespace CaptchaSharp.Services.More -{ - /// The service provided by https://solvecaptcha.com/ - public class SolveCaptchaService : CustomTwoCaptchaService - { - /// Initializes a using the given and - /// . If is null, a default one will be created. - public SolveCaptchaService(string apiKey, HttpClient httpClient = null) - : base(apiKey, new Uri("http://api.solvecaptcha.com"), httpClient, false) - { - SupportedCaptchaTypes = - CaptchaType.TextCaptcha | - CaptchaType.ImageCaptcha | - CaptchaType.ReCaptchaV2 | - CaptchaType.FunCaptcha | - CaptchaType.KeyCaptcha; - } - } -} diff --git a/CaptchaSharp.Services.More/SolveRecaptchaService.cs b/CaptchaSharp.Services.More/SolveRecaptchaService.cs deleted file mode 100644 index 18e27fd..0000000 --- a/CaptchaSharp.Services.More/SolveRecaptchaService.cs +++ /dev/null @@ -1,109 +0,0 @@ -using CaptchaSharp.Enums; -using CaptchaSharp.Exceptions; -using CaptchaSharp.Models; -using System; -using System.Globalization; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; - -namespace CaptchaSharp.Services.More -{ - /// The service provided by https://solverecaptcha.com/ - public class SolveRecaptchaService : CustomTwoCaptchaService - { - /// Initializes a using the given and - /// . If is null, a default one will be created. - public SolveRecaptchaService(string apiKey, HttpClient httpClient = null) - : base(apiKey, new Uri("http://api.solverecaptcha.com"), httpClient) - { - this.httpClient.DefaultRequestHeaders.Host = "api.solverecaptcha.com"; - this.httpClient.Timeout = Timeout; - - SupportedCaptchaTypes = - CaptchaType.ReCaptchaV2 | - CaptchaType.ReCaptchaV3; - } - - /// - public async override Task GetBalanceAsync(CancellationToken cancellationToken = default) - { - // There is no balance since this service has a monthly subscription - return await Task.Run(() => 999).ConfigureAwait(false); - } - - /// - public async override Task SolveRecaptchaV2Async - (string siteKey, string siteUrl, string dataS = "", bool enterprise = false, bool invisible = false, - Proxy proxy = null, CancellationToken cancellationToken = default) - { - var response = await httpClient.GetStringAsync - ("", - GetAuthPair() - .Add("sitekey", siteKey) - .Add("pageurl", siteUrl) - .Add("version", invisible ? "invisible" : "v2") - .Add("invisible", Convert.ToInt32(invisible).ToString()) - .Add(ConvertProxy(proxy)), - cancellationToken) - .ConfigureAwait(false); - - if (IsErrorCode(response)) - ThrowException(response); - - return new StringResponse { Id = 0, Response = TakeSecondSlice(response) }; - } - - /// - public async override Task SolveRecaptchaV3Async - (string siteKey, string siteUrl, string action = "verify", float minScore = 0.4F, bool enterprise = false, - Proxy proxy = null, CancellationToken cancellationToken = default) - { - var response = await httpClient.GetStringAsync - ("", - GetAuthPair() - .Add("sitekey", siteKey) - .Add("pageurl", siteUrl) - .Add("action", action) - .Add("min_score", minScore.ToString("0.0", CultureInfo.InvariantCulture)) - .Add("version", "v3") - .Add(ConvertProxy(proxy)), - cancellationToken) - .ConfigureAwait(false); - - if (IsErrorCode(response)) - ThrowException(response); - - return new StringResponse { Id = 0, Response = TakeSecondSlice(response) }; - } - - /// - public override Task ReportSolution - (long taskId, CaptchaType type, bool correct = false, CancellationToken cancellationToken = default) - { - throw new NotSupportedException(); - } - - private StringPairCollection GetAuthPair() - => new StringPairCollection().Add("key", ApiKey); - - private void ThrowException(string response) - { - switch (response) - { - case "ERROR_API_KEY_NOT_FOUND": - case "ERROR_ACCESS_DENIED": - throw new BadAuthenticationException(response); - - case "ERROR_NO_AVAILABLE_THREADS": - throw new TaskCreationException(response); - - case "ERROR_CAPTCHA_UNSOLVABLE": - throw new TaskSolutionException(response); - - default: - throw new Exception(response); - } - } - } -} diff --git a/CaptchaSharp.Services.More/TrueCaptchaService.cs b/CaptchaSharp.Services.More/TrueCaptchaService.cs deleted file mode 100644 index ec9ac73..0000000 --- a/CaptchaSharp.Services.More/TrueCaptchaService.cs +++ /dev/null @@ -1,73 +0,0 @@ -using CaptchaSharp.Exceptions; -using CaptchaSharp.Models; -using Newtonsoft.Json.Linq; -using System; -using System.Globalization; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; - -namespace CaptchaSharp.Services.More -{ - /// The service provided by https://apitruecaptcha.org/ - public class TrueCaptchaService : CaptchaService - { - /// Your user id. - public string UserId { get; set; } - - /// Your secret api key. - public string ApiKey { get; set; } - - /// The default used for requests. - protected HttpClient httpClient; - - /// Initializes a using the given , and - /// . If is null, a default one will be created. - public TrueCaptchaService(string userId, string apiKey, HttpClient httpClient = null) - { - UserId = userId; - ApiKey = apiKey; - - this.httpClient = httpClient ?? new HttpClient(); - this.httpClient.BaseAddress = new Uri("https://api.apitruecaptcha.org/"); - this.httpClient.Timeout = Timeout; - } - - /// - public async override Task GetBalanceAsync(CancellationToken cancellationToken = default) - { - var response = await httpClient.GetStringAsync - ("one/getbalance", - new StringPairCollection() - .Add("username", UserId) - .Add("apikey", ApiKey), - cancellationToken) - .ConfigureAwait(false); - - if (decimal.TryParse(response, NumberStyles.Any, CultureInfo.InvariantCulture, out decimal balance)) - return balance; - - else - throw new BadAuthenticationException(response); - } - - /// - public async override Task SolveImageCaptchaAsync - (string base64, ImageCaptchaOptions options = null, CancellationToken cancellationToken = default) - { - var content = new JObject(); - content.Add("userid", UserId); - content.Add("apikey", ApiKey); - content.Add("data", base64); - - var response = await httpClient.PostJsonToStringAsync - ("one/gettext", - content, - cancellationToken, false) - .ConfigureAwait(false); - - var jObject = JObject.Parse(response); - return new StringResponse { Id = 0, Response = jObject["result"].ToString() }; - } - } -} diff --git a/CaptchaSharp.Tests/AntiCaptchaServiceTests.cs b/CaptchaSharp.Tests/AntiCaptchaServiceTests.cs index 7a0ac23..2deb117 100644 --- a/CaptchaSharp.Tests/AntiCaptchaServiceTests.cs +++ b/CaptchaSharp.Tests/AntiCaptchaServiceTests.cs @@ -1,33 +1,40 @@ using CaptchaSharp.Services; -using System; using System.Threading.Tasks; using Xunit; +using Xunit.Abstractions; -namespace CaptchaSharp.Tests +namespace CaptchaSharp.Tests; + +public class AntiCaptchaFixture : ServiceFixture { - public class AntiCaptchaFixture : ServiceFixture + public AntiCaptchaFixture() { - public AntiCaptchaFixture() - { - Service = new AntiCaptchaService(Config.Credentials.AntiCaptchaApiKey); - } + Service = new AntiCaptchaService(Config.Credentials.AntiCaptchaApiKey); } +} - public class AntiCaptchaServiceTests : ServiceTests, IClassFixture - { - public AntiCaptchaServiceTests(AntiCaptchaFixture fixture) : base(fixture) { } - - [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); - [Fact] public Task SolveImageCaptchaAsync_ValidCaptcha_ValidSolution() => ImageCaptchaTest(); - [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); - [Fact] public Task SolveRecaptchaV2Async_WithProxy_ValidSolution() => RecaptchaV2Test_WithProxy(); - [Fact] public Task SolveRecaptchaV3Async_NoProxy_ValidSolution() => RecaptchaV3Test_NoProxy(); - [Fact] public Task SolveRecaptchaV3Async_WithProxy_ValidSolution() => RecaptchaV3Test_WithProxy(); - [Fact] public Task SolveFuncaptchaAsync_NoProxy_ValidSolution() => FunCaptchaTest_NoProxy(); - [Fact] public Task SolveFuncaptchaAsync_WithProxy_ValidSolution() => FunCaptchaTest_WithProxy(); - [Fact] public Task SolveHCaptchaAsync_NoProxy_ValidSolution() => HCaptchaTest_NoProxy(); - [Fact] public Task SolveHCaptchaAsync_WithProxy_ValidSolution() => HCaptchaTest_WithProxy(); - [Fact] public Task SolveGeeTestAsync_NoProxy_ValidSolution() => GeeTestTest_NoProxy(); - [Fact] public Task SolveGeeTestAsync_WithProxy_ValidSolution() => GeeTestTest_WithProxy(); - } -} \ No newline at end of file +public class AntiCaptchaServiceTests(AntiCaptchaFixture fixture, ITestOutputHelper output) + : ServiceTests(fixture, output), IClassFixture +{ + [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); + [Fact] public Task ReportSolution_NoException() => ReportRecaptchaSolutionTest(); + [Fact] public Task SolveImageCaptchaAsync_ValidCaptcha_ValidSolution() => ImageCaptchaTest(); + [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); + [Fact] public Task SolveRecaptchaV2Async_WithProxy_ValidSolution() => RecaptchaV2Test_WithProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_NoProxy_ValidSolution() => RecaptchaV2InvisibleTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_WithProxy_ValidSolution() => RecaptchaV2InvisibleTest_WithProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV2EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_WithProxy_ValidSolution() => RecaptchaV2EnterpriseTest_WithProxy(); + [Fact] public Task SolveRecaptchaV3Async_NoProxy_ValidSolution() => RecaptchaV3Test_NoProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV3EnterpriseTest_NoProxy(); + [Fact] public Task SolveFuncaptchaAsync_NoProxy_ValidSolution() => FunCaptchaTest_NoProxy(); + [Fact] public Task SolveFuncaptchaAsync_WithProxy_ValidSolution() => FunCaptchaTest_WithProxy(); + [Fact] public Task SolveHCaptchaAsync_NoProxy_ValidSolution() => HCaptchaTest_NoProxy(); + [Fact] public Task SolveHCaptchaAsync_WithProxy_ValidSolution() => HCaptchaTest_WithProxy(); + [Fact] public Task SolveGeeTestAsync_NoProxy_ValidSolution() => GeeTestTest_NoProxy(); + [Fact] public Task SolveGeeTestAsync_WithProxy_ValidSolution() => GeeTestTest_WithProxy(); + [Fact] public Task SolveCloudflareTurnstileAsync_NoProxy_ValidSolution() => CloudflareTurnstileTest_NoProxy(); + [Fact] public Task SolveCloudflareTurnstileAsync_WithProxy_ValidSolution() => CloudflareTurnstileTest_WithProxy(); + [Fact] public Task SolveGeeTestV4Async_NoProxy_ValidSolution() => GeeTestV4Test_NoProxy(); + [Fact] public Task SolveGeeTestV4Async_WithProxy_ValidSolution() => GeeTestV4Test_WithProxy(); +} diff --git a/CaptchaSharp.Tests/AnyCaptchaTests.cs b/CaptchaSharp.Tests/AnyCaptchaTests.cs deleted file mode 100644 index 4547ec3..0000000 --- a/CaptchaSharp.Tests/AnyCaptchaTests.cs +++ /dev/null @@ -1,26 +0,0 @@ -using CaptchaSharp.Services.More; -using System.Threading.Tasks; -using Xunit; - -namespace CaptchaSharp.Tests -{ - public class AnyCaptchaFixture : ServiceFixture - { - public AnyCaptchaFixture() - { - Service = new AnyCaptchaService(Config.Credentials.AnyCaptchaApiKey); - } - } - - public class AnyCaptchaServiceTests : ServiceTests, IClassFixture - { - public AnyCaptchaServiceTests(AnyCaptchaFixture fixture) : base(fixture) { } - - [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); - [Fact] public Task SolveImageCaptchaAsync_ValidCaptcha_ValidSolution() => ImageCaptchaTest(); - [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); - [Fact] public Task SolveRecaptchaV3Async_NoProxy_ValidSolution() => RecaptchaV3Test_NoProxy(); - [Fact] public Task SolveFuncaptchaAsync_NoProxy_ValidSolution() => FunCaptchaTest_NoProxy(); - [Fact] public Task SolveHCaptchaAsync_NoProxy_ValidSolution() => HCaptchaTest_NoProxy(); - } -} \ No newline at end of file diff --git a/CaptchaSharp.Tests/AzCaptchaServiceTests.cs b/CaptchaSharp.Tests/AzCaptchaServiceTests.cs new file mode 100644 index 0000000..8567219 --- /dev/null +++ b/CaptchaSharp.Tests/AzCaptchaServiceTests.cs @@ -0,0 +1,32 @@ +using System.Threading.Tasks; +using CaptchaSharp.Services; +using Xunit; +using Xunit.Abstractions; + +namespace CaptchaSharp.Tests; + +public class AzCaptchaFixture : ServiceFixture +{ + public AzCaptchaFixture() + { + Service = new AzCaptchaService( + Config.Credentials.AzCaptchaApiKey); + } +} + +public class AzCaptchaServiceTests(AzCaptchaFixture fixture, ITestOutputHelper output) + : ServiceTests(fixture, output), IClassFixture +{ + [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); + [Fact] public Task SolveImageCaptchaAsync_ValidCaptcha_ValidSolution() => ImageCaptchaTest(); + [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); + [Fact] public Task SolveRecaptchaV2Async_WithProxy_ValidSolution() => RecaptchaV2Test_WithProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_NoProxy_ValidSolution() => RecaptchaV2InvisibleTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_WithProxy_ValidSolution() => RecaptchaV2InvisibleTest_WithProxy(); + [Fact] public Task SolveRecaptchaV3Async_NoProxy_ValidSolution() => RecaptchaV3Test_NoProxy(); + [Fact] public Task SolveRecaptchaV3Async_WithProxy_ValidSolution() => RecaptchaV3Test_WithProxy(); + [Fact] public Task SolveFunCaptchaAsync_NoProxy_ValidSolution() => FunCaptchaTest_NoProxy(); + [Fact] public Task SolveFunCaptchaAsync_WithProxy_ValidSolution() => FunCaptchaTest_WithProxy(); + [Fact] public Task SolveHCaptchaAsync_NoProxy_ValidSolution() => HCaptchaTest_NoProxy(); + [Fact] public Task SolveHCaptchaAsync_WithProxy_ValidSolution() => HCaptchaTest_WithProxy(); +} diff --git a/CaptchaSharp.Tests/BestCaptchaSolverServiceTests.cs b/CaptchaSharp.Tests/BestCaptchaSolverServiceTests.cs new file mode 100644 index 0000000..8d1135f --- /dev/null +++ b/CaptchaSharp.Tests/BestCaptchaSolverServiceTests.cs @@ -0,0 +1,48 @@ +using System.Threading.Tasks; +using CaptchaSharp.Services; +using Xunit; +using Xunit.Abstractions; + +namespace CaptchaSharp.Tests; + +public class BestCaptchaSolverFixture : ServiceFixture +{ + public BestCaptchaSolverFixture() + { + Service = new BestCaptchaSolverService( + Config.Credentials.BestCaptchaSolverApiKey); + } +} + +public class BestCaptchaSolverServiceTests(BestCaptchaSolverFixture fixture, ITestOutputHelper output) + : ServiceTests(fixture, output), IClassFixture +{ + [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); + + // Do not abuse this method or you will be banned + [Fact] public Task ReportSolution_NoException() => ReportImageSolutionTest(correct: false); + + [Fact] public Task SolveImageCaptchaAsync_ValidCaptcha_ValidSolution() => ImageCaptchaTest(); + [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); + [Fact] public Task SolveRecaptchaV2Async_WithProxy_ValidSolution() => RecaptchaV2Test_WithProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_NoProxy_ValidSolution() => RecaptchaV2InvisibleTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_WithProxy_ValidSolution() => RecaptchaV2InvisibleTest_WithProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV2EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_WithProxy_ValidSolution() => RecaptchaV2EnterpriseTest_WithProxy(); + [Fact] public Task SolveRecaptchaV3Async_NoProxy_ValidSolution() => RecaptchaV3Test_NoProxy(); + [Fact] public Task SolveRecaptchaV3Async_WithProxy_ValidSolution() => RecaptchaV3Test_WithProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV3EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_WithProxy_ValidSolution() => RecaptchaV3EnterpriseTest_WithProxy(); + [Fact] public Task SolveFuncaptchaAsync_NoProxy_ValidSolution() => FunCaptchaTest_NoProxy(); + [Fact] public Task SolveFuncaptchaAsync_WithProxy_ValidSolution() => FunCaptchaTest_WithProxy(); + [Fact] public Task SolveHCaptchaAsync_NoProxy_ValidSolution() => HCaptchaTest_NoProxy(); + [Fact] public Task SolveHCaptchaAsync_WithProxy_ValidSolution() => HCaptchaTest_WithProxy(); + [Fact] public Task SolveGeeTestAsync_NoProxy_ValidSolution() => GeeTestTest_NoProxy(); + [Fact] public Task SolveGeeTestAsync_WithProxy_ValidSolution() => GeeTestTest_WithProxy(); + [Fact] public Task SolveCapyAsync_NoProxy_ValidSolution() => CapyTest_NoProxy(); + [Fact] public Task SolveCapyAsync_WithProxy_ValidSolution() => CapyTest_WithProxy(); + [Fact] public Task SolveCloudflareTurnstileAsync_NoProxy_ValidSolution() => CloudflareTurnstileTest_NoProxy(); + [Fact] public Task SolveCloudflareTurnstileAsync_WithProxy_ValidSolution() => CloudflareTurnstileTest_WithProxy(); + [Fact] public Task SolveGeeTestV4Async_NoProxy_ValidSolution() => GeeTestV4Test_NoProxy(); + [Fact] public Task SolveGeeTestV4Async_WithProxy_ValidSolution() => GeeTestV4Test_WithProxy(); +} diff --git a/CaptchaSharp.Tests/CapGuruServiceTests.cs b/CaptchaSharp.Tests/CapGuruServiceTests.cs new file mode 100644 index 0000000..578c421 --- /dev/null +++ b/CaptchaSharp.Tests/CapGuruServiceTests.cs @@ -0,0 +1,35 @@ +using System.Threading.Tasks; +using CaptchaSharp.Services; +using Xunit; +using Xunit.Abstractions; + +namespace CaptchaSharp.Tests; + +public class CapGuruFixture : ServiceFixture +{ + public CapGuruFixture() + { + Service = new CapGuruService( + Config.Credentials.CapGuruApiKey); + } +} + +public class CapGuruServiceTests(CapGuruFixture fixture, ITestOutputHelper output) + : ServiceTests(fixture, output), IClassFixture +{ + [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); + [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); + [Fact] public Task SolveRecaptchaV2Async_WithProxy_ValidSolution() => RecaptchaV2Test_WithProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_NoProxy_ValidSolution() => RecaptchaV2InvisibleTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_WithProxy_ValidSolution() => RecaptchaV2InvisibleTest_WithProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV2EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_WithProxy_ValidSolution() => RecaptchaV2EnterpriseTest_WithProxy(); + [Fact] public Task SolveRecaptchaV3Async_NoProxy_ValidSolution() => RecaptchaV3Test_NoProxy(); + [Fact] public Task SolveRecaptchaV3Async_WithProxy_ValidSolution() => RecaptchaV3Test_WithProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV3EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_WithProxy_ValidSolution() => RecaptchaV3EnterpriseTest_WithProxy(); + [Fact] public Task SolveHCaptchaAsync_NoProxy_ValidSolution() => HCaptchaTest_NoProxy(); + [Fact] public Task SolveHCaptchaAsync_WithProxy_ValidSolution() => HCaptchaTest_WithProxy(); + [Fact] public Task SolveCloudflareTurnstileAsync_NoProxy_ValidSolution() => CloudflareTurnstileTest_NoProxy(); + [Fact] public Task SolveCloudflareTurnstileAsync_WithProxy_ValidSolution() => CloudflareTurnstileTest_WithProxy(); +} diff --git a/CaptchaSharp.Tests/CapMonsterCloudServiceTests.cs b/CaptchaSharp.Tests/CapMonsterCloudServiceTests.cs new file mode 100644 index 0000000..dabe91a --- /dev/null +++ b/CaptchaSharp.Tests/CapMonsterCloudServiceTests.cs @@ -0,0 +1,45 @@ +using System.Threading.Tasks; +using CaptchaSharp.Services; +using Xunit; +using Xunit.Abstractions; + +namespace CaptchaSharp.Tests; + +public class CapMonsterCloudFixture : ServiceFixture +{ + public CapMonsterCloudFixture() + { + Service = new CapMonsterCloudService( + Config.Credentials.CapMonsterCloudApiKey); + } +} + +public class CapMonsterCloudServiceTests(CapMonsterCloudFixture fixture, ITestOutputHelper output) + : ServiceTests(fixture, output), IClassFixture +{ + [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); + + // Do not overuse this method, as it will get your account banned. + [Fact] public Task ReportSolutionAsync_ValidCaptcha_Reported() => ReportImageSolutionTest(correct: false); + + [Fact] public Task SolveImageCaptchaAsync_ValidCaptcha_ValidSolution() => ImageCaptchaTest(); + [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); + [Fact] public Task SolveRecaptchaV2Async_WithProxy_ValidSolution() => RecaptchaV2Test_WithProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_NoProxy_ValidSolution() => RecaptchaV2InvisibleTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_WithProxy_ValidSolution() => RecaptchaV2InvisibleTest_WithProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV2EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_WithProxy_ValidSolution() => RecaptchaV2EnterpriseTest_WithProxy(); + [Fact] public Task SolveRecaptchaV3Async_NoProxy_ValidSolution() => RecaptchaV3Test_NoProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV3EnterpriseTest_NoProxy(); + [Fact] public Task SolveFuncaptchaAsync_NoProxy_ValidSolution() => FunCaptchaTest_NoProxy(); + [Fact] public Task SolveFuncaptchaAsync_WithProxy_ValidSolution() => FunCaptchaTest_WithProxy(); + [Fact] public Task SolveHCaptchaAsync_NoProxy_ValidSolution() => HCaptchaTest_NoProxy(); + [Fact] public Task SolveHCaptchaAsync_WithProxy_ValidSolution() => HCaptchaTest_WithProxy(); + [Fact] public Task SolveGeeTestAsync_NoProxy_ValidSolution() => GeeTestTest_NoProxy(); + [Fact] public Task SolveGeeTestAsync_WithProxy_ValidSolution() => GeeTestTest_WithProxy(); + [Fact] public Task SolveDataDomeAsync_WithProxy_ValidSolution() => DataDomeTest_WithProxy(); + [Fact] public Task SolveCloudflareTurnstileAsync_NoProxy_ValidSolution() => CloudflareTurnstileTest_NoProxy(); + [Fact] public Task SolveCloudflareTurnstileAsync_WithProxy_ValidSolution() => CloudflareTurnstileTest_WithProxy(); + [Fact] public Task SolveGeeTestV4Async_NoProxy_ValidSolution() => GeeTestV4Test_NoProxy(); + [Fact] public Task SolveGeeTestV4Async_WithProxy_ValidSolution() => GeeTestV4Test_WithProxy(); +} diff --git a/CaptchaSharp.Tests/CapSolverServiceTests.cs b/CaptchaSharp.Tests/CapSolverServiceTests.cs index 0fa09ed..d2a5b5d 100644 --- a/CaptchaSharp.Tests/CapSolverServiceTests.cs +++ b/CaptchaSharp.Tests/CapSolverServiceTests.cs @@ -1,28 +1,45 @@ using CaptchaSharp.Services; using System.Threading.Tasks; using Xunit; +using Xunit.Abstractions; -namespace CaptchaSharp.Tests +namespace CaptchaSharp.Tests; + +public class CapSolverFixture : ServiceFixture { - public class CapSolverFixture : ServiceFixture + public CapSolverFixture() { - public CapSolverFixture() - { - Service = new CapSolverService(Config.Credentials.CapSolverApiKey); - } + Service = new CapSolverService(Config.Credentials.CapSolverApiKey); } +} - public class CapSolverServiceTests : ServiceTests, IClassFixture - { - public CapSolverServiceTests(CapSolverFixture fixture) : base(fixture) { } - - [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); - [Fact] public Task SolveImageCaptchaAsync_ValidCaptcha_ValidSolution() => ImageCaptchaTest(); - [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); - [Fact] public Task SolveRecaptchaV3Async_NoProxy_ValidSolution() => RecaptchaV3Test_NoProxy(); - [Fact] public Task SolveFuncaptchaAsync_NoProxy_ValidSolution() => FunCaptchaTest_NoProxy(); - [Fact] public Task SolveHCaptchaAsync_NoProxy_ValidSolution() => HCaptchaTest_NoProxy(); - [Fact] public Task SolveGeeTestAsync_NoProxy_ValidSolution() => GeeTestTest_NoProxy(); - [Fact] public Task SolveDataDomeTestAsync_WithProxy_ValidSolution() => DataDomeTest_WithProxy(); - } +public class CapSolverServiceTests(CapSolverFixture fixture, ITestOutputHelper output) + : ServiceTests(fixture, output), IClassFixture +{ + [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); + [Fact] public Task ReportSolution_NoException() => ReportImageSolutionTest(); + [Fact] public Task SolveImageCaptchaAsync_ValidCaptcha_ValidSolution() => ImageCaptchaTest(); + [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); + [Fact] public Task SolveRecaptchaV2Async_WithProxy_ValidSolution() => RecaptchaV2Test_WithProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_NoProxy_ValidSolution() => RecaptchaV2InvisibleTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_WithProxy_ValidSolution() => RecaptchaV2InvisibleTest_WithProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV2EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_WithProxy_ValidSolution() => RecaptchaV2EnterpriseTest_WithProxy(); + [Fact] public Task SolveRecaptchaV3Async_NoProxy_ValidSolution() => RecaptchaV3Test_NoProxy(); + [Fact] public Task SolveRecaptchaV3Async_WithProxy_ValidSolution() => RecaptchaV3Test_WithProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV3EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_WithProxy_ValidSolution() => RecaptchaV3EnterpriseTest_WithProxy(); + [Fact] public Task SolveFuncaptchaAsync_NoProxy_ValidSolution() => FunCaptchaTest_NoProxy(); + [Fact] public Task SolveFuncaptchaAsync_WithProxy_ValidSolution() => FunCaptchaTest_WithProxy(); + [Fact] public Task SolveHCaptchaAsync_NoProxy_ValidSolution() => HCaptchaTest_NoProxy(); + [Fact] public Task SolveHCaptchaAsync_WithProxy_ValidSolution() => HCaptchaTest_WithProxy(); + [Fact] public Task SolveGeeTestAsync_NoProxy_ValidSolution() => GeeTestTest_NoProxy(); + [Fact] public Task SolveDataDomeTestAsync_WithProxy_ValidSolution() => DataDomeTest_WithProxy(); + [Fact] public Task SolveCloudflareTurnstileAsync_NoProxy_ValidSolution() => CloudflareTurnstileTest_NoProxy(); + [Fact] public Task SolveAmazonWafAsync_NoProxy_ValidSolution() => AmazonWafTest_NoProxy(); + [Fact] public Task SolveAmazonWafAsync_WithProxy_ValidSolution() => AmazonWafTest_WithProxy(); + [Fact] public Task SolveMtCaptchaAsync_NoProxy_ValidSolution() => MtCaptchaTest_NoProxy(); + [Fact] public Task SolveMtCaptchaAsync_WithProxy_ValidSolution() => MtCaptchaTest_WithProxy(); + [Fact] public Task SolveGeeTestV4Async_NoProxy_ValidSolution() => GeeTestV4Test_NoProxy(); + [Fact] public Task SolveGeeTestV4Async_WithProxy_ValidSolution() => GeeTestV4Test_WithProxy(); } diff --git a/CaptchaSharp.Tests/CaptchaAiServiceTests.cs b/CaptchaSharp.Tests/CaptchaAiServiceTests.cs new file mode 100644 index 0000000..42f1613 --- /dev/null +++ b/CaptchaSharp.Tests/CaptchaAiServiceTests.cs @@ -0,0 +1,35 @@ +using System.Threading.Tasks; +using CaptchaSharp.Services; +using Xunit; +using Xunit.Abstractions; + +namespace CaptchaSharp.Tests; + +public class CaptchaAiFixture : ServiceFixture +{ + public CaptchaAiFixture() + { + Service = new CaptchaAiService( + Config.Credentials.CaptchaAiApiKey); + } +} + +public class CaptchaAiServiceTests(CaptchaAiFixture fixture, ITestOutputHelper output) + : ServiceTests(fixture, output), IClassFixture +{ + [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); + [Fact] public Task ReportSolution_NoException() => ReportImageSolutionTest(); + [Fact] public Task SolveImageCaptchaAsync_ValidCaptcha_ValidSolution() => ImageCaptchaTest(); + [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); + [Fact] public Task SolveRecaptchaV2Async_WithProxy_ValidSolution() => RecaptchaV2Test_WithProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_NoProxy_ValidSolution() => RecaptchaV2InvisibleTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_WithProxy_ValidSolution() => RecaptchaV2InvisibleTest_WithProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV2EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_WithProxy_ValidSolution() => RecaptchaV2EnterpriseTest_WithProxy(); + [Fact] public Task SolveRecaptchaV3Async_NoProxy_ValidSolution() => RecaptchaV3Test_NoProxy(); + [Fact] public Task SolveRecaptchaV3Async_WithProxy_ValidSolution() => RecaptchaV3Test_WithProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV3EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_WithProxy_ValidSolution() => RecaptchaV3EnterpriseTest_WithProxy(); + [Fact] public Task SolveHCaptchaAsync_NoProxy_ValidSolution() => HCaptchaTest_NoProxy(); + [Fact] public Task SolveHCaptchaAsync_WithProxy_ValidSolution() => HCaptchaTest_WithProxy(); +} diff --git a/CaptchaSharp.Tests/CaptchaCoderServiceTests.cs b/CaptchaSharp.Tests/CaptchaCoderServiceTests.cs new file mode 100644 index 0000000..c30a7fb --- /dev/null +++ b/CaptchaSharp.Tests/CaptchaCoderServiceTests.cs @@ -0,0 +1,29 @@ +using CaptchaSharp.Services; +using System.Threading.Tasks; +using Xunit; +using Xunit.Abstractions; + +namespace CaptchaSharp.Tests; + +public class CaptchaCoderFixture : ServiceFixture +{ + public CaptchaCoderFixture() + { + Service = new CaptchaCoderService(Config.Credentials.CaptchaCoderApiKey); + } +} + +public class CaptchaCoderServiceTests(CaptchaCoderFixture fixture, ITestOutputHelper output) + : ServiceTests(fixture, output), IClassFixture +{ + [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); + + // Do not overly use this test, or you will get banned. + [Fact] public Task ReportSolution_NoException() => ReportImageSolutionTest(); + + [Fact] public Task SolveImageCaptchaAsync_ValidCaptcha_ValidSolution() => ImageCaptchaTest(); + [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_NoProxy_ValidSolution() => RecaptchaV2InvisibleTest_NoProxy(); + [Fact] public Task SolveRecaptchaV3Async_NoProxy_ValidSolution() => RecaptchaV3Test_NoProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV3EnterpriseTest_NoProxy(); +} diff --git a/CaptchaSharp.Tests/CaptchaSharp.Tests.csproj b/CaptchaSharp.Tests/CaptchaSharp.Tests.csproj index f210d18..194ab36 100644 --- a/CaptchaSharp.Tests/CaptchaSharp.Tests.csproj +++ b/CaptchaSharp.Tests/CaptchaSharp.Tests.csproj @@ -1,8 +1,9 @@  - net6.0 + net8.0 false + enable @@ -16,10 +17,13 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + - diff --git a/CaptchaSharp.Tests/CaptchasIoServiceTests.cs b/CaptchaSharp.Tests/CaptchasIoServiceTests.cs new file mode 100644 index 0000000..1045738 --- /dev/null +++ b/CaptchaSharp.Tests/CaptchasIoServiceTests.cs @@ -0,0 +1,42 @@ +using System.Threading.Tasks; +using CaptchaSharp.Services; +using Xunit; +using Xunit.Abstractions; + +namespace CaptchaSharp.Tests; + +public class CaptchasIoFixture : ServiceFixture +{ + public CaptchasIoFixture() + { + Service = new CaptchasIoService( + Config.Credentials.CaptchasIoApiKey); + } +} + +public class CaptchasIoServiceTests(CaptchasIoFixture fixture, ITestOutputHelper output) + : ServiceTests(fixture, output), IClassFixture +{ + [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); + [Fact] public Task SolveTextCaptchaAsync_ValidCaptcha_ValidSolution() => TextCaptchaTest(); + [Fact] public Task SolveImageCaptchaAsync_ValidCaptcha_ValidSolution() => ImageCaptchaTest(); + [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); + [Fact] public Task SolveRecaptchaV2Async_WithProxy_ValidSolution() => RecaptchaV2Test_WithProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_NoProxy_ValidSolution() => RecaptchaV2InvisibleTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_WithProxy_ValidSolution() => RecaptchaV2InvisibleTest_WithProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV2EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_WithProxy_ValidSolution() => RecaptchaV2EnterpriseTest_WithProxy(); + [Fact] public Task SolveRecaptchaV3Async_NoProxy_ValidSolution() => RecaptchaV3Test_NoProxy(); + [Fact] public Task SolveRecaptchaV3Async_WithProxy_ValidSolution() => RecaptchaV3Test_WithProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV3EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_WithProxy_ValidSolution() => RecaptchaV3EnterpriseTest_WithProxy(); + [Fact] public Task SolveFuncaptchaAsync_NoProxy_ValidSolution() => FunCaptchaTest_NoProxy(); + [Fact] public Task SolveFuncaptchaAsync_WithProxy_ValidSolution() => FunCaptchaTest_WithProxy(); + [Fact] public Task SolveHCaptchaAsync_NoProxy_ValidSolution() => HCaptchaTest_NoProxy(); + [Fact] public Task SolveHCaptchaAsync_WithProxy_ValidSolution() => HCaptchaTest_WithProxy(); + [Fact] public Task SolveGeeTestAsync_NoProxy_ValidSolution() => GeeTestTest_NoProxy(); + [Fact] public Task SolveGeeTestAsync_WithProxy_ValidSolution() => GeeTestTest_WithProxy(); + [Fact] public Task SolveCloudflareTurnstileAsync_NoProxy_ValidSolution() => CloudflareTurnstileTest_NoProxy(); + [Fact] public Task SolveCloudflareTurnstileAsync_WithProxy_ValidSolution() => CloudflareTurnstileTest_WithProxy(); + [Fact] public Task SolveAudioCaptchaAsync_ValidCaptcha_ValidSolution() => AudioCaptchaTest(); +} diff --git a/CaptchaSharp.Tests/ConfigFixture.cs b/CaptchaSharp.Tests/ConfigFixture.cs index 8d5d750..ffb2ef0 100644 --- a/CaptchaSharp.Tests/ConfigFixture.cs +++ b/CaptchaSharp.Tests/ConfigFixture.cs @@ -2,58 +2,69 @@ using Newtonsoft.Json; using System.IO; -namespace CaptchaSharp.Tests +namespace CaptchaSharp.Tests; + +public class ConfigFixture { - public class ConfigFixture - { - private readonly string credentialsFile = "config.json"; - public Config Config { get; set; } + private const string _credentialsFile = "config.json"; + public Config Config { get; set; } - public ConfigFixture() + public ConfigFixture() + { + if (File.Exists(_credentialsFile)) { - if (File.Exists(credentialsFile)) - { - Config = JsonConvert.DeserializeObject(File.ReadAllText(credentialsFile)); - } - else - { - // Write a blank structure if it doesn't exist so that we don't have to manually create it from scratch - Config = new Config(); - File.WriteAllText(credentialsFile, JsonConvert.SerializeObject(Config, Formatting.Indented)); - } + Config = JsonConvert.DeserializeObject(File.ReadAllText(_credentialsFile))!; + } + else + { + // Write a blank structure if it doesn't exist so that we don't have to manually create it from scratch + Config = new Config(); + File.WriteAllText(_credentialsFile, JsonConvert.SerializeObject(Config, Formatting.Indented)); } } +} - public class Config - { - public Credentials Credentials { get; set; } = new(); - public Proxy Proxy { get; set; } = new(); - } +public class Config +{ + public Credentials Credentials { get; set; } = new(); + public SessionParams SessionParams { get; set; } = new(); +} - public class Credentials - { - public string TwoCaptchaApiKey { get; set; } = string.Empty; - public string AntiCaptchaApiKey { get; set; } = string.Empty; - public string CustomTwoCaptchaApiKey { get; set; } = string.Empty; - public string CustomTwoCaptchaHost { get; set; } = string.Empty; - public int CustomTwoCaptchaPort { get; set; } = 80; - public bool CustomTwoCaptchaOverrideHostHeader { get; set; } = true; - public string DeathByCaptchaUsername { get; set; } = string.Empty; - public string DeathByCaptchaPassword { get; set; } = string.Empty; - public string DeCaptcherUsername { get; set; } = string.Empty; - public string DeCaptcherPassword { get; set; } = string.Empty; - public string ImageTyperzApiKey { get; set; } = string.Empty; - public string CapMonsterHost { get; set; } = string.Empty; - public int CapMonsterPort { get; set; } = 80; - public string AZCaptchaApiKey { get; set; } = string.Empty; - public string CaptchasIOApiKey { get; set; } = string.Empty; - public string RuCaptchaApiKey { get; set; } = string.Empty; - public string SolveCaptchaApiKey { get; set; } = string.Empty; - public string SolveRecaptchaApiKey { get; set; } = string.Empty; - public string TrueCaptchaApiKey { get; set; } = string.Empty; - public string TrueCaptchaUsername { get; set; } = string.Empty; - public string NineKWApiKey { get; set; } = string.Empty; - public string AnyCaptchaApiKey { get; set; } = string.Empty; - public string CapSolverApiKey { get; set; } = string.Empty; - } +public class Credentials +{ + public string TwoCaptchaApiKey { get; set; } = string.Empty; + public string AntiCaptchaApiKey { get; set; } = string.Empty; + public string CustomTwoCaptchaApiKey { get; set; } = string.Empty; + public string CustomTwoCaptchaHost { get; set; } = string.Empty; + public int CustomTwoCaptchaPort { get; set; } = 80; + public bool CustomTwoCaptchaOverrideHostHeader { get; set; } = true; + public string DeathByCaptchaUsername { get; set; } = string.Empty; + public string DeathByCaptchaPassword { get; set; } = string.Empty; + public string CaptchaCoderApiKey { get; set; } = string.Empty; + public string HumanCoderApiKey { get; set; } = string.Empty; + public string ImageTyperzApiKey { get; set; } = string.Empty; + public string CapMonsterHost { get; set; } = string.Empty; + public int CapMonsterPort { get; set; } = 80; + public string AzCaptchaApiKey { get; set; } = string.Empty; + public string CaptchasIoApiKey { get; set; } = string.Empty; + public string RuCaptchaApiKey { get; set; } = string.Empty; + public string TrueCaptchaApiKey { get; set; } = string.Empty; + public string TrueCaptchaUsername { get; set; } = string.Empty; + public string NineKWApiKey { get; set; } = string.Empty; + public string CapSolverApiKey { get; set; } = string.Empty; + public string CapMonsterCloudApiKey { get; set; } = string.Empty; + public string MetaBypassTechClientId { get; set; } = string.Empty; + public string MetaBypassTechClientSecret { get; set; } = string.Empty; + public string MetaBypassTechUsername { get; set; } = string.Empty; + public string MetaBypassTechPassword { get; set; } = string.Empty; + public string NextCaptchaApiKey { get; set; } = string.Empty; + public string NoCaptchaAiApiKey { get; set; } = string.Empty; + public string NopechaApiKey { get; set; } = string.Empty; + public string BestCaptchaSolverApiKey { get; set; } = string.Empty; + public string CaptchaAiApiKey { get; set; } = string.Empty; + public string EzCaptchaApiKey { get; set; } = string.Empty; + public string SolveCaptchaApiKey { get; set; } = string.Empty; + public string EndCaptchaUsername { get; set; } = string.Empty; + public string EndCaptchaPassword { get; set; } = string.Empty; + public string CapGuruApiKey { get; set; } = string.Empty; } diff --git a/CaptchaSharp.Tests/DeCaptcherServiceTests.cs b/CaptchaSharp.Tests/DeCaptcherServiceTests.cs deleted file mode 100644 index 891c7db..0000000 --- a/CaptchaSharp.Tests/DeCaptcherServiceTests.cs +++ /dev/null @@ -1,27 +0,0 @@ -using CaptchaSharp.Services; -using System.Threading.Tasks; -using Xunit; - -namespace CaptchaSharp.Tests -{ - public class DeCaptcherFixture : ServiceFixture - { - public DeCaptcherFixture() - { - Service = new DeCaptcherService( - Config.Credentials.DeCaptcherUsername, - Config.Credentials.DeCaptcherPassword); - } - } - - public class DeCaptcherServiceTests : ServiceTests, IClassFixture - { - public DeCaptcherServiceTests(DeCaptcherFixture fixture) : base(fixture) { } - - [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); - [Fact] public Task SolveTextCaptchaAsync_ValidCaptcha_ValidSolution() => TextCaptchaTest(); - [Fact] public Task SolveImageCaptchaAsync_ValidCaptcha_ValidSolution() => ImageCaptchaTest(); - [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); - [Fact] public Task SolveRecaptchaV2Async_WithProxy_ValidSolution() => RecaptchaV2Test_WithProxy(); - } -} \ No newline at end of file diff --git a/CaptchaSharp.Tests/DeathByCaptchaServiceTests.cs b/CaptchaSharp.Tests/DeathByCaptchaServiceTests.cs index 12aa037..691584e 100644 --- a/CaptchaSharp.Tests/DeathByCaptchaServiceTests.cs +++ b/CaptchaSharp.Tests/DeathByCaptchaServiceTests.cs @@ -1,30 +1,62 @@ using CaptchaSharp.Services; using System.Threading.Tasks; using Xunit; +using Xunit.Abstractions; -namespace CaptchaSharp.Tests +namespace CaptchaSharp.Tests; + +public class DeathByCaptchaFixture : ServiceFixture { - public class DeathByCaptchaFixture : ServiceFixture + public DeathByCaptchaFixture() { - public DeathByCaptchaFixture() - { - Service = new DeathByCaptchaService( - Config.Credentials.DeathByCaptchaUsername, - Config.Credentials.DeathByCaptchaPassword); - } + Service = new DeathByCaptchaService( + Config.Credentials.DeathByCaptchaUsername, + Config.Credentials.DeathByCaptchaPassword); } +} - public class DeathByCaptchaServiceTests : ServiceTests, IClassFixture - { - public DeathByCaptchaServiceTests(DeathByCaptchaFixture fixture) : base(fixture) { } - - [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); - [Fact] public Task SolveImageCaptchaAsync_ValidCaptcha_ValidSolution() => ImageCaptchaTest(); - [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); - [Fact] public Task SolveRecaptchaV2Async_WithProxy_ValidSolution() => RecaptchaV2Test_WithProxy(); - [Fact] public Task SolveRecaptchaV3Async_NoProxy_ValidSolution() => RecaptchaV3Test_NoProxy(); - [Fact] public Task SolveRecaptchaV3Async_WithProxy_ValidSolution() => RecaptchaV3Test_WithProxy(); - [Fact] public Task SolveFuncaptchaAsync_NoProxy_ValidSolution() => FunCaptchaTest_NoProxy(); - [Fact] public Task SolveFuncaptchaAsync_WithProxy_ValidSolution() => FunCaptchaTest_WithProxy(); - } -} \ No newline at end of file +public class DeathByCaptchaServiceTests(DeathByCaptchaFixture fixture, ITestOutputHelper output) + : ServiceTests(fixture, output), IClassFixture +{ + [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); + [Fact] public Task ReportSolutionAsync_ValidCaptcha_Reported() => ReportImageSolutionTest(correct: false); + [Fact] public Task SolveImageCaptchaAsync_ValidCaptcha_ValidSolution() => ImageCaptchaTest(); + [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); + [Fact] public Task SolveRecaptchaV2Async_WithProxy_ValidSolution() => RecaptchaV2Test_WithProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_NoProxy_ValidSolution() => RecaptchaV2InvisibleTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_WithProxy_ValidSolution() => RecaptchaV2InvisibleTest_WithProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV2EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_WithProxy_ValidSolution() => RecaptchaV2EnterpriseTest_WithProxy(); + [Fact] public Task SolveRecaptchaV3Async_NoProxy_ValidSolution() => RecaptchaV3Test_NoProxy(); + [Fact] public Task SolveRecaptchaV3Async_WithProxy_ValidSolution() => RecaptchaV3Test_WithProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV3EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_WithProxy_ValidSolution() => RecaptchaV3EnterpriseTest_WithProxy(); + [Fact] public Task SolveFuncaptchaAsync_NoProxy_ValidSolution() => FunCaptchaTest_NoProxy(); + [Fact] public Task SolveFuncaptchaAsync_WithProxy_ValidSolution() => FunCaptchaTest_WithProxy(); + [Fact] public Task SolveHCaptchaAsync_NoProxy_ValidSolution() => HCaptchaTest_NoProxy(); + [Fact] public Task SolveHCaptchaAsync_WithProxy_ValidSolution() => HCaptchaTest_WithProxy(); + [Fact] public Task SolveKeyCaptchaAsync_NoProxy_ValidSolution() => KeyCaptchaTest_NoProxy(); + [Fact] public Task SolveKeyCaptchaAsync_WithProxy_ValidSolution() => KeyCaptchaTest_WithProxy(); + [Fact] public Task SolveGeeTestAsync_NoProxy_ValidSolution() => GeeTestTest_NoProxy(); + [Fact] public Task SolveGeeTestAsync_WithProxy_ValidSolution() => GeeTestTest_WithProxy(); + [Fact] public Task SolveCapyAsync_NoProxy_ValidSolution() => CapyTest_NoProxy(); + [Fact] public Task SolveCapyAsync_WithProxy_ValidSolution() => CapyTest_WithProxy(); + [Fact] public Task SolveDataDomeAsync_WithProxy_ValidSolution() => DataDomeTest_WithProxy(); + [Fact] public Task SolveCloudflareTurnstileAsync_NoProxy_ValidSolution() => CloudflareTurnstileTest_NoProxy(); + [Fact] public Task SolveCloudflareTurnstileAsync_WithProxy_ValidSolution() => CloudflareTurnstileTest_WithProxy(); + [Fact] public Task SolveLeminCroppedAsync_NoProxy_ValidSolution() => LeminCroppedTest_NoProxy(); + [Fact] public Task SolveLeminCroppedAsync_WithProxy_ValidSolution() => LeminCroppedTest_WithProxy(); + [Fact] public Task SolveAmazonWafAsync_NoProxy_ValidSolution() => AmazonWafTest_NoProxy(); + [Fact] public Task SolveAmazonWafAsync_WithProxy_ValidSolution() => AmazonWafTest_WithProxy(); + [Fact] public Task SolveCyberSiAraAsync_NoProxy_ValidSolution() => CyberSiAraTest_NoProxy(); + [Fact] public Task SolveCyberSiAraAsync_WithProxy_ValidSolution() => CyberSiAraTest_WithProxy(); + [Fact] public Task SolveMtCaptchaAsync_NoProxy_ValidSolution() => MtCaptchaTest_NoProxy(); + [Fact] public Task SolveMtCaptchaAsync_WithProxy_ValidSolution() => MtCaptchaTest_WithProxy(); + [Fact] public Task SolveCutCaptchaAsync_NoProxy_ValidSolution() => CutCaptchaTest_NoProxy(); + [Fact] public Task SolveCutCaptchaAsync_WithProxy_ValidSolution() => CutCaptchaTest_WithProxy(); + [Fact] public Task SolveFriendlyCaptchaAsync_NoProxy_ValidSolution() => FriendlyCaptchaTest_NoProxy(); + [Fact] public Task SolveFriendlyCaptchaAsync_WithProxy_ValidSolution() => FriendlyCaptchaTest_WithProxy(); + [Fact] public Task SolveAudioCaptchaAsync_ValidCaptcha_ValidSolution() => AudioCaptchaTest(); + [Fact] public Task SolveGeeTestV4Async_NoProxy_ValidSolution() => GeeTestV4Test_NoProxy(); + [Fact] public Task SolveGeeTestV4Async_WithProxy_ValidSolution() => GeeTestV4Test_WithProxy(); +} diff --git a/CaptchaSharp.Tests/EndCaptchaServiceTests.cs b/CaptchaSharp.Tests/EndCaptchaServiceTests.cs new file mode 100644 index 0000000..e37ba56 --- /dev/null +++ b/CaptchaSharp.Tests/EndCaptchaServiceTests.cs @@ -0,0 +1,32 @@ +using System.Threading.Tasks; +using CaptchaSharp.Services; +using Xunit; +using Xunit.Abstractions; + +namespace CaptchaSharp.Tests; + +public class EndCaptchaFixture : ServiceFixture +{ + public EndCaptchaFixture() + { + Service = new EndCaptchaService( + Config.Credentials.EndCaptchaUsername, + Config.Credentials.EndCaptchaPassword); + } +} + +public class EndCaptchaServiceTests(EndCaptchaFixture fixture, ITestOutputHelper output) + : ServiceTests(fixture, output), IClassFixture +{ + [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); + [Fact] public Task ReportSolution_NoException() => ReportImageSolutionTest(); + [Fact] public Task SolveImageCaptchaAsync_ValidCaptcha_ValidSolution() => ImageCaptchaTest(); + [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); + [Fact] public Task SolveRecaptchaV2Async_WithProxy_ValidSolution() => RecaptchaV2Test_WithProxy(); + [Fact] public Task SolveRecaptchaV3Async_NoProxy_ValidSolution() => RecaptchaV3Test_NoProxy(); + [Fact] public Task SolveRecaptchaV3Async_WithProxy_ValidSolution() => RecaptchaV3Test_WithProxy(); + [Fact] public Task SolveFuncaptchaAsync_NoProxy_ValidSolution() => FunCaptchaTest_NoProxy(); + [Fact] public Task SolveFuncaptchaAsync_WithProxy_ValidSolution() => FunCaptchaTest_WithProxy(); + [Fact] public Task SolveHCaptchaAsync_NoProxy_ValidSolution() => HCaptchaTest_NoProxy(); + [Fact] public Task SolveHCaptchaAsync_WithProxy_ValidSolution() => HCaptchaTest_WithProxy(); +} diff --git a/CaptchaSharp.Tests/EzCaptchaServiceTests.cs b/CaptchaSharp.Tests/EzCaptchaServiceTests.cs new file mode 100644 index 0000000..8651c4e --- /dev/null +++ b/CaptchaSharp.Tests/EzCaptchaServiceTests.cs @@ -0,0 +1,28 @@ +using System.Threading.Tasks; +using CaptchaSharp.Services; +using Xunit; +using Xunit.Abstractions; + +namespace CaptchaSharp.Tests; + +public class EzCaptchaFixture : ServiceFixture +{ + public EzCaptchaFixture() + { + Service = new EzCaptchaService(Config.Credentials.EzCaptchaApiKey); + } +} + +public class EzCaptchaServiceTests(EzCaptchaFixture fixture, ITestOutputHelper output) + : ServiceTests(fixture, output), IClassFixture +{ + [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); + [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_NoProxy_ValidSolution() => RecaptchaV2InvisibleTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV2EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV3Async_NoProxy_ValidSolution() => RecaptchaV3Test_NoProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV3EnterpriseTest_NoProxy(); + [Fact] public Task SolveFunCaptchaAsync_NoProxy_ValidSolution() => FunCaptchaTest_NoProxy(); + [Fact] public Task SolveHCaptchaAsync_NoProxy_ValidSolution() => HCaptchaTest_NoProxy(); + [Fact] public Task SolveDataDomeAsync_WithProxy_ValidSolution() => DataDomeTest_WithProxy(); +} diff --git a/CaptchaSharp.Tests/HumanCoderServiceTests.cs b/CaptchaSharp.Tests/HumanCoderServiceTests.cs new file mode 100644 index 0000000..03d1d3f --- /dev/null +++ b/CaptchaSharp.Tests/HumanCoderServiceTests.cs @@ -0,0 +1,29 @@ +using System.Threading.Tasks; +using CaptchaSharp.Services; +using Xunit; +using Xunit.Abstractions; + +namespace CaptchaSharp.Tests; + +public class HumanCoderFixture : ServiceFixture +{ + public HumanCoderFixture() + { + Service = new HumanCoderService(Config.Credentials.HumanCoderApiKey); + } +} + +public class HumanCoderServiceTests(HumanCoderFixture fixture, ITestOutputHelper output) + : ServiceTests(fixture, output), IClassFixture +{ + [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); + + // Do not overly use this test, or you will get banned. + [Fact] public Task ReportSolution_NoException() => ReportImageSolutionTest(); + + [Fact] public Task SolveImageCaptchaAsync_ValidCaptcha_ValidSolution() => ImageCaptchaTest(); + [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_NoProxy_ValidSolution() => RecaptchaV2InvisibleTest_NoProxy(); + [Fact] public Task SolveRecaptchaV3Async_NoProxy_ValidSolution() => RecaptchaV3Test_NoProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV3EnterpriseTest_NoProxy(); +} diff --git a/CaptchaSharp.Tests/ImageTyperzServiceTests.cs b/CaptchaSharp.Tests/ImageTyperzServiceTests.cs index 9d00875..a6e0221 100644 --- a/CaptchaSharp.Tests/ImageTyperzServiceTests.cs +++ b/CaptchaSharp.Tests/ImageTyperzServiceTests.cs @@ -1,32 +1,44 @@ using CaptchaSharp.Services; using System.Threading.Tasks; using Xunit; +using Xunit.Abstractions; -namespace CaptchaSharp.Tests +namespace CaptchaSharp.Tests; + +public class ImageTyperzFixture : ServiceFixture { - public class ImageTyperzFixture : ServiceFixture + public ImageTyperzFixture() { - public ImageTyperzFixture() - { - Service = new ImageTyperzService(Config.Credentials.ImageTyperzApiKey); - } + Service = new ImageTyperzService(Config.Credentials.ImageTyperzApiKey); } +} - public class ImageTyperzServiceTests : ServiceTests, IClassFixture - { - public ImageTyperzServiceTests(ImageTyperzFixture fixture) : base(fixture) { } - - [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); - [Fact] public Task SolveImageCaptchaAsync_ValidCaptcha_ValidSolution() => ImageCaptchaTest(); - [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); - [Fact] public Task SolveRecaptchaV2Async_WithProxy_ValidSolution() => RecaptchaV2Test_WithProxy(); - [Fact] public Task SolveRecaptchaV3Async_NoProxy_ValidSolution() => RecaptchaV3Test_NoProxy(); - [Fact] public Task SolveRecaptchaV3Async_WithProxy_ValidSolution() => RecaptchaV3Test_WithProxy(); - [Fact] public Task SolveHCaptchaAsync_NoProxy_ValidSolution() => HCaptchaTest_NoProxy(); - [Fact] public Task SolveHCaptchaAsync_WithProxy_ValidSolution() => HCaptchaTest_WithProxy(); - [Fact] public Task SolveGeeTestAsync_NoProxy_ValidSolution() => GeeTestTest_NoProxy(); - [Fact] public Task SolveGeeTestAsync_WithProxy_ValidSolution() => GeeTestTest_WithProxy(); - [Fact] public Task SolveCapyAsync_NoProxy_ValidSolution() => CapyTest_NoProxy(); - [Fact] public Task SolveCapyAsync_WithProxy_ValidSolution() => CapyTest_WithProxy(); - } -} \ No newline at end of file +public class ImageTyperzServiceTests(ImageTyperzFixture fixture, ITestOutputHelper output) + : ServiceTests(fixture, output), IClassFixture +{ + [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); + [Fact] public Task ReportSolution_NoException() => ReportImageSolutionTest(); + [Fact] public Task SolveImageCaptchaAsync_ValidCaptcha_ValidSolution() => ImageCaptchaTest(); + [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); + [Fact] public Task SolveRecaptchaV2Async_WithProxy_ValidSolution() => RecaptchaV2Test_WithProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_NoProxy_ValidSolution() => RecaptchaV2InvisibleTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_WithProxy_ValidSolution() => RecaptchaV2InvisibleTest_WithProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV2EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_WithProxy_ValidSolution() => RecaptchaV2EnterpriseTest_WithProxy(); + [Fact] public Task SolveRecaptchaV3Async_NoProxy_ValidSolution() => RecaptchaV3Test_NoProxy(); + [Fact] public Task SolveRecaptchaV3Async_WithProxy_ValidSolution() => RecaptchaV3Test_WithProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV3EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_WithProxy_ValidSolution() => RecaptchaV3EnterpriseTest_WithProxy(); + [Fact] public Task SolveFuncaptchaAsync_NoProxy_ValidSolution() => FunCaptchaTest_NoProxy(); + [Fact] public Task SolveFuncaptchaAsync_WithProxy_ValidSolution() => FunCaptchaTest_WithProxy(); + [Fact] public Task SolveHCaptchaAsync_NoProxy_ValidSolution() => HCaptchaTest_NoProxy(); + [Fact] public Task SolveHCaptchaAsync_WithProxy_ValidSolution() => HCaptchaTest_WithProxy(); + [Fact] public Task SolveGeeTestAsync_NoProxy_ValidSolution() => GeeTestTest_NoProxy(); + [Fact] public Task SolveGeeTestAsync_WithProxy_ValidSolution() => GeeTestTest_WithProxy(); + [Fact] public Task SolveCapyAsync_NoProxy_ValidSolution() => CapyTest_NoProxy(); + [Fact] public Task SolveCapyAsync_WithProxy_ValidSolution() => CapyTest_WithProxy(); + [Fact] public Task SolveCloudflareTurnstileAsync_NoProxy_ValidSolution() => CloudflareTurnstileTest_NoProxy(); + [Fact] public Task SolveCloudflareTurnstileAsync_WithProxy_ValidSolution() => CloudflareTurnstileTest_WithProxy(); + [Fact] public Task SolveGeeTestV4Async_NoProxy_ValidSolution() => GeeTestV4Test_NoProxy(); + [Fact] public Task SolveGeeTestV4Async_WithProxy_ValidSolution() => GeeTestV4Test_WithProxy(); +} diff --git a/CaptchaSharp.Tests/MetaBypassTechServiceTests.cs b/CaptchaSharp.Tests/MetaBypassTechServiceTests.cs new file mode 100644 index 0000000..c9e04f9 --- /dev/null +++ b/CaptchaSharp.Tests/MetaBypassTechServiceTests.cs @@ -0,0 +1,34 @@ +using System; +using System.Threading.Tasks; +using CaptchaSharp.Services; +using Xunit; +using Xunit.Abstractions; + +namespace CaptchaSharp.Tests; + +public class MetaBypassTechFixture : ServiceFixture +{ + public MetaBypassTechFixture() + { + Service = new MetaBypassTechService( + Config.Credentials.MetaBypassTechClientId, + Config.Credentials.MetaBypassTechClientSecret, + Config.Credentials.MetaBypassTechUsername, + Config.Credentials.MetaBypassTechPassword) + { + Timeout = TimeSpan.FromMinutes(5) + }; + } +} + +public class MetaBypassTechServiceTests(MetaBypassTechFixture fixture, ITestOutputHelper output) + : ServiceTests(fixture, output), IClassFixture +{ + [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); + [Fact] public Task SolveImageCaptchaAsync_InvalidImage_ThrowsException() => ImageCaptchaTest(); + [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_NoProxy_ValidSolution() => RecaptchaV2InvisibleTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV2EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV3Async_NoProxy_ValidSolution() => RecaptchaV3Test_NoProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV3EnterpriseTest_NoProxy(); +} diff --git a/CaptchaSharp.Tests/NextCaptchaServiceTests.cs b/CaptchaSharp.Tests/NextCaptchaServiceTests.cs new file mode 100644 index 0000000..6bc6971 --- /dev/null +++ b/CaptchaSharp.Tests/NextCaptchaServiceTests.cs @@ -0,0 +1,34 @@ +using System.Threading.Tasks; +using CaptchaSharp.Services; +using Xunit; +using Xunit.Abstractions; + +namespace CaptchaSharp.Tests; + +public class NextCaptchaFixture : ServiceFixture +{ + public NextCaptchaFixture() + { + Service = new NextCaptchaService( + Config.Credentials.NextCaptchaApiKey); + } +} + +public class NextCaptchaServiceTests(NextCaptchaFixture fixture, ITestOutputHelper output) + : ServiceTests(fixture, output), IClassFixture +{ + [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); + [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_NoProxy_ValidSolution() => RecaptchaV2InvisibleTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV2EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV3Async_NoProxy_ValidSolution() => RecaptchaV3Test_NoProxy(); + [Fact] public Task SolveRecaptchaV3Async_WithProxy_ValidSolution() => RecaptchaV3Test_WithProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV3EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_WithProxy_ValidSolution() => RecaptchaV3EnterpriseTest_WithProxy(); + [Fact] public Task SolveFuncaptchaAsync_NoProxy_ValidSolution() => FunCaptchaTest_NoProxy(); + [Fact] public Task SolveFuncaptchaAsync_WithProxy_ValidSolution() => FunCaptchaTest_WithProxy(); + [Fact] public Task SolveHCaptchaAsync_NoProxy_ValidSolution() => HCaptchaTest_NoProxy(); + [Fact] public Task SolveHCaptchaAsync_WithProxy_ValidSolution() => HCaptchaTest_WithProxy(); + [Fact] public Task SolveRecaptchaMobileAsync_NoProxy_ValidSolution() => RecaptchaMobileTest_NoProxy(); + [Fact] public Task SolveRecaptchaMobileAsync_WithProxy_ValidSolution() => RecaptchaMobileTest_WithProxy(); +} diff --git a/CaptchaSharp.Tests/NineKwServiceTests.cs b/CaptchaSharp.Tests/NineKwServiceTests.cs new file mode 100644 index 0000000..266abc8 --- /dev/null +++ b/CaptchaSharp.Tests/NineKwServiceTests.cs @@ -0,0 +1,39 @@ +using System.Threading.Tasks; +using CaptchaSharp.Services; +using Xunit; +using Xunit.Abstractions; + +namespace CaptchaSharp.Tests; + +public class NineKwFixture : ServiceFixture +{ + public NineKwFixture() + { + Service = new NineKwService( + Config.Credentials.NineKWApiKey); + } +} + +public class NineKwServiceTests(NineKwFixture fixture, ITestOutputHelper output) + : ServiceTests(fixture, output), IClassFixture +{ + [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); + [Fact] public Task ReportSolutionAsync_ValidCaptcha_Reported() => ReportImageSolutionTest(); + [Fact] public Task ReportRecaptchaSolutionAsync_ValidCaptcha_Reported() => ReportRecaptchaSolutionTest(); + [Fact] public Task SolveTextCaptchaAsync_ValidCaptcha_ValidSolution() => TextCaptchaTest(); + [Fact] public Task SolveImageCaptchaAsync_ValidCaptcha_ValidSolution() => ImageCaptchaTest(); + [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); + [Fact] public Task SolveRecaptchaV2Async_WithProxy_ValidSolution() => RecaptchaV2Test_WithProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_NoProxy_ValidSolution() => RecaptchaV2InvisibleTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_WithProxy_ValidSolution() => RecaptchaV2InvisibleTest_WithProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV2EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_WithProxy_ValidSolution() => RecaptchaV2EnterpriseTest_WithProxy(); + [Fact] public Task SolveRecaptchaV3Async_NoProxy_ValidSolution() => RecaptchaV3Test_NoProxy(); + [Fact] public Task SolveRecaptchaV3Async_WithProxy_ValidSolution() => RecaptchaV3Test_WithProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV3EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_WithProxy_ValidSolution() => RecaptchaV3EnterpriseTest_WithProxy(); + [Fact] public Task SolveFuncaptchaAsync_NoProxy_ValidSolution() => FunCaptchaTest_NoProxy(); + [Fact] public Task SolveFuncaptchaAsync_WithProxy_ValidSolution() => FunCaptchaTest_WithProxy(); + [Fact] public Task SolveHCaptchaAsync_NoProxy_ValidSolution() => HCaptchaTest_NoProxy(); + [Fact] public Task SolveHCaptchaAsync_WithProxy_ValidSolution() => HCaptchaTest_WithProxy(); +} diff --git a/CaptchaSharp.Tests/NoCaptchaAiServiceTests.cs b/CaptchaSharp.Tests/NoCaptchaAiServiceTests.cs new file mode 100644 index 0000000..6d3c413 --- /dev/null +++ b/CaptchaSharp.Tests/NoCaptchaAiServiceTests.cs @@ -0,0 +1,24 @@ +using System.Threading.Tasks; +using CaptchaSharp.Services; +using Xunit; +using Xunit.Abstractions; + +namespace CaptchaSharp.Tests; + +public class NoCaptchaAiFixture : ServiceFixture +{ + public NoCaptchaAiFixture() + { + Service = new NoCaptchaAiService( + Config.Credentials.NoCaptchaAiApiKey); + } +} + +public class NoCaptchaAiServiceTests(NoCaptchaAiFixture fixture, ITestOutputHelper output) + : ServiceTests(fixture, output), IClassFixture +{ + [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); + [Fact] public Task SolveImageCaptchaAsync_ValidCaptcha_ValidSolution() => ImageCaptchaTest(); + [Fact] public Task SolveHCaptchaAsync_NoProxy_ValidSolution() => HCaptchaTest_NoProxy(); + [Fact] public Task SolveHCaptchaAsync_WithProxy_ValidSolution() => HCaptchaTest_WithProxy(); +} diff --git a/CaptchaSharp.Tests/NopechaServiceTests.cs b/CaptchaSharp.Tests/NopechaServiceTests.cs new file mode 100644 index 0000000..3905a7b --- /dev/null +++ b/CaptchaSharp.Tests/NopechaServiceTests.cs @@ -0,0 +1,32 @@ +using System.Threading.Tasks; +using CaptchaSharp.Services; +using Xunit; +using Xunit.Abstractions; + +namespace CaptchaSharp.Tests; + +public class NopechaFixture : ServiceFixture +{ + public NopechaFixture() + { + Service = new NopechaService(Config.Credentials.NopechaApiKey); + } +} + +public class NopechaServiceTests(NopechaFixture fixture, ITestOutputHelper output) + : ServiceTests(fixture, output), IClassFixture +{ + [Fact] public Task GetBalanceAsync_ValidKey_GetsBalance() => BalanceTest(); + [Fact] public Task SolveImageCaptchaAsync_ValidCaptcha_ValidSolution() => ImageCaptchaTest(); + [Fact] public Task SolveRecaptchaV2Async_NoProxy_ValidSolution() => RecaptchaV2Test_NoProxy(); + [Fact] public Task SolveRecaptchaV2InvisibleAsync_NoProxy_ValidSolution() => RecaptchaV2InvisibleTest_NoProxy(); + [Fact] public Task SolveRecaptchaV2EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV2EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV3Async_NoProxy_ValidSolution() => RecaptchaV3Test_NoProxy(); + [Fact] public Task SolveRecaptchaV3Async_WithProxy_ValidSolution() => RecaptchaV3Test_WithProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_NoProxy_ValidSolution() => RecaptchaV3EnterpriseTest_NoProxy(); + [Fact] public Task SolveRecaptchaV3EnterpriseAsync_WithProxy_ValidSolution() => RecaptchaV3EnterpriseTest_WithProxy(); + [Fact] public Task SolveHCaptchaAsync_NoProxy_ValidSolution() => HCaptchaTest_NoProxy(); + [Fact] public Task SolveHCaptchaAsync_WithProxy_ValidSolution() => HCaptchaTest_WithProxy(); + [Fact] public Task SolveCloudflareTurnstileAsync_NoProxy_ValidSolution() => CloudflareTurnstileTest_NoProxy(); + [Fact] public Task SolveCloudflareTurnstileAsync_WithProxy_ValidSolution() => CloudflareTurnstileTest_WithProxy(); +} diff --git a/CaptchaSharp.Tests/ServiceFixture.cs b/CaptchaSharp.Tests/ServiceFixture.cs index 888ea6c..2c960a9 100644 --- a/CaptchaSharp.Tests/ServiceFixture.cs +++ b/CaptchaSharp.Tests/ServiceFixture.cs @@ -1,14 +1,10 @@ -namespace CaptchaSharp.Tests -{ - public abstract class ServiceFixture - { - private readonly ConfigFixture configFixture; - public Config Config => configFixture.Config; - public CaptchaService Service { get; set; } +using CaptchaSharp.Services; + +namespace CaptchaSharp.Tests; - public ServiceFixture() - { - configFixture = new ConfigFixture(); - } - } +public abstract class ServiceFixture +{ + private readonly ConfigFixture _configFixture = new(); + public Config Config => _configFixture.Config; + public required CaptchaService Service { get; init; } } diff --git a/CaptchaSharp.Tests/ServiceTests.cs b/CaptchaSharp.Tests/ServiceTests.cs index 4c718df..8df91f8 100644 --- a/CaptchaSharp.Tests/ServiceTests.cs +++ b/CaptchaSharp.Tests/ServiceTests.cs @@ -1,212 +1,646 @@ -using CaptchaSharp.Enums; +using CaptchaSharp.Enums; using CaptchaSharp.Models; using Newtonsoft.Json.Linq; using System; +using System.Collections.Generic; +using System.Net; using System.Net.Http; using System.Text.RegularExpressions; using System.Threading.Tasks; +using CaptchaSharp.Extensions; +using CaptchaSharp.Models.CaptchaOptions; +using CaptchaSharp.Services; using Xunit; +using Xunit.Abstractions; -namespace CaptchaSharp.Tests +namespace CaptchaSharp.Tests; + +public class ServiceTests { - public class ServiceTests + private readonly ServiceFixture _fixture; + private readonly ITestOutputHelper _output; + + private const string _captchaImageBase64 = "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"; + + private CaptchaService Service => _fixture.Service; + + protected ServiceTests(ServiceFixture fixture, ITestOutputHelper output) { - private readonly ServiceFixture fixture; - protected CaptchaService Service => fixture.Service; + this._fixture = fixture; + _output = output; + } - public ServiceTests(ServiceFixture fixture) - { - this.fixture = fixture; - } + protected static Task ShouldNotBeSupported(Func method) => Assert.ThrowsAsync(method); - protected static Task ShouldNotBeSupported(Func method) => Assert.ThrowsAsync(method); + protected async Task BalanceTest() + { + var balance = await Service.GetBalanceAsync(); + Assert.True(balance > 0); + + _output.WriteLine($"Balance: {balance}"); + } - protected async Task BalanceTest() + protected async Task ReportImageSolutionTest(bool correct = true) + { + var options = new ImageCaptchaOptions { - var balance = await Service.GetBalanceAsync(); - Assert.True(balance > 0); - } + IsPhrase = true, + CaseSensitive = true, + CharacterSet = CharacterSet.NotSpecified, + RequiresCalculation = false, + MinLength = 0, + MaxLength = 0, + CaptchaLanguageGroup = CaptchaLanguageGroup.NotSpecified, + CaptchaLanguage = CaptchaLanguage.NotSpecified, + TextInstructions = "" + }; + + var solution = await Service.SolveImageCaptchaAsync( + base64: _captchaImageBase64, + options); + + await Service.ReportSolutionAsync( + solution.Id, CaptchaType.ImageCaptcha, correct); + + Assert.True(true); + } + + protected async Task ReportRecaptchaSolutionTest(bool correct = true) + { + var solution = await Service.SolveRecaptchaV2Async( + siteKey: "6LfD3PIbAAAAAJs_eEHvoOl75_83eXSqpPSRFJ_u", + siteUrl: "https://2captcha.com/demo/recaptcha-v2", + dataS: "", + enterprise: false, + invisible: false); + + await Service.ReportSolutionAsync( + solution.Id, CaptchaType.ReCaptchaV2, correct); + + Assert.True(true); + } - protected async Task TextCaptchaTest() + protected async Task TextCaptchaTest() + { + var options = new TextCaptchaOptions { - var options = new TextCaptchaOptions - { - CaptchaLanguageGroup = CaptchaLanguageGroup.NotSpecified, - CaptchaLanguage = CaptchaLanguage.NotSpecified - }; + CaptchaLanguageGroup = CaptchaLanguageGroup.NotSpecified, + CaptchaLanguage = CaptchaLanguage.NotSpecified + }; - var solution = await Service.SolveTextCaptchaAsync( - text: "What is 2+2?", - options); + var solution = await Service.SolveTextCaptchaAsync( + text: "What is 2+2?", + options); - Assert.Equal("4", solution.Response); - } + Assert.Equal("4", solution.Response); + } - protected async Task ImageCaptchaTest() + protected async Task ImageCaptchaTest() + { + var options = new ImageCaptchaOptions { - var options = new ImageCaptchaOptions - { - IsPhrase = true, - CaseSensitive = true, - CharacterSet = CharacterSet.NotSpecified, - RequiresCalculation = false, - MinLength = 0, - MaxLength = 0, - CaptchaLanguageGroup = CaptchaLanguageGroup.NotSpecified, - CaptchaLanguage = CaptchaLanguage.NotSpecified, - TextInstructions = "" - }; - - var solution = await Service.SolveImageCaptchaAsync( - base64: "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", - options); - - Assert.Equal("w68hp", solution.Response.Replace(" ", "").ToLower()); - } + IsPhrase = true, + CaseSensitive = true, + CharacterSet = CharacterSet.NotSpecified, + RequiresCalculation = false, + MinLength = 0, + MaxLength = 0, + CaptchaLanguageGroup = CaptchaLanguageGroup.NotSpecified, + CaptchaLanguage = CaptchaLanguage.NotSpecified, + TextInstructions = "" + }; + + var solution = await Service.SolveImageCaptchaAsync( + base64: _captchaImageBase64, + options); + + Assert.Equal("w68hp", solution.Response.Replace(" ", "").ToLower()); + } - private async Task RecaptchaV2Test(Proxy proxy) - { - var solution = await Service.SolveRecaptchaV2Async( - siteKey: "6Ld2sf4SAAAAAKSgzs0Q13IZhY02Pyo31S2jgOB5", - siteUrl: "https://patrickhlauke.github.io/recaptcha/", - dataS: "", - enterprise: false, - invisible: false, - proxy); - - Assert.NotEqual(string.Empty, solution.Response); - } + private async Task RecaptchaV2Test(SessionParams? sessionParams) + { + var solution = await Service.SolveRecaptchaV2Async( + siteKey: "6LfD3PIbAAAAAJs_eEHvoOl75_83eXSqpPSRFJ_u", + siteUrl: "https://2captcha.com/demo/recaptcha-v2", + dataS: "", + enterprise: false, + invisible: false, + sessionParams); + + Assert.NotEqual(string.Empty, solution.Response); + + _output.WriteLine($"Captcha ID: {solution.Id}"); + _output.WriteLine($"Response: {solution.Response}"); + } - protected Task RecaptchaV2Test_NoProxy() => RecaptchaV2Test(null); + protected Task RecaptchaV2Test_NoProxy() => RecaptchaV2Test(null); - protected Task RecaptchaV2Test_WithProxy() => RecaptchaV2Test(fixture.Config.Proxy); + protected Task RecaptchaV2Test_WithProxy() => RecaptchaV2Test(_fixture.Config.SessionParams); - private async Task RecaptchaV3Test(Proxy proxy) - { - var solution = await Service.SolveRecaptchaV3Async( - siteKey: "6LcFcoAUAAAAAN7Um8IRZOtbzgsV5ei2meTmRi6m", - siteUrl: "https://contactform7.com/contact/", - action: "action", - minScore: 0.3f, - enterprise: false, - proxy); - - Assert.NotEqual(string.Empty, solution.Response); - } + private async Task RecaptchaV2InvisibleTest(SessionParams? sessionParams) + { + var solution = await Service.SolveRecaptchaV2Async( + siteKey: "6LdO5_IbAAAAAAeVBL9TClS19NUTt5wswEb3Q7C5", + siteUrl: "https://2captcha.com/demo/recaptcha-v2-invisible", + dataS: "", + enterprise: false, + invisible: true, + sessionParams); + + Assert.NotEqual(string.Empty, solution.Response); + + _output.WriteLine($"Captcha ID: {solution.Id}"); + _output.WriteLine($"Response: {solution.Response}"); + } + + protected Task RecaptchaV2InvisibleTest_NoProxy() => RecaptchaV2InvisibleTest(null); + + protected Task RecaptchaV2InvisibleTest_WithProxy() => RecaptchaV2InvisibleTest(_fixture.Config.SessionParams); + + private async Task RecaptchaV2EnterpriseTest(SessionParams? sessionParams) + { + var solution = await Service.SolveRecaptchaV2Async( + siteKey: "6Lf26sUnAAAAAIKLuWNYgRsFUfmI-3Lex3xT5N-s", + siteUrl: "https://2captcha.com/demo/recaptcha-v2-enterprise", + dataS: "", + enterprise: true, + invisible: true, + sessionParams); + + Assert.NotEqual(string.Empty, solution.Response); + + _output.WriteLine($"Captcha ID: {solution.Id}"); + _output.WriteLine($"Response: {solution.Response}"); + } + + protected Task RecaptchaV2EnterpriseTest_NoProxy() => RecaptchaV2EnterpriseTest(null); + + protected Task RecaptchaV2EnterpriseTest_WithProxy() => RecaptchaV2EnterpriseTest(_fixture.Config.SessionParams); + + private async Task RecaptchaV3Test(SessionParams? sessionParams) + { + var solution = await Service.SolveRecaptchaV3Async( + siteKey: "6LfB5_IbAAAAAMCtsjEHEHKqcB9iQocwwxTiihJu", + siteUrl: "https://2captcha.com/demo/recaptcha-v3", + action: "demo_action", + minScore: 0.9f, + enterprise: false, + sessionParams); + + Assert.NotEqual(string.Empty, solution.Response); + + _output.WriteLine($"Captcha ID: {solution.Id}"); + _output.WriteLine($"Response: {solution.Response}"); + } - protected Task RecaptchaV3Test_NoProxy() => RecaptchaV3Test(null); - protected Task RecaptchaV3Test_WithProxy() => RecaptchaV3Test(fixture.Config.Proxy); + protected Task RecaptchaV3Test_NoProxy() => RecaptchaV3Test(null); + protected Task RecaptchaV3Test_WithProxy() => RecaptchaV3Test(_fixture.Config.SessionParams); - private async Task FunCaptchaTest(Proxy proxy) - { - // TODO: Find a valid funcaptcha to test! - var solution = await Service.SolveFuncaptchaAsync( - publicKey: "69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC", - serviceUrl: "https://api.funcaptcha.com/fc/api/nojs/", - siteUrl: "https://api.funcaptcha.com/fc/api/nojs/", - noJS: false, - proxy); - - Assert.NotEqual(string.Empty, solution.Response); - } + private async Task RecaptchaV3EnterpriseTest(SessionParams? sessionParams) + { + var solution = await Service.SolveRecaptchaV3Async( + siteKey: "6Lel38UnAAAAAMRwKj9qLH2Ws4Tf2uTDQCyfgR6b", + siteUrl: "https://2captcha.com/demo/recaptcha-v3-enterprise", + action: "demo_action", + minScore: 0.9f, + enterprise: true, + sessionParams); + + Assert.NotEqual(string.Empty, solution.Response); + + _output.WriteLine($"Captcha ID: {solution.Id}"); + _output.WriteLine($"Response: {solution.Response}"); + } + + protected Task RecaptchaV3EnterpriseTest_NoProxy() => RecaptchaV3EnterpriseTest(null); + + protected Task RecaptchaV3EnterpriseTest_WithProxy() => RecaptchaV3EnterpriseTest(_fixture.Config.SessionParams); + + private async Task FunCaptchaTest(SessionParams? sessionParams) + { + var solution = await Service.SolveFuncaptchaAsync( + publicKey: "3EE79F8D-13A6-474B-9278-448EA19F79B3", + serviceUrl: "https://client-api.arkoselabs.com", + siteUrl: "https://www.arkoselabs.com/arkose-matchkey/", + noJs: false, + data: null, + sessionParams); + + Assert.NotEqual(string.Empty, solution.Response); + + _output.WriteLine($"Captcha ID: {solution.Id}"); + _output.WriteLine($"Response: {solution.Response}"); + } - protected Task FunCaptchaTest_NoProxy() => FunCaptchaTest(null); - protected Task FunCaptchaTest_WithProxy() => FunCaptchaTest(fixture.Config.Proxy); + protected Task FunCaptchaTest_NoProxy() => FunCaptchaTest(null); + protected Task FunCaptchaTest_WithProxy() => FunCaptchaTest(_fixture.Config.SessionParams); - private async Task HCaptchaTest(Proxy proxy) - { - var solution = await Service.SolveHCaptchaAsync( - siteKey: "13257c82-e129-4f09-a733-2a7cb3102832", - siteUrl: "https://dashboard.hcaptcha.com/signup", - proxy); + private async Task HCaptchaTest(SessionParams? sessionParams) + { + var solution = await Service.SolveHCaptchaAsync( + siteKey: "f7de0da3-3303-44e8-ab48-fa32ff8ccc7b", + siteUrl: "https://2captcha.com/demo/hcaptcha", + invisible: false, + enterprisePayload: null, + sessionParams); + + Assert.NotEqual(string.Empty, solution.Response); + + _output.WriteLine($"Captcha ID: {solution.Id}"); + _output.WriteLine($"Response: {solution.Response}"); + } - Assert.NotEqual(string.Empty, solution.Response); - } + protected Task HCaptchaTest_NoProxy() => HCaptchaTest(null); + protected Task HCaptchaTest_WithProxy() => HCaptchaTest(_fixture.Config.SessionParams); + + private async Task KeyCaptchaTest(SessionParams? sessionParams) + { + // Get the required parameters from the page since they are not static + const string siteUrl = "https://www.keycaptcha.com/contact-us/"; + using var httpClient = new HttpClient(); + using var response = await httpClient.GetAsync(siteUrl); + var pageSource = await response.Content.ReadAsStringAsync(); + + var userId = Regex.Match(pageSource, "var s_s_c_user_id = '([^']*)'").Groups[1].Value; + var sessionId = Regex.Match(pageSource, "var s_s_c_session_id = '([^']*)'").Groups[1].Value; + var webServerSign1 = Regex.Match(pageSource, "var s_s_c_web_server_sign = '([^']*)'").Groups[1].Value; + var webServerSign2 = Regex.Match(pageSource, "var s_s_c_web_server_sign2 = '([^']*)'").Groups[1].Value; + + var solution = await Service.SolveKeyCaptchaAsync( + userId, + sessionId, + webServerSign1, + webServerSign2, + siteUrl, + sessionParams); + + Assert.NotEqual(string.Empty, solution.Response); + + _output.WriteLine($"Captcha ID: {solution.Id}"); + _output.WriteLine($"Response: {solution.Response}"); + } - protected Task HCaptchaTest_NoProxy() => HCaptchaTest(null); - protected Task HCaptchaTest_WithProxy() => HCaptchaTest(fixture.Config.Proxy); + protected Task KeyCaptchaTest_NoProxy() => KeyCaptchaTest(null); + protected Task KeyCaptchaTest_WithProxy() => KeyCaptchaTest(_fixture.Config.SessionParams); - private async Task KeyCaptchaTest(Proxy proxy) - { - // Get the required parameters from the page since they are not static - var siteUrl = $"{"https"}://www.keycaptcha.com/contact-us/"; - using var httpClient = new HttpClient(); - using var response = await httpClient.GetAsync(siteUrl); - var pageSource = await response.Content.ReadAsStringAsync(); - - var userId = Regex.Match(pageSource, "var s_s_c_user_id = '([^']*)'").Groups[1].Value; - var sessionId = Regex.Match(pageSource, "var s_s_c_session_id = '([^']*)'").Groups[1].Value; - var webServerSign1 = Regex.Match(pageSource, "var s_s_c_web_server_sign = '([^']*)'").Groups[1].Value; - var webServerSign2 = Regex.Match(pageSource, "var s_s_c_web_server_sign2 = '([^']*)'").Groups[1].Value; - - var solution = await Service.SolveKeyCaptchaAsync( - userId, - sessionId, - webServerSign1, - webServerSign2, - siteUrl, - proxy); - - Assert.NotEqual(string.Empty, solution.Response); - } + private async Task GeeTestTest(SessionParams? sessionParams) + { + // Get the required parameters from the page since they are not static + var unixTime = DateTimeOffset.Now.ToUnixTimeMilliseconds(); + var siteUrl = $"https://www.geetest.com/demo/gt/register-enFullpage-official?t={unixTime}"; + using var httpClient = new HttpClient(); + using var response = await httpClient.GetAsync(siteUrl); + var pageSource = await response.Content.ReadAsStringAsync(); + var obj = JObject.Parse(pageSource); + + var gt = obj.Value("gt")!; + var challenge = obj.Value("challenge")!; + + var solution = await Service.SolveGeeTestAsync( + gt, + challenge, + siteUrl, + apiServer: "api.geetest.com", + sessionParams); + + Assert.NotEqual("", solution.Challenge); + Assert.NotEqual("", solution.SecCode); + Assert.NotEqual("", solution.Validate); + + _output.WriteLine($"Captcha ID: {solution.Id}"); + _output.WriteLine($"Challenge: {solution.Challenge}"); + _output.WriteLine($"SecCode: {solution.SecCode}"); + _output.WriteLine($"Validate: {solution.Validate}"); + } - protected Task KeyCaptchaTest_NoProxy() => KeyCaptchaTest(null); - protected Task KeyCaptchaTest_WithProxy() => KeyCaptchaTest(fixture.Config.Proxy); + protected Task GeeTestTest_NoProxy() => GeeTestTest(null); + protected Task GeeTestTest_WithProxy() => GeeTestTest(_fixture.Config.SessionParams); - private async Task GeeTestTest(Proxy proxy) - { - // Get the required parameters from the page since they are not static - var unixTime = DateTimeOffset.Now.ToUnixTimeMilliseconds(); - var siteUrl = $"{"https"}://www.geetest.com/demo/gt/register-enFullpage-official?t={unixTime}"; - using var httpClient = new HttpClient(); - using var response = await httpClient.GetAsync(siteUrl); - var pageSource = await response.Content.ReadAsStringAsync(); - var obj = JObject.Parse(pageSource); - - var gt = obj.Value("gt"); - var challenge = obj.Value("challenge"); - - var solution = await Service.SolveGeeTestAsync( - gt, - challenge, - apiServer: "api.geetest.com", - siteUrl, - proxy); - - Assert.NotEqual("", solution.Challenge); - Assert.NotEqual("", solution.SecCode); - Assert.NotEqual("", solution.Validate); - } + private async Task CapyTest(SessionParams? sessionParams) + { + var solution = await Service.SolveCapyAsync( + siteKey: "PUZZLE_Cme4hZLjuZRMYC3uh14C52D3uNms5w", + siteUrl: $"{"https"}://www.capy.me/account/signin", + sessionParams); + + Assert.NotEqual(string.Empty, solution.ChallengeKey); + Assert.NotEqual(string.Empty, solution.CaptchaKey); + Assert.NotEqual(string.Empty, solution.Answer); + + _output.WriteLine($"Captcha ID: {solution.Id}"); + _output.WriteLine($"ChallengeKey: {solution.ChallengeKey}"); + _output.WriteLine($"CaptchaKey: {solution.CaptchaKey}"); + _output.WriteLine($"Answer: {solution.Answer}"); + } - protected Task GeeTestTest_NoProxy() => GeeTestTest(null); - protected Task GeeTestTest_WithProxy() => GeeTestTest(fixture.Config.Proxy); + protected Task CapyTest_NoProxy() => CapyTest(null); + protected Task CapyTest_WithProxy() => CapyTest(_fixture.Config.SessionParams); - private async Task CapyTest(Proxy proxy) + // Proxy and User-Agent required + private async Task DataDomeTest(SessionParams sessionParams) + { + const string site = "https://antoinevastel.com/bots/datadome"; + + // If it doesn't work, try a few times until it triggers + // the captcha + var cookieContainer = new CookieContainer(); + using var httpClientHandler = new HttpClientHandler(); + httpClientHandler.UseCookies = true; + httpClientHandler.CookieContainer = cookieContainer; + using var httpClient = new HttpClient(httpClientHandler); + + if (string.IsNullOrEmpty(sessionParams.UserAgent)) { - var solution = await Service.SolveCapyAsync( - siteKey: "PUZZLE_Cme4hZLjuZRMYC3uh14C52D3uNms5w", - siteUrl: $"{"https"}://www.capy.me/account/signin", - proxy); - - Assert.NotEqual(string.Empty, solution.ChallengeKey); - Assert.NotEqual(string.Empty, solution.CaptchaKey); - Assert.NotEqual(string.Empty, solution.Answer); + throw new ArgumentException("User-Agent is required"); } + + // The User-Agent must be the same as the one used to get the page + httpClient.DefaultRequestHeaders.Add("User-Agent", sessionParams.UserAgent); + + using var response = await httpClient.GetAsync(site); + var pageSource = await response.Content.ReadAsStringAsync(); + + var host = Regex.Match(pageSource, "'host':'([^']*)'").Groups[1].Value; + var initialCid = Regex.Match(pageSource, "'cid':'([^']*)'").Groups[1].Value; + var t = Regex.Match(pageSource, "'t':'([^']*)'").Groups[1].Value; + var s = Regex.Match(pageSource, @"'s':(\d+)").Groups[1].Value; + var e = Regex.Match(pageSource, "'e':'([^']*)'").Groups[1].Value; + var hsh = Regex.Match(pageSource, "'hsh':'([^']*)'").Groups[1].Value; + + // Get cid from "datadome" cookie + var cid = cookieContainer.GetCookies(new Uri(site))["datadome"]?.Value; + sessionParams.Cookies = new Dictionary + { + ["datadome"] = cid! + }; + + var captchaUrl = + $"https://{host}/captcha/?initialCid={WebUtility.UrlEncode(initialCid)}&hash={hsh}&cid={cid}&t={t}&referer={WebUtility.UrlEncode(site)}&s={s}&e={e}&dm=cd"; + + var solution = await Service.SolveDataDomeAsync( + siteUrl: site, + captchaUrl: captchaUrl, + sessionParams); + + Assert.NotEqual(string.Empty, solution.Response); + + _output.WriteLine($"Captcha ID: {solution.Id}"); + _output.WriteLine($"Response: {solution.Response}"); + } - protected Task CapyTest_NoProxy() => CapyTest(null); - protected Task CapyTest_WithProxy() => CapyTest(fixture.Config.Proxy); + protected Task DataDomeTest_WithProxy() => DataDomeTest(_fixture.Config.SessionParams); - private async Task DataDomeTest(Proxy proxy) - { - var solution = await Service.SolveDataDomeAsync( - siteUrl: "", // Fill this when testing - captchaUrl: "", // Fill this when testing - proxy); + private async Task CloudflareTurnstileTest(SessionParams? sessionParams) + { + var solution = await Service.SolveCloudflareTurnstileAsync( + siteKey: "0x4AAAAAAAVrOwQWPlm3Bnr5", + siteUrl: "https://2captcha.com/demo/cloudflare-turnstile", + sessionParams: sessionParams); + + Assert.NotEqual(string.Empty, solution.Response); + + _output.WriteLine($"Captcha ID: {solution.Id}"); + _output.WriteLine($"Response: {solution.Response}"); + _output.WriteLine($"User-Agent: {solution.UserAgent}"); + } + + protected Task CloudflareTurnstileTest_NoProxy() => CloudflareTurnstileTest(new SessionParams + { + // User-Agent required + UserAgent = _fixture.Config.SessionParams.UserAgent + }); + + protected Task CloudflareTurnstileTest_WithProxy() => CloudflareTurnstileTest(_fixture.Config.SessionParams); - Assert.NotEqual(string.Empty, solution.Response); - } + private async Task LeminCroppedTest(SessionParams? sessionParams) + { + var solution = await Service.SolveLeminCroppedAsync( + captchaId: "CROPPED_3dfdd5c_d1872b526b794d83ba3b365eb15a200b", + siteUrl: "https://2captcha.com/demo/lemin", + sessionParams: sessionParams); + + Assert.NotEqual(string.Empty, solution.Answer); + Assert.NotEqual(string.Empty, solution.ChallengeId); + + _output.WriteLine($"Captcha ID: {solution.Id}"); + _output.WriteLine($"Answer: {solution.Answer}"); + _output.WriteLine($"Challenge ID: {solution.ChallengeId}"); + } + + protected Task LeminCroppedTest_NoProxy() => LeminCroppedTest(null); + + protected Task LeminCroppedTest_WithProxy() => LeminCroppedTest(_fixture.Config.SessionParams); + + private async Task AmazonWafTest(SessionParams? sessionParams) + { + using var httpClient = new HttpClient(); + using var response = await httpClient.GetAsync("https://nopecha.com/captcha/awscaptcha"); + var pageSource = await response.Content.ReadAsStringAsync(); + + var captchaPage = Regex.Match(pageSource, "