From 190f09885cf7714cc378fa0892ed79c884fab354 Mon Sep 17 00:00:00 2001 From: bezzz Date: Mon, 27 Jan 2025 12:24:19 +0300 Subject: [PATCH 1/2] CCL-5528 added Basilisk, Imperva, Binance, ComplexImageRecognition tasks --- package.json | 2 +- src/CapMonsterCloudClient.ts | 44 ++++++ src/CapMonsterCloudClientFactory.i.spec.ts | 148 ++++++++++++++++++ src/GetResultTimeouts.ts | 9 ++ src/GetTaskResult.ts | 10 +- src/Requests/BasiliskRequest.ts | 13 ++ src/Requests/BasiliskRequestBase.ts | 41 +++++ src/Requests/BinanceRequest.ts | 13 ++ src/Requests/BinanceRequestBase.ts | 41 +++++ .../ComplexImageTaskRecognitionRequest.ts | 16 ++ .../ComplexImageTaskRecognitionRequestBase.ts | 35 +++++ src/Requests/ImpervaRequest.ts | 13 ++ src/Requests/ImpervaRequestBase.ts | 46 ++++++ src/Requests/Task.ts | 8 +- src/Requests/TurnstileRequestBase.ts | 38 ++--- src/Responses/BasiliskResponse.ts | 15 ++ src/Responses/BinanceResponse.ts | 7 + .../ComplexImageRecognitionResponse.ts | 8 + src/Responses/ImpervaResponse.ts | 17 ++ src/TaskType.ts | 1 + src/index.ts | 19 +++ 21 files changed, 522 insertions(+), 22 deletions(-) create mode 100644 src/Requests/BasiliskRequest.ts create mode 100644 src/Requests/BasiliskRequestBase.ts create mode 100644 src/Requests/BinanceRequest.ts create mode 100644 src/Requests/BinanceRequestBase.ts create mode 100644 src/Requests/ComplexImageTaskRecognitionRequest.ts create mode 100644 src/Requests/ComplexImageTaskRecognitionRequestBase.ts create mode 100644 src/Requests/ImpervaRequest.ts create mode 100644 src/Requests/ImpervaRequestBase.ts create mode 100644 src/Responses/BasiliskResponse.ts create mode 100644 src/Responses/BinanceResponse.ts create mode 100644 src/Responses/ComplexImageRecognitionResponse.ts create mode 100644 src/Responses/ImpervaResponse.ts diff --git a/package.json b/package.json index 1847fb5..0f1dd3b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@zennolab_com/capmonstercloud-client", - "version": "1.8.2", + "version": "1.9.0", "description": "Official JS client library for https://capmonster.cloud/ captcha recognition service", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/src/CapMonsterCloudClient.ts b/src/CapMonsterCloudClient.ts index 0873983..74b4af3 100644 --- a/src/CapMonsterCloudClient.ts +++ b/src/CapMonsterCloudClient.ts @@ -43,6 +43,14 @@ import { TenDIResponse } from './Responses/TenDIResponse'; import { AmazonProxylessRequest } from './Requests/AmazonProxylessRequest'; import { AmazonResponse } from './Responses/AmazonResponse'; import { AmazonRequest } from './Requests/AmazonRequest'; +import { BasiliskRequest } from './Requests/BasiliskRequest'; +import { BasiliskResponse } from './Responses/BasiliskResponse'; +import { ImpervaRequest } from './Requests/ImpervaRequest'; +import { ImpervaResponse } from './Responses/ImpervaResponse'; +import { BinanceRequest } from './Requests/BinanceRequest'; +import { BinanceResponse } from './Responses/BinanceResponse'; +import { ComplexImageTaskRecognitionRequest } from './Requests/ComplexImageTaskRecognitionRequest'; +import { ComplexImageRecognitionResponse } from './Responses/ComplexImageRecognitionResponse'; /** * Base type for capmonster.cloud Client exceptions */ @@ -274,6 +282,42 @@ export class CapMonsterCloudClient { resultTimeouts?: GetResultTimeouts, cancellationController?: AbortController, ): Promise>; + /** + * Solve Basilisk task + * You will get response within 10 - 180 secs period depending on service workload. + */ + public async Solve( + task: BasiliskRequest, + resultTimeouts?: GetResultTimeouts, + cancellationController?: AbortController, + ): Promise>; + /** + * Solve Imperva task + * You will get response within 10 - 180 secs period depending on service workload. + */ + public async Solve( + task: ImpervaRequest, + resultTimeouts?: GetResultTimeouts, + cancellationController?: AbortController, + ): Promise>; + /** + * Solve Binance task + * You will get response within 10 - 180 secs period depending on service workload. + */ + public async Solve( + task: BinanceRequest, + resultTimeouts?: GetResultTimeouts, + cancellationController?: AbortController, + ): Promise>; + /** + * Solve ComplexImageRecognition task + * You will get response within 10 - 180 secs period depending on service workload. + */ + public async Solve( + task: ComplexImageTaskRecognitionRequest, + resultTimeouts?: GetResultTimeouts, + cancellationController?: AbortController, + ): Promise>; /** * Solve AmazonProxyless task * You will get response within 10 - 180 secs period depending on service workload. diff --git a/src/CapMonsterCloudClientFactory.i.spec.ts b/src/CapMonsterCloudClientFactory.i.spec.ts index deb93dc..2a84b72 100644 --- a/src/CapMonsterCloudClientFactory.i.spec.ts +++ b/src/CapMonsterCloudClientFactory.i.spec.ts @@ -11,6 +11,10 @@ import { ComplexImageHCaptchaRequest } from './Requests/ComplexImageHCaptchaRequ import { ComplexImageFunCaptchaRequest } from './Requests/ComplexImageFunCaptchaRequest'; import { TenDIRequest } from './Requests/TenDIRequest'; import { AmazonProxylessRequest } from './Requests/AmazonProxylessRequest'; +import { BasiliskRequest } from './Requests/BasiliskRequest'; +import { ImpervaRequest } from './Requests/ImpervaRequest'; +import { BinanceRequest } from './Requests/BinanceRequest'; +import { ComplexImageTaskRecognitionRequest } from './Requests/ComplexImageTaskRecognitionRequest'; const { version } = require('../package.json'); // eslint-disable-line @typescript-eslint/no-var-requires describe('Check integration tests for CapMonsterCloudClientFactory()', () => { @@ -561,6 +565,41 @@ describe('Check integration tests for CapMonsterCloudClientFactory()', () => { expect(await srv.destroy()).toBeUndefined(); }); + it('should solve Basilisk Task', async () => { + expect.assertions(5); + + const srv = await createServerMock({ + responses: [ + { responseBody: '{"errorId":0,"taskId":1234567}' }, + { + responseBody: + '{"errorId":0,"status":"ready","solution":{"data": {"captcha_response": "5620301f30daf284b829fba66fa9b3d0"}, "headers": { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" }}}', + }, + ], + }); + + const cmcClient = CapMonsterCloudClientFactory.Create( + new ClientOptions({ clientKey: '', serviceUrl: `http://localhost:${srv.address.port}` }), + ); + + const basiliskRequest = new BasiliskRequest({ + websiteURL: 'https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=middle', + websiteKey: 'websiteKey', + }); + + const task = await cmcClient.Solve(basiliskRequest); + + expect(srv.caughtRequests[0]).toHaveProperty( + 'body', + '{"clientKey":"","task":{"type":"CustomTask","websiteURL":"https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=middle","websiteKey":"websiteKey","class":"Basilisk"},"softId":54}', + ); + expect(srv.caughtRequests[1]).toHaveProperty('body', '{"clientKey":"","taskId":1234567}'); + expect(task).toHaveProperty('solution'); + expect(task).toHaveProperty('solution.data', { captcha_response: '5620301f30daf284b829fba66fa9b3d0' }); + + expect(await srv.destroy()).toBeUndefined(); + }); + it('should solve Amazon Task', async () => { expect.assertions(5); @@ -600,6 +639,115 @@ describe('Check integration tests for CapMonsterCloudClientFactory()', () => { '10115f5b-ebd8-45c7-851e-cfd4f6a82e3e:EAoAua1QezAhAAAA:dp7sp2rXIRcnJcmpWOC1vIu+yq/A3EbR6b6K7c67P49usNF1f1bt/Af5pNcZ7TKZlW+jIZ7QfNs8zjjqiu8C9XQq50Pmv2DxUlyFtfPZkGwk0d27Ocznk18/IOOa49Rydx+/XkGA7xoGLNaUelzNX34PlyXjoOtL0rzYBxMAQy0D1tn+Q5u97kJBjs5Mytqu9tXPIPCTSn4dfXv5llSkv9pxBEnnhwz6HEdmdJMdfur+YRW1MgCX7i3L2Y0/CNL8kd8CEhTMzwyoXekrzBM=', }); + expect(await srv.destroy()).toBeUndefined(); + }); + it('should solve Imperva Task', async () => { + expect.assertions(5); + + const srv = await createServerMock({ + responses: [ + { responseBody: '{"errorId":0,"taskId":1234567}' }, + { + responseBody: + '{"errorId":0,"status":"ready","solution":{"domains": { "site.com" : { "cookies": { "___utmvc": "NMB", "reese84": "reese84"}} } }}', + }, + ], + }); + + const cmcClient = CapMonsterCloudClientFactory.Create( + new ClientOptions({ clientKey: '', serviceUrl: `http://localhost:${srv.address.port}` }), + ); + + const impervaRequest = new ImpervaRequest({ + websiteURL: 'https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=middle', + metadata: { + incapsulaScriptBase64: 'dmFyIF8weGQ2ZmU9Wydce..eDUzXHg2YV', + incapsulaSessionCookie: 'l/LsGnrvyB9lNhXI8borDKa2IGc', + }, + }); + + const task = await cmcClient.Solve(impervaRequest); + + expect(srv.caughtRequests[0]).toHaveProperty( + 'body', + '{"clientKey":"","task":{"type":"CustomTask","websiteURL":"https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=middle","metadata":{"incapsulaScriptBase64":"dmFyIF8weGQ2ZmU9Wydce..eDUzXHg2YV","incapsulaSessionCookie":"l/LsGnrvyB9lNhXI8borDKa2IGc"},"class":"Imperva"},"softId":54}', + ); + expect(srv.caughtRequests[1]).toHaveProperty('body', '{"clientKey":"","taskId":1234567}'); + expect(task).toHaveProperty('solution'); + + expect(task).toHaveProperty('solution.domains', { 'site.com': { cookies: { ___utmvc: 'NMB', reese84: 'reese84' } } }); + + expect(await srv.destroy()).toBeUndefined(); + }); + it('should solve Binance Task', async () => { + expect.assertions(5); + + const srv = await createServerMock({ + responses: [ + { responseBody: '{"errorId":0,"taskId":1234567}' }, + { + responseBody: + '{"errorId":0,"status":"ready","solution":{"token":"captcha#09ba4905a79f44f2a99e44f234439644-ioVA7neog7eRHCDAsC0MixpZvt5kc99maS943qIsquNP9D77","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"}}', + }, + ], + }); + + const cmcClient = CapMonsterCloudClientFactory.Create( + new ClientOptions({ clientKey: '', serviceUrl: `http://localhost:${srv.address.port}` }), + ); + + const binanceRequest = new BinanceRequest({ + websiteURL: 'https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=middle', + websiteKey: 'websiteKey', + validateId: 'validateId', + }); + + const task = await cmcClient.Solve(binanceRequest); + + expect(srv.caughtRequests[0]).toHaveProperty( + 'body', + '{"clientKey":"","task":{"type":"BinanceTaskProxyless","websiteURL":"https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=middle","websiteKey":"websiteKey","validateId":"validateId"},"softId":54}', + ); + expect(srv.caughtRequests[1]).toHaveProperty('body', '{"clientKey":"","taskId":1234567}'); + expect(task).toHaveProperty('solution'); + expect(task).toHaveProperty( + 'solution.token', + 'captcha#09ba4905a79f44f2a99e44f234439644-ioVA7neog7eRHCDAsC0MixpZvt5kc99maS943qIsquNP9D77', + ); + + expect(await srv.destroy()).toBeUndefined(); + }); + it('should solve ComplexImageRecognition Task', async () => { + expect.assertions(5); + + const srv = await createServerMock({ + responses: [ + { responseBody: '{"errorId":0,"taskId":1234567}' }, + { + responseBody: '{"errorId":0,"status":"ready","solution":{"answer":[130.90909]}}', + }, + ], + }); + + const cmcClient = CapMonsterCloudClientFactory.Create( + new ClientOptions({ clientKey: '', serviceUrl: `http://localhost:${srv.address.port}` }), + ); + + const binanceRequest = new ComplexImageTaskRecognitionRequest({ + imagesBase64: ['/9xwee/'], + metaData: { Task: 'oocl_rotate' }, + }); + + const task = await cmcClient.Solve(binanceRequest); + + expect(srv.caughtRequests[0]).toHaveProperty( + 'body', + '{"clientKey":"","task":{"type":"ComplexImageTask","class":"recognition","imagesBase64":["/9xwee/"],"metadata":{"Task":"oocl_rotate"}},"softId":54}', + ); + expect(srv.caughtRequests[1]).toHaveProperty('body', '{"clientKey":"","taskId":1234567}'); + expect(task).toHaveProperty('solution'); + expect(task).toHaveProperty('solution.answer', [130.90909]); + expect(await srv.destroy()).toBeUndefined(); }); }); diff --git a/src/GetResultTimeouts.ts b/src/GetResultTimeouts.ts index 2c71761..787cfcd 100644 --- a/src/GetResultTimeouts.ts +++ b/src/GetResultTimeouts.ts @@ -82,6 +82,13 @@ export const AmazonTaskTimeouts = { timeout: 1000 * 80, } as GetResultTimeouts; +export const BinanceTaskTimeouts = { + firstRequestDelay: 1000 * 1, + firstRequestNoCacheDelay: 1000 * 10, + requestsInterval: 1000 * 1, + timeout: 1000 * 80, +} as GetResultTimeouts; + export function detectResultTimeouts(task: Task): GetResultTimeouts { switch (task.type) { case TaskType.FunCaptchaTaskProxyless: @@ -113,6 +120,8 @@ export function detectResultTimeouts(task: Task): GetResultTimeouts { case TaskType.AmazonTaskProxyless: case TaskType.AmazonTask: return AmazonTaskTimeouts; + case TaskType.BinanceTaskProxyless: + return BinanceTaskTimeouts; default: throw new Error(`Could not detect result timeouts for provided task type = ${task.type}`); } diff --git a/src/GetTaskResult.ts b/src/GetTaskResult.ts index 514c134..ff9777f 100644 --- a/src/GetTaskResult.ts +++ b/src/GetTaskResult.ts @@ -10,6 +10,10 @@ import { ComplexImageResponse } from './Responses/ComplexImageResponse'; import { DataDomeResponse } from './Responses/DataDomeResponse'; import { TenDIResponse } from './Responses/TenDIResponse'; import { AmazonResponse } from './Responses/AmazonResponse'; +import { BasiliskResponse } from './Responses/BasiliskResponse'; +import { ImpervaResponse } from './Responses/ImpervaResponse'; +import { BinanceResponse } from './Responses/BinanceResponse'; +import { ComplexImageRecognitionResponse } from './Responses/ComplexImageRecognitionResponse'; export enum TaskResultType { Failed = 'Failed', @@ -37,7 +41,11 @@ export type TaskCompletedSolution = | ComplexImageResponse | DataDomeResponse | TenDIResponse - | AmazonResponse; + | AmazonResponse + | BasiliskResponse + | ImpervaResponse + | BinanceResponse + | ComplexImageRecognitionResponse; export type TaskCompleted = { type: TaskResultType.Completed; diff --git a/src/Requests/BasiliskRequest.ts b/src/Requests/BasiliskRequest.ts new file mode 100644 index 0000000..463c3e8 --- /dev/null +++ b/src/Requests/BasiliskRequest.ts @@ -0,0 +1,13 @@ +import { TaskType } from '../TaskType'; +import { BasiliskRequestBase, BasiliskRequestBaseIn } from './BasiliskRequestBase'; + +export type BasiliskRequestIn = Pick>; +/** + * Basilisk recognition request. + * {@link https://zenno.link/doc-basilisk} + */ +export class BasiliskRequest extends BasiliskRequestBase { + constructor(argsObj: BasiliskRequestIn) { + super({ type: TaskType.CustomTask, _class: 'Basilisk', ...argsObj }); + } +} diff --git a/src/Requests/BasiliskRequestBase.ts b/src/Requests/BasiliskRequestBase.ts new file mode 100644 index 0000000..1975cb5 --- /dev/null +++ b/src/Requests/BasiliskRequestBase.ts @@ -0,0 +1,41 @@ +import { CaptchaRequestBase, CaptchaRequestBaseIn } from './CaptchaRequestBase'; + +export type BasiliskRequestBaseIn = { + websiteURL: string; + websiteKey: string; + userAgent?: string; + _class: string; +} & CaptchaRequestBaseIn; + +/** + * Base Basilisk recognition request + */ +export abstract class BasiliskRequestBase extends CaptchaRequestBase { + /** + * Address of a webpage with Basilisk. + */ + public websiteURL!: string; + + /** + * Can be found in the html code in the attribute data-sitekey of the captcha container or in the payload of a POST request to the https://basiliskcaptcha.com/challenge/check-site in the field site_key + */ + public websiteKey!: string; + + /** + * Browser User-Agent. Pass only the actual UA from Windows OS + */ + public userAgent?: string; + + /** + * Class of captcha object + */ + public class: string; + + constructor({ type, nocache, websiteURL, userAgent, websiteKey, _class }: BasiliskRequestBaseIn) { + super({ type, nocache }); + this.websiteURL = websiteURL; + this.websiteKey = websiteKey; + this.userAgent = userAgent; + this.class = _class; + } +} diff --git a/src/Requests/BinanceRequest.ts b/src/Requests/BinanceRequest.ts new file mode 100644 index 0000000..c4279d4 --- /dev/null +++ b/src/Requests/BinanceRequest.ts @@ -0,0 +1,13 @@ +import { TaskType } from '../TaskType'; +import { BinanceRequestBase, BinanceRequestBaseIn } from './BinanceRequestBase'; + +export type BinanceRequestIn = Pick>; +/** + * Binance recognition request. + * {@link https://zenno.link/doc-binance} + */ +export class BinanceRequest extends BinanceRequestBase { + constructor(argsObj: BinanceRequestIn) { + super({ type: TaskType.BinanceTaskProxyless, ...argsObj }); + } +} diff --git a/src/Requests/BinanceRequestBase.ts b/src/Requests/BinanceRequestBase.ts new file mode 100644 index 0000000..644a670 --- /dev/null +++ b/src/Requests/BinanceRequestBase.ts @@ -0,0 +1,41 @@ +import { CaptchaRequestBase, CaptchaRequestBaseIn } from './CaptchaRequestBase'; + +export type BinanceRequestBaseIn = { + websiteURL: string; + websiteKey: string; + validateId: string; + userAgent?: string; +} & CaptchaRequestBaseIn; + +/** + * Base Binance recognition request + */ +export abstract class BinanceRequestBase extends CaptchaRequestBase { + /** + * Address of a webpage with Binance. + */ + public websiteURL!: string; + + /** + * A unique parameter for your website's section. The value of the parameter bizId, bizType, or bizCode. It can be taken from the traffic (see the description below + */ + public websiteKey!: string; + + /** + * A dynamic key. The value of the parameter validateId, securityId, or securityCheckResponseValidateId. It can be taken from the traffic (see the description below). + */ + public validateId!: string; + + /** + * Browser User-Agent. Pass only the actual UA from Windows OS + */ + public userAgent?: string; + + constructor({ type, nocache, websiteURL, userAgent, websiteKey, validateId }: BinanceRequestBaseIn) { + super({ type, nocache }); + this.websiteURL = websiteURL; + this.websiteKey = websiteKey; + this.validateId = validateId; + this.userAgent = userAgent; + } +} diff --git a/src/Requests/ComplexImageTaskRecognitionRequest.ts b/src/Requests/ComplexImageTaskRecognitionRequest.ts new file mode 100644 index 0000000..a6e9e63 --- /dev/null +++ b/src/Requests/ComplexImageTaskRecognitionRequest.ts @@ -0,0 +1,16 @@ +import { TaskType } from '../TaskType'; +import { ComplexImageRecognitionRequestBase, ComplexImageRecognitionRequestBaseIn } from './ComplexImageTaskRecognitionRequestBase'; + +export type ComplexImageRecognitionRequestIn = Pick< + ComplexImageRecognitionRequestBaseIn, + Exclude +>; +/** + * ComplexImageTaskRecognition recognition request. + * {@link https://zenno.link/doc-complex-image-recognition} + */ +export class ComplexImageTaskRecognitionRequest extends ComplexImageRecognitionRequestBase { + constructor(argsObj: ComplexImageRecognitionRequestIn) { + super({ type: TaskType.ComplexImageTask, _class: 'recognition', ...argsObj }); + } +} diff --git a/src/Requests/ComplexImageTaskRecognitionRequestBase.ts b/src/Requests/ComplexImageTaskRecognitionRequestBase.ts new file mode 100644 index 0000000..cd746d3 --- /dev/null +++ b/src/Requests/ComplexImageTaskRecognitionRequestBase.ts @@ -0,0 +1,35 @@ +import { CaptchaRequestBase, CaptchaRequestBaseIn } from './CaptchaRequestBase'; + +type metaData = { + Task: string; + TaskArgument?: string; +}; + +export type ComplexImageRecognitionRequestBaseIn = { + _class: string; + imagesBase64?: Array; + metaData: metaData; +} & CaptchaRequestBaseIn; + +export class ComplexImageRecognitionRequestBase extends CaptchaRequestBase { + /** + * Class of captcha object + */ + public class!: string; + /** + * List of images + */ + public imagesBase64?: Array; + /** + * Browser's User-Agent which is used in emulation. + * It is required that you use a signature of a modern browser. + */ + public metadata: metaData; + + constructor({ type, nocache, _class, imagesBase64, metaData }: ComplexImageRecognitionRequestBaseIn) { + super({ type, nocache }); + this.class = _class; + this.imagesBase64 = imagesBase64; + this.metadata = metaData; + } +} diff --git a/src/Requests/ImpervaRequest.ts b/src/Requests/ImpervaRequest.ts new file mode 100644 index 0000000..77ce9c1 --- /dev/null +++ b/src/Requests/ImpervaRequest.ts @@ -0,0 +1,13 @@ +import { TaskType } from '../TaskType'; +import { ImpervaRequestBase, ImpervaRequestBaseIn } from './ImpervaRequestBase'; + +export type ImpervaRequestIn = Pick>; +/** + * Imperva recognition request. + * {@link https://zenno.link/doc-imperva} + */ +export class ImpervaRequest extends ImpervaRequestBase { + constructor(argsObj: ImpervaRequestIn) { + super({ type: TaskType.CustomTask, _class: 'Imperva', ...argsObj }); + } +} diff --git a/src/Requests/ImpervaRequestBase.ts b/src/Requests/ImpervaRequestBase.ts new file mode 100644 index 0000000..5175782 --- /dev/null +++ b/src/Requests/ImpervaRequestBase.ts @@ -0,0 +1,46 @@ +import { CaptchaRequestBase, CaptchaRequestBaseIn } from './CaptchaRequestBase'; + +export type ImpervaRequestBaseIn = { + websiteURL: string; + metadata: { + incapsulaScriptBase64: string; + incapsulaSessionCookie: string; + reese84UrlEndpoint?: string; + }; + userAgent?: string; + _class: string; +} & CaptchaRequestBaseIn; + +/** + * Base Imperva recognition request + */ +export abstract class ImpervaRequestBase extends CaptchaRequestBase { + /** + * Address of a webpage with Imperva. + */ + public websiteURL!: string; + + public metadata: { + incapsulaScriptBase64: string; + incapsulaSessionCookie: string; + reese84UrlEndpoint?: string; + }; + + /** + * Browser User-Agent. Pass only the actual UA from Windows OS + */ + public userAgent?: string; + + /** + * Class of captcha object + */ + public class: string; + + constructor({ type, nocache, websiteURL, userAgent, metadata, _class }: ImpervaRequestBaseIn) { + super({ type, nocache }); + this.websiteURL = websiteURL; + this.metadata = metadata; + this.userAgent = userAgent; + this.class = _class; + } +} diff --git a/src/Requests/Task.ts b/src/Requests/Task.ts index 27c587d..4ae6e64 100644 --- a/src/Requests/Task.ts +++ b/src/Requests/Task.ts @@ -14,6 +14,9 @@ import { ComplexImageHCaptchaRequest } from './ComplexImageHCaptchaRequest'; import { ComplexImageRecaptchaRequest } from './ComplexImageRecaptchaRequest'; import { ComplexImageFunCaptchaRequest } from './ComplexImageFunCaptchaRequest'; import { DataDomeRequest } from './DataDomeRequest'; +import { BasiliskRequest } from './BasiliskRequest'; +import { ImpervaRequest } from './ImpervaRequest'; +import { BinanceRequest } from './BinanceRequest'; /** * Universal type for recognition request @@ -34,4 +37,7 @@ export type Task = | ComplexImageHCaptchaRequest | ComplexImageRecaptchaRequest | ComplexImageFunCaptchaRequest - | DataDomeRequest; + | DataDomeRequest + | BasiliskRequest + | ImpervaRequest + | BinanceRequest; diff --git a/src/Requests/TurnstileRequestBase.ts b/src/Requests/TurnstileRequestBase.ts index bf25be5..5cf098c 100644 --- a/src/Requests/TurnstileRequestBase.ts +++ b/src/Requests/TurnstileRequestBase.ts @@ -1,27 +1,27 @@ import { CaptchaRequestBase, CaptchaRequestBaseIn } from './CaptchaRequestBase'; export type TurnstileRequestBaseIn = { - websiteURL: string; - websiteKey: string; - } & CaptchaRequestBaseIn; + websiteURL: string; + websiteKey: string; +} & CaptchaRequestBaseIn; /** * Base Turnstile recognition request */ export abstract class TurnstileRequestBase extends CaptchaRequestBase { - /** - * Address of a webpage - */ - public websiteURL!: string; - - /** - * Turnstile website key. - */ - public websiteKey!: string; - - constructor({ type, nocache, websiteURL, websiteKey }: TurnstileRequestBaseIn) { - super({ type, nocache }); - this.websiteURL = websiteURL; - this.websiteKey = websiteKey; - } - } \ No newline at end of file + /** + * Address of a webpage + */ + public websiteURL!: string; + + /** + * Turnstile website key. + */ + public websiteKey!: string; + + constructor({ type, nocache, websiteURL, websiteKey }: TurnstileRequestBaseIn) { + super({ type, nocache }); + this.websiteURL = websiteURL; + this.websiteKey = websiteKey; + } +} diff --git a/src/Responses/BasiliskResponse.ts b/src/Responses/BasiliskResponse.ts new file mode 100644 index 0000000..ae547d8 --- /dev/null +++ b/src/Responses/BasiliskResponse.ts @@ -0,0 +1,15 @@ +type BasiliskData = { + captcha_response: string; +}; + +type UserAgent = { + 'User-Agent': string; +}; + +/** + * Basilisk recognition response base + */ +export type BasiliskResponse = { + data: BasiliskData; + headers: UserAgent; +}; diff --git a/src/Responses/BinanceResponse.ts b/src/Responses/BinanceResponse.ts new file mode 100644 index 0000000..aa0e29e --- /dev/null +++ b/src/Responses/BinanceResponse.ts @@ -0,0 +1,7 @@ +/** + * Binance recognition response base + */ +export type BinanceResponse = { + token: string; + userAgent: string; +}; diff --git a/src/Responses/ComplexImageRecognitionResponse.ts b/src/Responses/ComplexImageRecognitionResponse.ts new file mode 100644 index 0000000..2dc7b77 --- /dev/null +++ b/src/Responses/ComplexImageRecognitionResponse.ts @@ -0,0 +1,8 @@ +type RotateAnswer = Array; +type DoubleAnswer = Array; +type BetpunchAnswer = Array; +type BlsAnswer = Array; + +export type ComplexImageRecognitionResponse = { + answer: RotateAnswer | DoubleAnswer | BetpunchAnswer | BlsAnswer; +}; diff --git a/src/Responses/ImpervaResponse.ts b/src/Responses/ImpervaResponse.ts new file mode 100644 index 0000000..a006171 --- /dev/null +++ b/src/Responses/ImpervaResponse.ts @@ -0,0 +1,17 @@ +type SiteResponseType = { + cookies: { + ___utmvc: string; + reese84: string; + }; +}; + +type DomainsProps = { + [site: string]: SiteResponseType; +}; + +/** + * Imperva recognition response base + */ +export type ImpervaResponse = { + domains: DomainsProps; +}; diff --git a/src/TaskType.ts b/src/TaskType.ts index c98f62d..0008c15 100644 --- a/src/TaskType.ts +++ b/src/TaskType.ts @@ -17,4 +17,5 @@ export enum TaskType { CustomTask = 'CustomTask', AmazonTask = 'AmazonTask', AmazonTaskProxyless = 'AmazonTaskProxyless', + BinanceTaskProxyless = 'BinanceTaskProxyless', } diff --git a/src/index.ts b/src/index.ts index 1b6d299..14b8cd4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -27,6 +27,10 @@ import { ComplexImageFunCaptchaRequest, ComplexImageFunCaptchaRequestIn } from ' import { DataDomeRequest, DataDomeRequestIn } from './Requests/DataDomeRequest'; import { TenDIRequest, TenDIRequestIn } from './Requests/TenDIRequest'; import { AmazonRequest, AmazonRequestIn } from './Requests/AmazonRequest'; +import { BasiliskRequest, BasiliskRequestIn } from './Requests/BasiliskRequest'; +import { ImpervaRequest, ImpervaRequestIn } from './Requests/ImpervaRequest'; +import { BinanceRequest, BinanceRequestIn } from './Requests/BinanceRequest'; +import { ComplexImageRecognitionRequestIn, ComplexImageTaskRecognitionRequest } from './Requests/ComplexImageTaskRecognitionRequest'; export default { CapMonsterCloudClientFactory, @@ -51,6 +55,10 @@ export default { DataDomeRequest, TenDIRequest, AmazonRequest, + BasiliskRequest, + ImpervaRequest, + BinanceRequest, + ComplexImageTaskRecognitionRequest, }; export { @@ -94,7 +102,18 @@ export { ComplexImageHCaptchaRequestIn, ComplexImageFunCaptchaRequest, ComplexImageFunCaptchaRequestIn, + DataDomeRequest, DataDomeRequestIn, + TenDIRequest, TenDIRequestIn, + AmazonRequest, AmazonRequestIn, + BasiliskRequest, + BasiliskRequestIn, + ImpervaRequest, + ImpervaRequestIn, + BinanceRequest, + BinanceRequestIn, + ComplexImageTaskRecognitionRequest, + ComplexImageRecognitionRequestIn, }; From 0a686f03adde4c8b72d231d4d6995016b164c157 Mon Sep 17 00:00:00 2001 From: bezzz Date: Mon, 27 Jan 2025 17:17:34 +0300 Subject: [PATCH 2/2] CCL-5528 added BinanceTask with proxy --- src/CapMonsterCloudClient.ts | 10 +++++ src/CapMonsterCloudClientFactory.i.spec.ts | 44 ++++++++++++++++++++++ src/GetResultTimeouts.ts | 1 + src/Requests/BinanceProxylessRequest.ts | 13 +++++++ src/Requests/BinanceRequest.ts | 8 ++-- src/TaskType.ts | 1 + src/index.ts | 4 ++ 7 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 src/Requests/BinanceProxylessRequest.ts diff --git a/src/CapMonsterCloudClient.ts b/src/CapMonsterCloudClient.ts index 74b4af3..dcd3db5 100644 --- a/src/CapMonsterCloudClient.ts +++ b/src/CapMonsterCloudClient.ts @@ -51,6 +51,7 @@ import { BinanceRequest } from './Requests/BinanceRequest'; import { BinanceResponse } from './Responses/BinanceResponse'; import { ComplexImageTaskRecognitionRequest } from './Requests/ComplexImageTaskRecognitionRequest'; import { ComplexImageRecognitionResponse } from './Responses/ComplexImageRecognitionResponse'; +import { BinanceProxylessRequest } from './Requests/BinanceProxylessRequest'; /** * Base type for capmonster.cloud Client exceptions */ @@ -309,6 +310,15 @@ export class CapMonsterCloudClient { resultTimeouts?: GetResultTimeouts, cancellationController?: AbortController, ): Promise>; + /** + * Solve BinanceProxyless task + * You will get response within 10 - 180 secs period depending on service workload. + */ + public async Solve( + task: BinanceProxylessRequest, + resultTimeouts?: GetResultTimeouts, + cancellationController?: AbortController, + ): Promise>; /** * Solve ComplexImageRecognition task * You will get response within 10 - 180 secs period depending on service workload. diff --git a/src/CapMonsterCloudClientFactory.i.spec.ts b/src/CapMonsterCloudClientFactory.i.spec.ts index 2a84b72..2d858cd 100644 --- a/src/CapMonsterCloudClientFactory.i.spec.ts +++ b/src/CapMonsterCloudClientFactory.i.spec.ts @@ -15,6 +15,7 @@ import { BasiliskRequest } from './Requests/BasiliskRequest'; import { ImpervaRequest } from './Requests/ImpervaRequest'; import { BinanceRequest } from './Requests/BinanceRequest'; import { ComplexImageTaskRecognitionRequest } from './Requests/ComplexImageTaskRecognitionRequest'; +import { BinanceProxylessRequest } from './Requests/BinanceProxylessRequest'; const { version } = require('../package.json'); // eslint-disable-line @typescript-eslint/no-var-requires describe('Check integration tests for CapMonsterCloudClientFactory()', () => { @@ -700,6 +701,49 @@ describe('Check integration tests for CapMonsterCloudClientFactory()', () => { websiteURL: 'https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=middle', websiteKey: 'websiteKey', validateId: 'validateId', + proxyType: 'http', + proxyAddress: '8.8.8.8', + proxyPort: 8080, + proxyLogin: 'proxyLoginHere', + proxyPassword: 'proxyPasswordHere', + }); + + const task = await cmcClient.Solve(binanceRequest); + + expect(srv.caughtRequests[0]).toHaveProperty( + 'body', + '{"clientKey":"","task":{"type":"BinanceTaskProxyless","websiteURL":"https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=middle","websiteKey":"websiteKey","validateId":"validateId","proxyType":"http","proxyAddress":"8.8.8.8","proxyPort":8080,"proxyLogin":"proxyLoginHere","proxyPassword":"proxyPasswordHere"},"softId":54}', + ); + expect(srv.caughtRequests[1]).toHaveProperty('body', '{"clientKey":"","taskId":1234567}'); + expect(task).toHaveProperty('solution'); + expect(task).toHaveProperty( + 'solution.token', + 'captcha#09ba4905a79f44f2a99e44f234439644-ioVA7neog7eRHCDAsC0MixpZvt5kc99maS943qIsquNP9D77', + ); + + expect(await srv.destroy()).toBeUndefined(); + }); + it('should solve Binance Task Proxyless', async () => { + expect.assertions(5); + + const srv = await createServerMock({ + responses: [ + { responseBody: '{"errorId":0,"taskId":1234567}' }, + { + responseBody: + '{"errorId":0,"status":"ready","solution":{"token":"captcha#09ba4905a79f44f2a99e44f234439644-ioVA7neog7eRHCDAsC0MixpZvt5kc99maS943qIsquNP9D77","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"}}', + }, + ], + }); + + const cmcClient = CapMonsterCloudClientFactory.Create( + new ClientOptions({ clientKey: '', serviceUrl: `http://localhost:${srv.address.port}` }), + ); + + const binanceRequest = new BinanceProxylessRequest({ + websiteURL: 'https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=middle', + websiteKey: 'websiteKey', + validateId: 'validateId', }); const task = await cmcClient.Solve(binanceRequest); diff --git a/src/GetResultTimeouts.ts b/src/GetResultTimeouts.ts index 787cfcd..261a98f 100644 --- a/src/GetResultTimeouts.ts +++ b/src/GetResultTimeouts.ts @@ -121,6 +121,7 @@ export function detectResultTimeouts(task: Task): GetResultTimeouts { case TaskType.AmazonTask: return AmazonTaskTimeouts; case TaskType.BinanceTaskProxyless: + case TaskType.BinanceTask: return BinanceTaskTimeouts; default: throw new Error(`Could not detect result timeouts for provided task type = ${task.type}`); diff --git a/src/Requests/BinanceProxylessRequest.ts b/src/Requests/BinanceProxylessRequest.ts new file mode 100644 index 0000000..84ebb1e --- /dev/null +++ b/src/Requests/BinanceProxylessRequest.ts @@ -0,0 +1,13 @@ +import { TaskType } from '../TaskType'; +import { BinanceRequestBase, BinanceRequestBaseIn } from './BinanceRequestBase'; + +export type BinanceProxylessRequestIn = Pick>; +/** + * Binance recognition request. + * {@link https://zenno.link/doc-binance} + */ +export class BinanceProxylessRequest extends BinanceRequestBase { + constructor(argsObj: BinanceProxylessRequestIn) { + super({ type: TaskType.BinanceTaskProxyless, ...argsObj }); + } +} diff --git a/src/Requests/BinanceRequest.ts b/src/Requests/BinanceRequest.ts index c4279d4..e376ce8 100644 --- a/src/Requests/BinanceRequest.ts +++ b/src/Requests/BinanceRequest.ts @@ -1,12 +1,14 @@ +import { Mixin } from 'ts-mixer'; import { TaskType } from '../TaskType'; import { BinanceRequestBase, BinanceRequestBaseIn } from './BinanceRequestBase'; +import { ProxyInfo, ProxyInfoIn } from './ProxyInfo'; -export type BinanceRequestIn = Pick>; +export type BinanceRequestIn = Pick> & ProxyInfoIn; /** - * Binance recognition request. + * Binance recognition request (with proxy). * {@link https://zenno.link/doc-binance} */ -export class BinanceRequest extends BinanceRequestBase { +export class BinanceRequest extends Mixin(BinanceRequestBase, ProxyInfo) { constructor(argsObj: BinanceRequestIn) { super({ type: TaskType.BinanceTaskProxyless, ...argsObj }); } diff --git a/src/TaskType.ts b/src/TaskType.ts index 0008c15..7a9ca25 100644 --- a/src/TaskType.ts +++ b/src/TaskType.ts @@ -18,4 +18,5 @@ export enum TaskType { AmazonTask = 'AmazonTask', AmazonTaskProxyless = 'AmazonTaskProxyless', BinanceTaskProxyless = 'BinanceTaskProxyless', + BinanceTask = 'BinanceTask', } diff --git a/src/index.ts b/src/index.ts index 14b8cd4..168fe48 100644 --- a/src/index.ts +++ b/src/index.ts @@ -30,6 +30,7 @@ import { AmazonRequest, AmazonRequestIn } from './Requests/AmazonRequest'; import { BasiliskRequest, BasiliskRequestIn } from './Requests/BasiliskRequest'; import { ImpervaRequest, ImpervaRequestIn } from './Requests/ImpervaRequest'; import { BinanceRequest, BinanceRequestIn } from './Requests/BinanceRequest'; +import { BinanceProxylessRequest, BinanceProxylessRequestIn } from './Requests/BinanceProxylessRequest'; import { ComplexImageRecognitionRequestIn, ComplexImageTaskRecognitionRequest } from './Requests/ComplexImageTaskRecognitionRequest'; export default { @@ -58,6 +59,7 @@ export default { BasiliskRequest, ImpervaRequest, BinanceRequest, + BinanceProxylessRequest, ComplexImageTaskRecognitionRequest, }; @@ -114,6 +116,8 @@ export { ImpervaRequestIn, BinanceRequest, BinanceRequestIn, + BinanceProxylessRequest, + BinanceProxylessRequestIn, ComplexImageTaskRecognitionRequest, ComplexImageRecognitionRequestIn, };