Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions CapMonsterCloud.Client.IntegrationTests/IntegrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,52 @@
actual.Should().BeEquivalentTo(expectedResult);
}

[Test]
public async Task Imperva_ShouldSolve()
{
var clientKey = Gen.RandomString();
var taskId = Gen.RandomInt();

var captchaRequest = ObjectGen.CustomTask.CreateImpervaTask();
var expectedResult = ObjectGen.CustomTask.CreateImpervaSolution();

var expectedRequests = new List<(RequestType Type, string ExpectedRequest)>
{
(
Type: RequestType.CreateTask,
ExpectedRequest: JsonConvert.SerializeObject(new
{ clientKey = clientKey, task = captchaRequest, softId = 53 })
),
(
Type: RequestType.GetTaskResult,
ExpectedRequest: JsonConvert.SerializeObject(new { clientKey = clientKey, taskId = taskId })
),
};

var captchaResults = new List<object>
{
new { taskId = taskId, errorId = 0, errorCode = (string)null! },
new
{
status = "ready",
solution = new
{
domains = expectedResult.Solution.Domains
},
errorId = 0,
errorCode = (string)null!
}
};

var sut = new Sut(clientKey);
sut.SetupHttpServer(captchaResults);

var actual = await sut.SolveAsync(captchaRequest);

sut.GetActualRequests().Should().BeEquivalentTo(expectedRequests);
actual.Should().BeEquivalentTo(expectedResult);
}

[Test]
public async Task RecaptchaComplexImageTask_ShouldSolve()
{
Expand Down Expand Up @@ -636,7 +682,7 @@
}

[Test]
public async Task RecaptchaV2_IncorrectProxyPort_ShouldThrowArgumentException()

Check warning on line 685 in CapMonsterCloud.Client.IntegrationTests/IntegrationTests.cs

View workflow job for this annotation

GitHub Actions / build

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 685 in CapMonsterCloud.Client.IntegrationTests/IntegrationTests.cs

View workflow job for this annotation

GitHub Actions / build

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
{
Action actual = () => ObjectGen.RecaptchaV2.CreateTask(
proxyPort: Gen.RandomInt(65535));
Expand Down
31 changes: 31 additions & 0 deletions CapMonsterCloud.Client.IntegrationTests/ObjectGen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,37 @@ public static CaptchaResult<CustomTaskResponse> CreateBasiliskSolution()
}
};
}

public static ImpervaCustomTaskRequest CreateImpervaTask()
{
return new ImpervaCustomTaskRequest(Gen.RandomString(), Gen.RandomString(), Gen.RandomString())
{
WebsiteUrl = Gen.RandomUri().ToString(),
UserAgent = Gen.UserAgent(),
Proxy = new ProxyContainer(Gen.RandomString(), Gen.RandomInt(0, 65535), Gen.RandomEnum<ProxyType>(), Gen.RandomString(), Gen.RandomString())
};
}

public static CaptchaResult<CustomTaskResponse> CreateImpervaSolution()
{
return new CaptchaResult<CustomTaskResponse>
{
Error = null,
Solution = new CustomTaskResponse
{
Domains = new Dictionary<string, CustomTaskResponse.DomainInfo>
{
{
Gen.RandomString(),
new CustomTaskResponse.DomainInfo()
{
Cookies = new Dictionary<string, string> { { Gen.RandomString(), Gen.RandomString() } },
}
}
}
}
};
}
}

