diff --git a/README.md b/README.md index fcd220b..803fcfb 100644 --- a/README.md +++ b/README.md @@ -52,11 +52,11 @@ document.addEventListener('DOMContentLoaded', async () => { websiteURL: 'https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=high', websiteKey: '6Lcg7CMUAAAAANphynKgn9YAgA4tQ2KI_iqRyTwd', proxy: { - proxyType: 'http', - proxyAddress: '8.8.8.8', - proxyPort: 8080, - proxyLogin: 'proxyLoginHere', - proxyPassword: 'proxyPasswordHere', + proxyType: 'http', + proxyAddress: '8.8.8.8', + proxyPort: 8080, + proxyLogin: 'proxyLoginHere', + proxyPassword: 'proxyPasswordHere', }, userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.132 Safari/537.36', }); @@ -83,9 +83,10 @@ DEBUG=cmc-* node app.js - [HcaptchaComplexImageTaskRequest](https://zenno.link/doc-complextask-hc-en) - [ImageToTextRequest](https://zenno.link/doc-ImageToTextTask-en) - [ImpervaRequest](https://zenno.link/doc-imperva-en) +- [ProsopoRequest](https://zenno.link/doc-prosopo-en) - [RecaptchaComplexImageTaskRequest](https://zenno.link/doc-complextask-rc-en) - [RecaptchaV2EnterpriseRequest](https://zenno.link/doc-recaptcha2e-proxy-en) - [RecaptchaV2Request](https://zenno.link/doc-recaptcha2-proxy-en) - [RecaptchaV3ProxylessRequest](https://zenno.link/doc-recaptcha3-en) - [TenDIRequest](https://zenno.link/doc-tendi-en) -- [TurnstileRequest](https://zenno.link/doc-turnstile-proxy-en) \ No newline at end of file +- [TurnstileRequest](https://zenno.link/doc-turnstile-proxy-en) diff --git a/package.json b/package.json index 70b2a3d..ee38fd3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@zennolab_com/capmonstercloud-client", - "version": "2.0.0", + "version": "2.1.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 b94bebf..1a9c0d3 100644 --- a/src/CapMonsterCloudClient.ts +++ b/src/CapMonsterCloudClient.ts @@ -45,6 +45,9 @@ import { BinanceRequest } from './Requests/BinanceRequest'; import { BinanceResponse } from './Responses/BinanceResponse'; import { ComplexImageTaskRecognitionRequest } from './Requests/ComplexImageTaskRecognitionRequest'; import { ComplexImageRecognitionResponse } from './Responses/ComplexImageRecognitionResponse'; +import { ProsopoRequest } from './Requests/ProsopoRequest'; +import { ProsopoResponse } from './Responses/ProsopoResponse'; + /** * Base type for capmonster.cloud Client exceptions */ @@ -312,6 +315,15 @@ export class CapMonsterCloudClient { resultTimeouts?: GetResultTimeouts, cancellationController?: AbortController, ): Promise>; + /** + * Solve Prosopo task + * You will get response within 10 - 180 secs period depending on service workload. + */ + public async Solve( + task: ProsopoRequest, + resultTimeouts?: GetResultTimeouts, + cancellationController?: AbortController, + ): Promise>; /** * Solve Complex Image FunCaptcha 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 92b908c..48a8fa6 100644 --- a/src/CapMonsterCloudClientFactory.i.spec.ts +++ b/src/CapMonsterCloudClientFactory.i.spec.ts @@ -15,6 +15,8 @@ import { BinanceRequest } from './Requests/BinanceRequest'; import { ComplexImageTaskRecognitionRequest } from './Requests/ComplexImageTaskRecognitionRequest'; import { AmazonRequest } from './Requests/AmazonRequest'; import { HCaptchaRequest } from './Requests/HCaptchaRequest'; +import { ProsopoRequest } from './Requests/ProsopoRequest'; + const { version } = require('../package.json'); // eslint-disable-line @typescript-eslint/no-var-requires describe('Check integration tests for CapMonsterCloudClientFactory()', () => { @@ -923,6 +925,87 @@ describe('Check integration tests for CapMonsterCloudClientFactory()', () => { expect(task).toHaveProperty('solution'); expect(task).toHaveProperty('solution.answer', [130.90909]); + expect(await srv.destroy()).toBeUndefined(); + }); + it('should solve Prosopo Task', async () => { + expect.assertions(5); + + const srv = await createServerMock({ + responses: [ + { responseBody: '{"errorId":0,"taskId":1234567}' }, + { + responseBody: + '{"errorId":0,"status":"ready","solution":{"token":"0x00016c68747470733a2f2f70726f6e6f6465332e70726f736f706f2e696fc0354550516f4d5a454463354c704e376774784d4d7a5950547a4136"}}', + }, + ], + }); + + const cmcClient = CapMonsterCloudClientFactory.Create( + new ClientOptions({ clientKey: '', serviceUrl: `http://localhost:${srv.address.port}` }), + ); + + const prosopoRequest = new ProsopoRequest({ + websiteURL: 'https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=middle', + websiteKey: 'websiteKey', + proxy: { + proxyType: 'http', + proxyAddress: '8.8.8.8', + proxyPort: 8080, + proxyLogin: 'proxyLoginHere', + proxyPassword: 'proxyPasswordHere', + }, + }); + + const task = await cmcClient.Solve(prosopoRequest); + + expect(srv.caughtRequests[0]).toHaveProperty( + 'body', + '{"clientKey":"","task":{"type":"ProsopoTask","websiteURL":"https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=middle","websiteKey":"websiteKey","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', + '0x00016c68747470733a2f2f70726f6e6f6465332e70726f736f706f2e696fc0354550516f4d5a454463354c704e376774784d4d7a5950547a4136', + ); + + expect(await srv.destroy()).toBeUndefined(); + }); + it('should solve Prosopo Task Proxyless', async () => { + expect.assertions(5); + + const srv = await createServerMock({ + responses: [ + { responseBody: '{"errorId":0,"taskId":1234567}' }, + { + responseBody: + '{"errorId":0,"status":"ready","solution":{"token":"0x00016c68747470733a2f2f70726f6e6f6465332e70726f736f706f2e696fc0354550516f4d5a454463354c704e376774784d4d7a5950547a4136"}}', + }, + ], + }); + + const cmcClient = CapMonsterCloudClientFactory.Create( + new ClientOptions({ clientKey: '', serviceUrl: `http://localhost:${srv.address.port}` }), + ); + + const prosopoRequest = new ProsopoRequest({ + websiteURL: 'https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=middle', + websiteKey: 'websiteKey', + }); + + const task = await cmcClient.Solve(prosopoRequest); + + expect(srv.caughtRequests[0]).toHaveProperty( + 'body', + '{"clientKey":"","task":{"type":"ProsopoTask","websiteURL":"https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=middle","websiteKey":"websiteKey"},"softId":54}', + ); + expect(srv.caughtRequests[1]).toHaveProperty('body', '{"clientKey":"","taskId":1234567}'); + expect(task).toHaveProperty('solution'); + expect(task).toHaveProperty( + 'solution.token', + '0x00016c68747470733a2f2f70726f6e6f6465332e70726f736f706f2e696fc0354550516f4d5a454463354c704e376774784d4d7a5950547a4136', + ); + expect(await srv.destroy()).toBeUndefined(); }); }); diff --git a/src/GetResultTimeouts.ts b/src/GetResultTimeouts.ts index 50abf12..706d9db 100644 --- a/src/GetResultTimeouts.ts +++ b/src/GetResultTimeouts.ts @@ -89,6 +89,13 @@ export const BinanceTaskTimeouts = { timeout: 1000 * 80, } as GetResultTimeouts; +export const ProsopoTaskTimeouts = { + 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.FunCaptchaTask: @@ -117,6 +124,8 @@ export function detectResultTimeouts(task: Task): GetResultTimeouts { return AmazonTaskTimeouts; case TaskType.BinanceTask: return BinanceTaskTimeouts; + case TaskType.ProsopoTask: + return ProsopoTaskTimeouts; default: throw new Error(`Could not detect result timeouts for provided task type = ${task.type}`); } diff --git a/src/Requests/ProsopoRequest/ProsopoRequest.ts b/src/Requests/ProsopoRequest/ProsopoRequest.ts new file mode 100644 index 0000000..1a70862 --- /dev/null +++ b/src/Requests/ProsopoRequest/ProsopoRequest.ts @@ -0,0 +1,18 @@ +import { TaskType } from '../../TaskType'; +import { ProsopoRequestBase, ProsopoRequestBaseIn } from './ProsopoRequestBase'; +import { ProxyInfo, ProxyInfoIn } from '../ProxyInfo'; + +export type ProsopoRequestIn = Pick> & { proxy?: ProxyInfoIn }; +/** + * Prosopo recognition request (with proxy). + * {@link https://zenno.link/doc-prosopo-en} + */ +export class ProsopoRequest extends ProsopoRequestBase { + constructor({ proxy, ...restArgsObj }: ProsopoRequestIn) { + super({ type: TaskType.ProsopoTask, ...restArgsObj }); + + if (proxy) { + Object.assign(this, new ProxyInfo(proxy)); + } + } +} diff --git a/src/Requests/ProsopoRequest/ProsopoRequestBase.ts b/src/Requests/ProsopoRequest/ProsopoRequestBase.ts new file mode 100644 index 0000000..782a94e --- /dev/null +++ b/src/Requests/ProsopoRequest/ProsopoRequestBase.ts @@ -0,0 +1,27 @@ +import { CaptchaRequestBase, CaptchaRequestBaseIn } from '../CaptchaRequestBase'; + +export type ProsopoRequestBaseIn = { + websiteURL: string; + websiteKey: string; +} & CaptchaRequestBaseIn; + +/** + * Base Prosopo recognition request + */ +export abstract class ProsopoRequestBase extends CaptchaRequestBase { + /** + * The full URL of the CAPTCHA page. + */ + public websiteURL!: string; + + /** + * The value of the siteKey parameter found on the page. + */ + public websiteKey!: string; + + constructor({ type, nocache, websiteURL, websiteKey }: ProsopoRequestBaseIn) { + super({ type, nocache }); + this.websiteURL = websiteURL; + this.websiteKey = websiteKey; + } +} diff --git a/src/Requests/ProsopoRequest/index.ts b/src/Requests/ProsopoRequest/index.ts new file mode 100644 index 0000000..bd6d456 --- /dev/null +++ b/src/Requests/ProsopoRequest/index.ts @@ -0,0 +1 @@ +export * from './ProsopoRequest'; diff --git a/src/Responses/ProsopoResponse.ts b/src/Responses/ProsopoResponse.ts new file mode 100644 index 0000000..acd556c --- /dev/null +++ b/src/Responses/ProsopoResponse.ts @@ -0,0 +1,6 @@ +/** + * Prosopo recognition response base + */ +export type ProsopoResponse = { + token: string; +}; diff --git a/src/TaskType.ts b/src/TaskType.ts index 65a5707..b727e3e 100644 --- a/src/TaskType.ts +++ b/src/TaskType.ts @@ -13,4 +13,5 @@ export enum TaskType { CustomTask = 'CustomTask', AmazonTask = 'AmazonTask', BinanceTask = 'BinanceTask', + ProsopoTask = 'ProsopoTask', } diff --git a/src/index.ts b/src/index.ts index 02a8280..7200a55 100644 --- a/src/index.ts +++ b/src/index.ts @@ -22,6 +22,7 @@ import { BasiliskRequest, BasiliskRequestIn } from './Requests/BasiliskRequest'; import { ImpervaRequest, ImpervaRequestIn } from './Requests/ImpervaRequest'; import { BinanceRequest, BinanceRequestIn } from './Requests/BinanceRequest'; import { ComplexImageRecognitionRequestIn, ComplexImageTaskRecognitionRequest } from './Requests/ComplexImageTaskRecognitionRequest'; +import { ProsopoRequest, ProsopoRequestIn } from './Requests/ProsopoRequest'; export default { CapMonsterCloudClientFactory, @@ -44,6 +45,7 @@ export default { ImpervaRequest, BinanceRequest, ComplexImageTaskRecognitionRequest, + ProsopoRequest, }; export { @@ -89,4 +91,6 @@ export { BinanceRequestIn, ComplexImageTaskRecognitionRequest, ComplexImageRecognitionRequestIn, + ProsopoRequest, + ProsopoRequestIn, };