public static class AmazonWaf
Expand Down
3 changes: 3 additions & 0 deletions CapMonsterCloud.Client.IntegrationTests/Sut.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ public async Task<CaptchaResult<CustomTaskResponse>> SolveAsync(
public async Task<CaptchaResult<BinanceTaskResponse>> SolveAsync(
BinanceTaskRequest request) => await _cloudClient.SolveAsync<BinanceTaskResponse>(request);

public async Task<CaptchaResult<CustomTaskResponse>> SolveAsync(
ImpervaCustomTaskRequest request) => await _cloudClient.SolveAsync<CustomTaskResponse>(request);

public async Task<decimal> GetBalanceAsync()
{
return await _cloudClient.GetBalanceAsync();
Expand Down
4 changes: 2 additions & 2 deletions CapMonsterCloud.Client/CapMonsterCloud.Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageIcon>logo.png</PackageIcon>
<RepositoryUrl>https://github.com/ZennoLab/capmonstercloud-client-dotnet</RepositoryUrl>
<Version>2.0.0</Version>
<PackageReleaseNotes>Changed way of using proxy</PackageReleaseNotes>
<Version>2.1.0</Version>
<PackageReleaseNotes>Added Imperva CustomTask</PackageReleaseNotes>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,16 @@ private static GetResultTimeouts GetTimeouts(Type type)
RequestsInterval = TimeSpan.FromSeconds(1),
Timeout = TimeSpan.FromSeconds(20)
}
}
},
{
typeof(ImpervaCustomTaskRequest),
new GetResultTimeouts
{
FirstRequestDelay = TimeSpan.FromSeconds(1),
RequestsInterval = TimeSpan.FromSeconds(1),
Timeout = TimeSpan.FromSeconds(15)
}
},
};
}
}
23 changes: 21 additions & 2 deletions CapMonsterCloud.Client/Requests/DataDomeCustomTaskRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,28 @@
/// <summary>
/// DataDome CustomTask recognition request
/// </summary>
public sealed class DataDomeCustomTaskRequest : DataDomeCustomTaskRequestBase
public sealed class DataDomeCustomTaskRequest : CustomTaskRequestBase
{
/// <inheritdoc/>
public DataDomeCustomTaskRequest(string datadomeCookie, string captchaUrl = null, string htmlPageBase64 = null) : base(datadomeCookie, captchaUrl, htmlPageBase64) { }
public override string Class => "DataDome";

/// <summary>
///
/// These values will be set to Metadata property.
///
/// - captchaUrl: "captchaUrl": "..."
/// Field is required if metadata.htmlPageBase64 is not filled.
/// You can take the link from the page with the captcha.
/// Often it looks like https://geo.captcha-delivery.com/captcha/?initialCid=...
///
/// - htmlPageBase64: "htmlPageBase64": "PGh0bWw+PGhlYWQ+PHRpdGxlPmJs...N0E5QTA1"
/// Field is required if 'captchaUrl' is not filled.
/// A base64 encoded html page that comes with a 403 code and a Set-Cookie: datadome="..." header in response to a get request to the target site.
///
/// - datadomeCookie: "datadomeCookie": "datadome=6BvxqELMoorFNoo7GT1...JyfP_mhz"
/// Field is required. Your cookies from datadome. You can get it on the page using "document.cookie" or in the Set-Cookie request header: "datadome=..."
///
/// </summary>
public DataDomeCustomTaskRequest(string datadomeCookie, string captchaUrl, string htmlPageBase64) => Metadata = new { datadomeCookie, captchaUrl, htmlPageBase64 };
}
}
30 changes: 0 additions & 30 deletions CapMonsterCloud.Client/Requests/DataDomeCustomTaskRequestBase.cs

This file was deleted.

28 changes: 28 additions & 0 deletions CapMonsterCloud.Client/Requests/ImpervaCustomTaskRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
namespace Zennolab.CapMonsterCloud.Requests
{
/// <summary>
/// Imperva CustomTask recognition request
/// </summary>
public class ImpervaCustomTaskRequest : CustomTaskRequestBase
{
/// <inheritdoc/>
public override string Class => "Imperva";

/// <summary>
///
/// These values will be set to Metadata property.
///
/// - incapsulaScriptBase64: "incapsulaScriptBase64": "..."
/// the base64-encoded content of the Incapsula JavaScript script. To obtain this value, you need to go to the script page.
/// The script content loaded by this src must be encoded in base64 format. This will be the value for the parameter incapsulaScriptBase64.
///
/// - incapsulaSessionCookie: "incapsulaSessionCookie": "l/LsGnrvyB9lNhXI8borDKa2IGcAAAAAX0qAEHheCWuNDquzwb44cw="
/// Your cookies from Incapsula. You can obtain them on the page using "document.cookie" or in the request header Set-Cookie: "incap_sess_*=..."
///
/// - reese84UrlEndpoint: "reese84UrlEndpoint": "Built-with-the-For-hopence-Hurleysurfecting-the-"
/// The name of the endpoint where the reese84 fingerprint is sent can be found among the requests and ends with ?d=site.com
///
/// </summary>
public ImpervaCustomTaskRequest(string incapsulaScriptBase64, string incapsulaSessionCookie, string reese84UrlEndpoint) => Metadata = new { incapsulaScriptBase64, incapsulaSessionCookie, reese84UrlEndpoint };
}
}
19 changes: 16 additions & 3 deletions CapMonsterCloud.Client/Requests/TenDiCustomTaskRequest.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
namespace Zennolab.CapMonsterCloud.Requests
using Newtonsoft.Json;
using System.ComponentModel.DataAnnotations;

namespace Zennolab.CapMonsterCloud.Requests
{
/// <summary>
/// TenDi CustomTask recognition request
/// </summary>
public sealed class TenDiCustomTaskRequest : TenDiCustomTaskRequestBase
{
public sealed class TenDiCustomTaskRequest : CustomTaskRequestBase
{
/// <inheritdoc/>
public override string Class => "TenDI";

/// <summary>
/// captchaAppId. For example "websiteKey": "189123456" - is a unique parameter for your site. You can take it from an html page with a captcha or from traffic.
/// </summary>
/// <example>189123456</example>
[JsonProperty("websiteKey", Required = Required.Always)]
[StringLength(int.MaxValue, MinimumLength = 1)]
public string WebsiteKey { get; set; }
}
}
22 changes: 0 additions & 22 deletions CapMonsterCloud.Client/Requests/TenDiCustomTaskRequestBase.cs

This file was deleted.

Loading