diff --git a/.github/workflows/on_pull_request.yml b/.github/workflows/on_pull_request.yml index 64ddc74..db3463e 100644 --- a/.github/workflows/on_pull_request.yml +++ b/.github/workflows/on_pull_request.yml @@ -11,13 +11,14 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Use Node.js 16.x - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + - name: Use Node.js 22.x + uses: actions/setup-node@v4 with: - node-version: 16.x - - name: yarn install - run: yarn install + node-version: 22.x + cache: npm + - name: npm ci + run: npm ci - name: tsc uses: icrawl/action-tsc@v1 - run: npm run build diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index 429602b..85efdfb 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -11,14 +11,15 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Use Node.js 16.x - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + - name: Use Node.js 22.x + uses: actions/setup-node@v4 with: - node-version: 16.x + node-version: 22.x registry-url: 'https://registry.npmjs.org' - - name: yarn install - run: yarn install + cache: npm + - name: npm ci + run: npm ci - name: tsc uses: icrawl/action-tsc@v1 - run: npm run build diff --git a/.gitignore b/.gitignore index 2a797b1..970f14a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ dist/ node_modules/ -.idea \ No newline at end of file +.idea +.vscode \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index fbbf303..53f2e58 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,7 +2,7 @@ "editor.formatOnSave": true, "eslint.format.enable": true, "editor.codeActionsOnSave": { - "source.fixAll.eslint": true + "source.fixAll.eslint": "explicit" }, "typescript.tsdk": "node_modules/typescript/lib", "files.eol": "\n" diff --git a/README.md b/README.md index ad364f8..7781f60 100644 --- a/README.md +++ b/README.md @@ -75,26 +75,32 @@ DEBUG=cmc-* node app.js ## Supported captcha recognition requests: +- [AlibabaRequest](https://docs.capmonster.cloud/docs/captchas/alibaba-task/) +- [AltchaRequest](https://zenno.link/doc-altcha-en) - [AmazonRequest](https://zenno.link/doc-amazon-en) - [BasiliskRequest](https://zenno.link/doc-basilisk-en) - [BinanceRequest](https://zenno.link/doc-binance-en) +- [CastleRequest](https://zenno.link/castle-en) +- [ComplexImageFunCaptchaRequest](https://zenno.link/doc-complextask-rc-en) +- [ComplexImageHCaptchaRequest](https://zenno.link/doc-complextask-hc-en) +- [ComplexImageRecaptchaRequest](https://zenno.link/doc-complextask-rc-en) +- [ComplexImageTaskRecognitionRequest](https://zenno.link/doc-complex-image-recognition) - [DataDomeRequest](https://zenno.link/doc-datadome-en) +- [FriendlyRequest](https://docs.capmonster.cloud/docs/captchas/friendly-task/) +- [FunCaptchaRequest](https://docs.capmonster.cloud/docs/captchas/funcaptcha-task/) - [GeeTestRequest](https://zenno.link/doc-geetest-proxy-en) -- [HcaptchaComplexImageTaskRequest](https://zenno.link/doc-complextask-hc-en) +- [HCaptchaRequest](https://docs.capmonster.cloud/docs/captchas/) +- [HuntRequest](https://zenno.link/hunt-en) - [ImageToTextRequest](https://zenno.link/doc-ImageToTextTask-en) -- [ImpervaRequest](https://zenno.link/doc-imperva-en) -- [MTCaptcha](https://zenno.link/doc-mt-captcha-en) +- [ImpervaRequest](https://docs.capmonster.cloud/docs/captchas/incapsula/) +- [MTCaptchaRequest](https://zenno.link/doc-mt-captcha-en) - [ProsopoRequest](https://zenno.link/doc-prosopo-en) -- [RecaptchaComplexImageTaskRequest](https://zenno.link/doc-complextask-rc-en) - [RecaptchaV2EnterpriseRequest](https://zenno.link/doc-recaptcha2e-proxy-en) -- [RecaptchaV3EnterpriseRequest](https://zenno.link/doc-recaptcha3e-proxy-en) - [RecaptchaV2Request](https://zenno.link/doc-recaptcha2-proxy-en) +- [RecaptchaV3EnterpriseRequest](https://zenno.link/doc-recaptcha3e-proxy-en) - [RecaptchaV3ProxylessRequest](https://zenno.link/doc-recaptcha3-en) -- [Temu](https://zenno.link/doc-temu-en) +- [TemuRequest](https://zenno.link/doc-temu-en) - [TenDIRequest](https://zenno.link/doc-tendi-en) +- [TSPDRequest](https://zenno.link/tspd-en) - [TurnstileRequest](https://zenno.link/doc-turnstile-proxy-en) -- [Yidun](https://zenno.link/doc-yidun-en) -- [Altcha](https://zenno.link/doc-altcha-en) -- [Castle](https://zenno.link/castle-en) -- [TSPD](https://zenno.link/tspd-en) -- [Hunt](https://zenno.link/hunt-en) +- [YidunRequest](https://zenno.link/doc-yidun-en) diff --git a/package-lock.json b/package-lock.json index b7a40ff..005263c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@zennolab_com/capmonstercloud-client", - "version": "1.9.0", + "version": "2.7.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@zennolab_com/capmonstercloud-client", - "version": "1.9.0", + "version": "2.7.0", "license": "ISC", "dependencies": { "debug": "^4.3.4" @@ -26,7 +26,7 @@ "typescript": "^4.7.4" }, "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/@ampproject/remapping": { diff --git a/package.json b/package.json index aa662bd..b6e4e08 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name": "@zennolab_com/capmonstercloud-client", - "version": "2.6.1", + "version": "2.7.0", "description": "Official JS client library for https://capmonster.cloud/ captcha recognition service", "main": "dist/index.js", "types": "dist/index.d.ts", "engines": { - "node": ">=10" + "node": ">=18" }, "files": [ "dist" diff --git a/src/CapMonsterCloudClient.ts b/src/CapMonsterCloudClient.ts index 566296e..4bcc237 100644 --- a/src/CapMonsterCloudClient.ts +++ b/src/CapMonsterCloudClient.ts @@ -63,6 +63,10 @@ import { TSPDRequest } from './Requests/TSPDRequest'; import { TSPDResponse } from './Responses/TSPDResponse'; import { HuntRequest } from './Requests/HuntRequest'; import { HuntResponse } from './Responses/HuntResponse'; +import { AlibabaRequest } from './Requests/AlibabaRequest'; +import { AlibabaResponse } from './Responses/AlibabaResponse'; +import { FriendlyRequest } from './Requests/FriendlyRequest'; +import { FriendlyResponse } from './Responses/FriendlyResponse'; /** * Base type for capmonster.cloud Client exceptions @@ -295,6 +299,24 @@ export class CapMonsterCloudClient { resultTimeouts?: GetResultTimeouts, cancellationController?: AbortController, ): Promise>; + /** + * Solve Alibaba task + * You will get response within 10 - 180 secs period depending on service workload. + */ + public async Solve( + task: AlibabaRequest, + resultTimeouts?: GetResultTimeouts, + cancellationController?: AbortController, + ): Promise>; + /** + * Solve Friendly Captcha task + * You will get response within 10 - 180 secs period depending on service workload. + */ + public async Solve( + task: FriendlyRequest, + resultTimeouts?: GetResultTimeouts, + cancellationController?: AbortController, + ): Promise>; /** * Solve TenDI 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 bdb7a56..ac54cec 100644 --- a/src/CapMonsterCloudClientFactory.i.spec.ts +++ b/src/CapMonsterCloudClientFactory.i.spec.ts @@ -22,6 +22,8 @@ import { MTCaptchaRequest } from './Requests/MTCaptchaRequest'; import { CastleRequest } from './Requests/CastleRequest'; import { TSPDRequest } from './Requests/TSPDRequest'; import { HuntRequest } from './Requests/HuntRequest'; +import { AlibabaRequest } from './Requests/AlibabaRequest'; +import { FriendlyRequest } from './Requests/FriendlyRequest'; const { version } = require('../package.json'); // eslint-disable-line @typescript-eslint/no-var-requires @@ -735,6 +737,44 @@ describe('Check integration tests for CapMonsterCloudClientFactory()', () => { 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: { + incapsulaScriptUrl: '_Incapsula_Resource?SWJIYLWA=719d34d31c8e3a6e6fffd425f7e032f3', + incapsulaCookies: '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":{"incapsulaScriptUrl":"_Incapsula_Resource?SWJIYLWA=719d34d31c8e3a6e6fffd425f7e032f3","incapsulaCookies":"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 Imperva Task with Proxy', async () => { expect.assertions(5); @@ -755,8 +795,8 @@ describe('Check integration tests for CapMonsterCloudClientFactory()', () => { const impervaRequest = new ImpervaRequest({ websiteURL: 'https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=middle', metadata: { - incapsulaScriptBase64: 'dmFyIF8weGQ2ZmU9Wydce..eDUzXHg2YV', - incapsulaSessionCookie: 'l/LsGnrvyB9lNhXI8borDKa2IGc', + incapsulaScriptUrl: '_Incapsula_Resource?SWJIYLWA=719d34d31c8e3a6e6fffd425f7e032f3', + incapsulaCookies: 'l/LsGnrvyB9lNhXI8borDKa2IGc', }, proxy: { proxyType: 'http', @@ -771,7 +811,7 @@ describe('Check integration tests for CapMonsterCloudClientFactory()', () => { 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","proxyType":"http","proxyAddress":"8.8.8.8","proxyPort":8080,"proxyLogin":"proxyLoginHere","proxyPassword":"proxyPasswordHere"},"softId":54}', + '{"clientKey":"","task":{"type":"CustomTask","websiteURL":"https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=middle","metadata":{"incapsulaScriptUrl":"_Incapsula_Resource?SWJIYLWA=719d34d31c8e3a6e6fffd425f7e032f3","incapsulaCookies":"l/LsGnrvyB9lNhXI8borDKa2IGc"},"class":"Imperva","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'); @@ -1303,4 +1343,168 @@ describe('Check integration tests for CapMonsterCloudClientFactory()', () => { expect(await srv.destroy()).toBeUndefined(); }); + + it('should solve Alibaba Task', async () => { + expect.assertions(5); + + const srv = await createServerMock({ + responses: [ + { responseBody: '{"errorId":0,"taskId":1234567}' }, + { + responseBody: + '{"errorId":0,"status":"ready","solution":{"data":{"tokens":"{\\"sceneId\\":\\"1ww7426c4\\",\\"certifyId\\":\\"kBjCxX2W2c\\"}"}}}', + }, + ], + }); + + const cmcClient = CapMonsterCloudClientFactory.Create( + new ClientOptions({ clientKey: '', serviceUrl: `http://localhost:${srv.address.port}` }), + ); + + const alibabaRequest = new AlibabaRequest({ + websiteURL: 'https://www.example.com', + userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + metadata: { + sceneId: '1ww7426c4', + prefix: 'dlw3kug', + }, + }); + + const task = await cmcClient.Solve(alibabaRequest); + + expect(srv.caughtRequests[0]).toHaveProperty( + 'body', + '{"clientKey":"","task":{"type":"CustomTask","websiteURL":"https://www.example.com","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36","metadata":{"sceneId":"1ww7426c4","prefix":"dlw3kug"},"class":"alibaba"},"softId":54}', + ); + expect(srv.caughtRequests[1]).toHaveProperty('body', '{"clientKey":"","taskId":1234567}'); + expect(task).toHaveProperty('solution'); + expect(task).toHaveProperty('solution.data.tokens'); + + expect(await srv.destroy()).toBeUndefined(); + }); + + it('should solve Alibaba Task with Proxy', async () => { + expect.assertions(5); + + const srv = await createServerMock({ + responses: [ + { responseBody: '{"errorId":0,"taskId":1234567}' }, + { + responseBody: + '{"errorId":0,"status":"ready","solution":{"data":{"tokens":"{\\"sceneId\\":\\"1ww7426c4\\",\\"certifyId\\":\\"kBjCxX2W2c\\"}"}}}', + }, + ], + }); + + const cmcClient = CapMonsterCloudClientFactory.Create( + new ClientOptions({ clientKey: '', serviceUrl: `http://localhost:${srv.address.port}` }), + ); + + const alibabaRequest = new AlibabaRequest({ + websiteURL: 'https://www.example.com', + userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + metadata: { + sceneId: '1ww7426c4', + prefix: 'dlw3kug', + }, + proxy: { + proxyType: 'http', + proxyAddress: '8.8.8.8', + proxyPort: 8080, + proxyLogin: 'proxyLoginHere', + proxyPassword: 'proxyPasswordHere', + }, + }); + + const task = await cmcClient.Solve(alibabaRequest); + + expect(srv.caughtRequests[0]).toHaveProperty( + 'body', + '{"clientKey":"","task":{"type":"CustomTask","websiteURL":"https://www.example.com","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36","metadata":{"sceneId":"1ww7426c4","prefix":"dlw3kug"},"class":"alibaba","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.data.tokens'); + + expect(await srv.destroy()).toBeUndefined(); + }); + + it('should solve Friendly Task', async () => { + expect.assertions(5); + + const srv = await createServerMock({ + responses: [ + { responseBody: '{"errorId":0,"taskId":1234567}' }, + { responseBody: '{"errorId":0,"status":"ready","solution":{"data":{"token":"friendly-token"}}}' }, + ], + }); + + const cmcClient = CapMonsterCloudClientFactory.Create( + new ClientOptions({ clientKey: '', serviceUrl: `http://localhost:${srv.address.port}` }), + ); + + const friendlyRequest = new FriendlyRequest({ + websiteURL: 'https://example.com', + websiteKey: 'FFMGEMAD2K3JJ35P', + userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + metadata: { + apiGetLib: 'https://cdn.jsdelivr.net/npm/friendly-challenge@0.9.15/widget.module.min.js', + }, + }); + + const task = await cmcClient.Solve(friendlyRequest); + + expect(srv.caughtRequests[0]).toHaveProperty( + 'body', + '{"clientKey":"","task":{"type":"CustomTask","websiteURL":"https://example.com","websiteKey":"FFMGEMAD2K3JJ35P","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36","metadata":{"apiGetLib":"https://cdn.jsdelivr.net/npm/friendly-challenge@0.9.15/widget.module.min.js"},"class":"friendly"},"softId":54}', + ); + expect(srv.caughtRequests[1]).toHaveProperty('body', '{"clientKey":"","taskId":1234567}'); + expect(task).toHaveProperty('solution'); + expect(task).toHaveProperty('solution.data.token', 'friendly-token'); + + expect(await srv.destroy()).toBeUndefined(); + }); + + it('should solve Friendly Task with Proxy', async () => { + expect.assertions(5); + + const srv = await createServerMock({ + responses: [ + { responseBody: '{"errorId":0,"taskId":1234567}' }, + { responseBody: '{"errorId":0,"status":"ready","solution":{"data":{"token":"friendly-token"}}}' }, + ], + }); + + const cmcClient = CapMonsterCloudClientFactory.Create( + new ClientOptions({ clientKey: '', serviceUrl: `http://localhost:${srv.address.port}` }), + ); + + const friendlyRequest = new FriendlyRequest({ + websiteURL: 'https://example.com', + websiteKey: 'FFMGEMAD2K3JJ35P', + userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + metadata: { + apiGetLib: 'https://cdn.jsdelivr.net/npm/friendly-challenge@0.9.15/widget.module.min.js', + }, + proxy: { + proxyType: 'http', + proxyAddress: '8.8.8.8', + proxyPort: 8080, + proxyLogin: 'proxyLoginHere', + proxyPassword: 'proxyPasswordHere', + }, + }); + + const task = await cmcClient.Solve(friendlyRequest); + + expect(srv.caughtRequests[0]).toHaveProperty( + 'body', + '{"clientKey":"","task":{"type":"CustomTask","websiteURL":"https://example.com","websiteKey":"FFMGEMAD2K3JJ35P","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36","metadata":{"apiGetLib":"https://cdn.jsdelivr.net/npm/friendly-challenge@0.9.15/widget.module.min.js"},"class":"friendly","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.data.token', 'friendly-token'); + + expect(await srv.destroy()).toBeUndefined(); + }); }); diff --git a/src/GetTaskResult.ts b/src/GetTaskResult.ts index c955cc5..883782e 100644 --- a/src/GetTaskResult.ts +++ b/src/GetTaskResult.ts @@ -18,6 +18,8 @@ import { AltchaResponse } from './Responses/AltchaResponse'; import { CastleResponse } from './Responses/CastleResponse'; import { TSPDResponse } from './Responses/TSPDResponse'; import { HuntResponse } from './Responses/HuntResponse'; +import { AlibabaResponse } from './Responses/AlibabaResponse'; +import { FriendlyResponse } from './Responses/FriendlyResponse'; export enum TaskResultType { Failed = 'Failed', @@ -53,7 +55,9 @@ export type TaskCompletedSolution = | AltchaResponse | CastleResponse | TSPDResponse - | HuntResponse; + | HuntResponse + | AlibabaResponse + | FriendlyResponse; export type TaskCompleted = { type: TaskResultType.Completed; diff --git a/src/Requests/AlibabaRequest/AlibabaRequest.ts b/src/Requests/AlibabaRequest/AlibabaRequest.ts new file mode 100644 index 0000000..aef13e3 --- /dev/null +++ b/src/Requests/AlibabaRequest/AlibabaRequest.ts @@ -0,0 +1,23 @@ +import { TaskType } from '../../TaskType'; +import { AlibabaRequestBase, AlibabaRequestBaseIn } from './AlibabaRequestBase'; +import { ProxyInfo, ProxyInfoIn } from '../ProxyInfo'; + +export type AlibabaRequestIn = Pick> & { + proxy?: ProxyInfoIn; +}; + +/** + * Alibaba Captcha recognition request. + * {@link https://docs.capmonster.cloud/docs/captchas/alibaba-task/} + */ +export class AlibabaRequest extends AlibabaRequestBase { + public declare class: 'alibaba'; + + constructor({ proxy, ...argsObj }: AlibabaRequestIn) { + super({ type: TaskType.CustomTask, _class: 'alibaba', ...argsObj }); + + if (proxy) { + Object.assign(this, new ProxyInfo(proxy)); + } + } +} diff --git a/src/Requests/AlibabaRequest/AlibabaRequestBase.ts b/src/Requests/AlibabaRequest/AlibabaRequestBase.ts new file mode 100644 index 0000000..3ec72c8 --- /dev/null +++ b/src/Requests/AlibabaRequest/AlibabaRequestBase.ts @@ -0,0 +1,52 @@ +import { CaptchaRequestBase, CaptchaRequestBaseIn } from '../CaptchaRequestBase'; + +export type AlibabaMetadata = { + sceneId: string; + prefix: string; + userId?: string; + userUserId?: string; + verifyType?: string; + region?: string; + UserCertifyId?: string; + apiGetLib?: string; +}; + +export type AlibabaRequestBaseIn = { + websiteURL: string; + userAgent?: string; + metadata: AlibabaMetadata; + _class: string; +} & CaptchaRequestBaseIn; + +/** + * Base Alibaba recognition request + */ +export abstract class AlibabaRequestBase extends CaptchaRequestBase { + /** + * Address of a webpage with Alibaba Captcha. + */ + public websiteURL!: string; + + /** + * Browser User-Agent. Pass only the actual UA from Windows OS + */ + public userAgent?: string; + + /** + * Additional metadata required to solve Alibaba Captcha. + */ + public metadata!: AlibabaMetadata; + + /** + * Class of captcha object + */ + public class: string; + + constructor({ type, nocache, websiteURL, userAgent, metadata, _class }: AlibabaRequestBaseIn) { + super({ type, nocache }); + this.websiteURL = websiteURL; + this.userAgent = userAgent; + this.metadata = metadata; + this.class = _class; + } +} diff --git a/src/Requests/AlibabaRequest/index.ts b/src/Requests/AlibabaRequest/index.ts new file mode 100644 index 0000000..7f89037 --- /dev/null +++ b/src/Requests/AlibabaRequest/index.ts @@ -0,0 +1 @@ +export * from './AlibabaRequest'; diff --git a/src/Requests/AltchaRequest/AltchaRequestBase.ts b/src/Requests/AltchaRequest/AltchaRequestBase.ts index 9530b66..fedea54 100644 --- a/src/Requests/AltchaRequest/AltchaRequestBase.ts +++ b/src/Requests/AltchaRequest/AltchaRequestBase.ts @@ -2,6 +2,7 @@ import { CaptchaRequestBase, CaptchaRequestBaseIn } from '../CaptchaRequestBase' export type AltchaRequestBaseIn = { websiteURL: string; + websiteKey: string; userAgent?: string; _class: string; metadata: Metadata; @@ -43,9 +44,10 @@ export abstract class AltchaRequestBase extends CaptchaRequestBase { */ public class: string; - constructor({ type, nocache, websiteURL, userAgent, metadata, _class }: AltchaRequestBaseIn) { + constructor({ type, nocache, websiteURL, websiteKey, userAgent, metadata, _class }: AltchaRequestBaseIn) { super({ type, nocache }); this.websiteURL = websiteURL; + this.websiteKey = websiteKey; this.metadata = metadata; this.userAgent = userAgent; this.class = _class; diff --git a/src/Requests/AmazonRequest/AmazonRequestBase.ts b/src/Requests/AmazonRequest/AmazonRequestBase.ts index f9b35b6..7473635 100644 --- a/src/Requests/AmazonRequest/AmazonRequestBase.ts +++ b/src/Requests/AmazonRequest/AmazonRequestBase.ts @@ -8,6 +8,7 @@ export type AmazonRequestBaseIn = { context: string; iv: string; cookieSolution?: boolean; + userAgent?: string; } & CaptchaRequestBaseIn; /** @@ -49,7 +50,23 @@ export abstract class AmazonRequestBase extends CaptchaRequestBase { */ public cookieSolution?: boolean = false; - constructor({ type, nocache, websiteURL, challengeScript, captchaScript, websiteKey, context, iv, cookieSolution }: AmazonRequestBaseIn) { + /** + * Browser User-Agent. Pass only the actual UA from Windows OS. + */ + public userAgent?: string; + + constructor({ + type, + nocache, + websiteURL, + challengeScript, + captchaScript, + websiteKey, + context, + iv, + cookieSolution, + userAgent, + }: AmazonRequestBaseIn) { super({ type, nocache }); this.websiteURL = websiteURL; this.challengeScript = challengeScript; @@ -58,5 +75,6 @@ export abstract class AmazonRequestBase extends CaptchaRequestBase { this.context = context; this.iv = iv; this.cookieSolution = cookieSolution; + this.userAgent = userAgent; } } diff --git a/src/Requests/ComplexImageTaskRecognitionRequestBase.ts b/src/Requests/ComplexImageTaskRecognitionRequestBase.ts index cd746d3..6a062fc 100644 --- a/src/Requests/ComplexImageTaskRecognitionRequestBase.ts +++ b/src/Requests/ComplexImageTaskRecognitionRequestBase.ts @@ -3,6 +3,7 @@ import { CaptchaRequestBase, CaptchaRequestBaseIn } from './CaptchaRequestBase'; type metaData = { Task: string; TaskArgument?: string; + PayloadType?: string; }; export type ComplexImageRecognitionRequestBaseIn = { diff --git a/src/Requests/FriendlyRequest/FriendlyRequest.ts b/src/Requests/FriendlyRequest/FriendlyRequest.ts new file mode 100644 index 0000000..7dafeb4 --- /dev/null +++ b/src/Requests/FriendlyRequest/FriendlyRequest.ts @@ -0,0 +1,23 @@ +import { TaskType } from '../../TaskType'; +import { FriendlyRequestBase, FriendlyRequestBaseIn } from './FriendlyRequestBase'; +import { ProxyInfo, ProxyInfoIn } from '../ProxyInfo'; + +export type FriendlyRequestIn = Pick> & { + proxy?: ProxyInfoIn; +}; + +/** + * Friendly Captcha recognition request. + * {@link https://docs.capmonster.cloud/docs/captchas/friendly-task/} + */ +export class FriendlyRequest extends FriendlyRequestBase { + public declare class: 'friendly'; + + constructor({ proxy, ...argsObj }: FriendlyRequestIn) { + super({ type: TaskType.CustomTask, _class: 'friendly', ...argsObj }); + + if (proxy) { + Object.assign(this, new ProxyInfo(proxy)); + } + } +} diff --git a/src/Requests/FriendlyRequest/FriendlyRequestBase.ts b/src/Requests/FriendlyRequest/FriendlyRequestBase.ts new file mode 100644 index 0000000..d332d73 --- /dev/null +++ b/src/Requests/FriendlyRequest/FriendlyRequestBase.ts @@ -0,0 +1,52 @@ +import { CaptchaRequestBase, CaptchaRequestBaseIn } from '../CaptchaRequestBase'; + +export type FriendlyMetadata = { + apiGetLib: string; +}; + +export type FriendlyRequestBaseIn = { + websiteURL: string; + websiteKey: string; + userAgent?: string; + metadata: FriendlyMetadata; + _class: string; +} & CaptchaRequestBaseIn; + +/** + * Base Friendly Captcha recognition request + */ +export abstract class FriendlyRequestBase extends CaptchaRequestBase { + /** + * Address of a webpage with Friendly Captcha. + */ + public websiteURL!: string; + + /** + * Friendly Captcha sitekey. + */ + public websiteKey!: string; + + /** + * Browser User-Agent. Pass only the actual UA from Windows OS + */ + public userAgent?: string; + + /** + * Additional metadata required to solve Friendly Captcha. + */ + public metadata!: FriendlyMetadata; + + /** + * Class of captcha object + */ + public class: string; + + constructor({ type, nocache, websiteURL, websiteKey, userAgent, metadata, _class }: FriendlyRequestBaseIn) { + super({ type, nocache }); + this.websiteURL = websiteURL; + this.websiteKey = websiteKey; + this.userAgent = userAgent; + this.metadata = metadata; + this.class = _class; + } +} diff --git a/src/Requests/FriendlyRequest/index.ts b/src/Requests/FriendlyRequest/index.ts new file mode 100644 index 0000000..32c0dcc --- /dev/null +++ b/src/Requests/FriendlyRequest/index.ts @@ -0,0 +1 @@ +export * from './FriendlyRequest'; diff --git a/src/Requests/FunCaptchaRequest/FunCaptchaRequestBase.ts b/src/Requests/FunCaptchaRequest/FunCaptchaRequestBase.ts index 60f1e68..db36077 100644 --- a/src/Requests/FunCaptchaRequest/FunCaptchaRequestBase.ts +++ b/src/Requests/FunCaptchaRequest/FunCaptchaRequestBase.ts @@ -6,6 +6,7 @@ export type FunCaptchaRequestBaseIn = { funcaptchaApiJSSubdomain?: string; data?: string; cookies?: string; + userAgent?: string; } & CaptchaRequestBaseIn; /** @@ -49,12 +50,18 @@ export abstract class FunCaptchaRequestBase extends CaptchaRequestBase { */ public cookies?: string; - constructor({ type, nocache, websiteURL, websitePublicKey, funcaptchaApiJSSubdomain, data, cookies }: FunCaptchaRequestBaseIn) { + /** + * Browser's User-Agent which is used in emulation. + */ + public userAgent?: string; + + constructor({ type, nocache, websiteURL, websitePublicKey, funcaptchaApiJSSubdomain, data, cookies, userAgent }: FunCaptchaRequestBaseIn) { super({ type, nocache }); this.websiteURL = websiteURL; this.websitePublicKey = websitePublicKey; this.funcaptchaApiJSSubdomain = funcaptchaApiJSSubdomain; this.data = data; this.cookies = cookies; + this.userAgent = userAgent; } } diff --git a/src/Requests/ImpervaRequest/ImpervaRequest.ts b/src/Requests/ImpervaRequest/ImpervaRequest.ts index 03ee77d..5213540 100644 --- a/src/Requests/ImpervaRequest/ImpervaRequest.ts +++ b/src/Requests/ImpervaRequest/ImpervaRequest.ts @@ -2,16 +2,22 @@ import { TaskType } from '../../TaskType'; import { ImpervaRequestBase, ImpervaRequestBaseIn } from './ImpervaRequestBase'; import { ProxyInfo, ProxyInfoIn } from '../ProxyInfo'; -export type ImpervaRequestIn = Pick> & { proxy: ProxyInfoIn }; +export type ImpervaRequestIn = Pick> & { + proxy?: ProxyInfoIn; +}; + /** - * Imperva recognition request. - * {@link https://zenno.link/doc-imperva-en} + * Imperva (Incapsula) recognition request. + * {@link https://docs.capmonster.cloud/docs/captchas/incapsula/} */ export class ImpervaRequest extends ImpervaRequestBase { public declare class: 'Imperva'; constructor({ proxy, ...argsObj }: ImpervaRequestIn) { super({ type: TaskType.CustomTask, _class: 'Imperva', ...argsObj }); - Object.assign(this, new ProxyInfo(proxy)); + + if (proxy) { + Object.assign(this, new ProxyInfo(proxy)); + } } } diff --git a/src/Requests/ImpervaRequest/ImpervaRequestBase.ts b/src/Requests/ImpervaRequest/ImpervaRequestBase.ts index c593692..7734aeb 100644 --- a/src/Requests/ImpervaRequest/ImpervaRequestBase.ts +++ b/src/Requests/ImpervaRequest/ImpervaRequestBase.ts @@ -1,38 +1,48 @@ import { CaptchaRequestBase, CaptchaRequestBaseIn } from '../CaptchaRequestBase'; +export type ImpervaMetadata = { + /** + * Incapsula JS resource path or URL. + * @example "_Incapsula_Resource?SWJIYLWA=719d34d31c8e3a6e6fffd425f7e032f3" + */ + incapsulaScriptUrl: string; + /** + * Cookies from the Incapsula challenge page (`document.cookie` or `Set-Cookie` header). + * @example "incap_ses_1166_2930313=...; visid_incap_2930313=..." + */ + incapsulaCookies: string; + /** + * Reese84 fingerprint endpoint (request path ending with `?d=site.com`). + */ + reese84UrlEndpoint?: string; +}; + export type ImpervaRequestBaseIn = { websiteURL: string; - metadata: { - incapsulaScriptBase64: string; - incapsulaSessionCookie: string; - reese84UrlEndpoint?: string; - }; + metadata: ImpervaMetadata; userAgent?: string; _class: string; } & CaptchaRequestBaseIn; /** - * Base Imperva recognition request + * Base Imperva (Incapsula) recognition request. + * {@link https://docs.capmonster.cloud/docs/captchas/incapsula/} */ export abstract class ImpervaRequestBase extends CaptchaRequestBase { /** - * Address of a webpage with Imperva. + * Address of the main page where Incapsula is located. */ public websiteURL!: string; - public metadata: { - incapsulaScriptBase64: string; - incapsulaSessionCookie: string; - reese84UrlEndpoint?: string; - }; + public metadata: ImpervaMetadata; /** - * Browser User-Agent. Pass only the actual UA from Windows OS + * Browser User-Agent. Pass only the actual UA from Windows OS. */ public userAgent?: string; /** - * Class of captcha object + * Class of captcha object. */ public class: string; diff --git a/src/Requests/ImpervaRequest/index.ts b/src/Requests/ImpervaRequest/index.ts index b1c8f85..5dda248 100644 --- a/src/Requests/ImpervaRequest/index.ts +++ b/src/Requests/ImpervaRequest/index.ts @@ -1 +1,2 @@ export * from './ImpervaRequest'; +export type { ImpervaMetadata } from './ImpervaRequestBase'; diff --git a/src/Requests/RecaptchaV2EnterpriseRequest/RecaptchaV2EnterpriseRequestBase.ts b/src/Requests/RecaptchaV2EnterpriseRequest/RecaptchaV2EnterpriseRequestBase.ts index 5854148..5bf4f43 100644 --- a/src/Requests/RecaptchaV2EnterpriseRequest/RecaptchaV2EnterpriseRequestBase.ts +++ b/src/Requests/RecaptchaV2EnterpriseRequest/RecaptchaV2EnterpriseRequestBase.ts @@ -7,6 +7,8 @@ export type RecaptchaV2EnterpriseRequestBaseIn = { recaptchaDataSValue?: string; userAgent?: string; pageAction?: string; + apiDomain?: string; + cookies?: string; } & CaptchaRequestBaseIn; /** @@ -59,6 +61,16 @@ export abstract class RecaptchaV2EnterpriseRequestBase extends CaptchaRequestBas // The action name passed to grecaptcha.execute(). public pageAction?: string; + /** + * Domain that hosts the reCAPTCHA API interface. + */ + public apiDomain?: string; + + /** + * Additional cookies which we must use during interaction with target page or Google. + */ + public cookies?: string; + constructor({ type, nocache, @@ -68,6 +80,8 @@ export abstract class RecaptchaV2EnterpriseRequestBase extends CaptchaRequestBas recaptchaDataSValue, userAgent, pageAction, + apiDomain, + cookies, }: RecaptchaV2EnterpriseRequestBaseIn) { super({ type, nocache }); this.websiteURL = websiteURL; @@ -76,5 +90,7 @@ export abstract class RecaptchaV2EnterpriseRequestBase extends CaptchaRequestBas this.recaptchaDataSValue = recaptchaDataSValue; this.userAgent = userAgent; this.pageAction = pageAction; + this.apiDomain = apiDomain; + this.cookies = cookies; } } diff --git a/src/Requests/RecaptchaV2Request/RecaptchaV2RequestBase.ts b/src/Requests/RecaptchaV2Request/RecaptchaV2RequestBase.ts index 51b8ac3..8c475ca 100644 --- a/src/Requests/RecaptchaV2Request/RecaptchaV2RequestBase.ts +++ b/src/Requests/RecaptchaV2Request/RecaptchaV2RequestBase.ts @@ -6,6 +6,7 @@ export type RecaptchaV2RequestBaseIn = { recaptchaDataSValue?: string; userAgent?: string; cookies?: string; + isInvisible?: boolean; } & CaptchaRequestBaseIn; /** @@ -43,12 +44,18 @@ export abstract class RecaptchaV2RequestBase extends CaptchaRequestBase { */ public cookies?: string; - constructor({ type, nocache, websiteURL, websiteKey, recaptchaDataSValue, userAgent, cookies }: RecaptchaV2RequestBaseIn) { + /** + * Set true for invisible version of reCAPTCHA v2. + */ + public isInvisible?: boolean; + + constructor({ type, nocache, websiteURL, websiteKey, recaptchaDataSValue, userAgent, cookies, isInvisible }: RecaptchaV2RequestBaseIn) { super({ type, nocache }); this.websiteURL = websiteURL; this.websiteKey = websiteKey; this.recaptchaDataSValue = recaptchaDataSValue; this.userAgent = userAgent; this.cookies = cookies; + this.isInvisible = isInvisible; } } diff --git a/src/Requests/RecaptchaV3ProxylessRequest.ts b/src/Requests/RecaptchaV3ProxylessRequest.ts index 8b9af49..47f73ca 100644 --- a/src/Requests/RecaptchaV3ProxylessRequest.ts +++ b/src/Requests/RecaptchaV3ProxylessRequest.ts @@ -6,6 +6,7 @@ type RecaptchaV3RequestIn = { websiteKey: string; minScore?: number; pageAction?: string; + isEnterprise?: boolean; } & CaptchaRequestBaseIn; export type RecaptchaV3ProxylessRequestIn = Pick>; @@ -44,11 +45,17 @@ export class RecaptchaV3ProxylessRequest extends CaptchaRequestBase { */ public pageAction: string; - constructor({ nocache, websiteURL, websiteKey, minScore, pageAction = 'verify' }: RecaptchaV3ProxylessRequestIn) { + /** + * Set true to solve reCAPTCHA v3 Enterprise with the same request shape. + */ + public isEnterprise?: boolean; + + constructor({ nocache, websiteURL, websiteKey, minScore, pageAction = 'verify', isEnterprise }: RecaptchaV3ProxylessRequestIn) { super({ type: TaskType.RecaptchaV3TaskProxyless, nocache }); this.websiteURL = websiteURL; this.websiteKey = websiteKey; this.minScore = minScore; this.pageAction = pageAction; + this.isEnterprise = isEnterprise; } } diff --git a/src/Requests/RequestsSerialization.u.spec.ts b/src/Requests/RequestsSerialization.u.spec.ts index b42d787..b1c2974 100644 --- a/src/Requests/RequestsSerialization.u.spec.ts +++ b/src/Requests/RequestsSerialization.u.spec.ts @@ -1,4 +1,5 @@ import { DataDomeRequest } from './DataDomeRequest'; +import { ImpervaRequest } from './ImpervaRequest'; import { SerializeObject } from './RequestsSerialization'; import { CapMonsterModules } from '../CapMonsterModules'; import { RecaptchaV2Request } from './RecaptchaV2Request'; @@ -14,6 +15,8 @@ import { ComplexImageRecaptchaRequest } from './ComplexImageRecaptchaRequest'; import { ComplexImageFunCaptchaRequest } from './ComplexImageFunCaptchaRequest'; import { AmazonRequest } from './AmazonRequest'; import { AltchaRequest } from './AltchaRequest'; +import { AlibabaRequest } from './AlibabaRequest'; +import { FriendlyRequest } from './FriendlyRequest'; import { RecaptchaV3EnterpriseRequest } from './RecaptchaV3EnterpriseRequest'; describe('Check unit tests for SerializeObject()', () => { @@ -26,6 +29,7 @@ describe('Check unit tests for SerializeObject()', () => { recaptchaDataSValue: 'some data-s value', userAgent: 'PostmanRuntime/7.29.0', cookies: 'cookieA=value#A;cookieB=value#B', + isInvisible: true, }), }); @@ -38,6 +42,7 @@ describe('Check unit tests for SerializeObject()', () => { recaptchaDataSValue: 'some data-s value', userAgent: 'PostmanRuntime/7.29.0', cookies: 'cookieA=value#A;cookieB=value#B', + isInvisible: true, }, }); }); @@ -51,6 +56,7 @@ describe('Check unit tests for SerializeObject()', () => { recaptchaDataSValue: 'some data-s value', userAgent: 'PostmanRuntime/7.29.0', cookies: 'cookieA=value#A;cookieB=value#B', + isInvisible: true, proxy: { proxyType: 'socks4', proxyAddress: 'https://proxy.com', @@ -75,6 +81,7 @@ describe('Check unit tests for SerializeObject()', () => { proxyPort: 6045, proxyLogin: 'login', proxyPassword: 'p@ssword', + isInvisible: true, }, }); }); @@ -114,6 +121,7 @@ describe('Check unit tests for SerializeObject()', () => { websiteKey: '6Lcg7CMUAAAAANphynKgn9YAgA4tQ2KI_iqRyTwd', minScore: 0.6, pageAction: 'some-action', + isEnterprise: true, }), }); @@ -125,6 +133,7 @@ describe('Check unit tests for SerializeObject()', () => { websiteKey: '6Lcg7CMUAAAAANphynKgn9YAgA4tQ2KI_iqRyTwd', minScore: 0.6, pageAction: 'some-action', + isEnterprise: true, }, }); }); @@ -137,6 +146,7 @@ describe('Check unit tests for SerializeObject()', () => { websitePublicKey: '69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC', data: '{"blob":"dyXvXANMbHj1iDyz.Qj97JtSqR2n%2BuoY1V%2FbdgbrG7p%2FmKiqdU9AwJ6MifEt0np4vfYn6TTJDJEfZDlcz9Q1XMn9przeOV%2FCr2%2FIpi%2FC1s%3D"}', funcaptchaApiJSSubdomain: 'mywebsite-api.funcaptcha.com', + userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', }), }); @@ -148,6 +158,7 @@ describe('Check unit tests for SerializeObject()', () => { websitePublicKey: '69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC', data: '{"blob":"dyXvXANMbHj1iDyz.Qj97JtSqR2n%2BuoY1V%2FbdgbrG7p%2FmKiqdU9AwJ6MifEt0np4vfYn6TTJDJEfZDlcz9Q1XMn9przeOV%2FCr2%2FIpi%2FC1s%3D"}', funcaptchaApiJSSubdomain: 'mywebsite-api.funcaptcha.com', + userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', }, }); }); @@ -160,6 +171,7 @@ describe('Check unit tests for SerializeObject()', () => { websitePublicKey: '69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC', data: '{"blob":"dyXvXANMbHj1iDyz.Qj97JtSqR2n%2BuoY1V%2FbdgbrG7p%2FmKiqdU9AwJ6MifEt0np4vfYn6TTJDJEfZDlcz9Q1XMn9przeOV%2FCr2%2FIpi%2FC1s%3D"}', funcaptchaApiJSSubdomain: 'mywebsite-api.funcaptcha.com', + userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', proxy: { proxyType: 'socks5', proxyAddress: 'https://proxy.com', @@ -178,6 +190,7 @@ describe('Check unit tests for SerializeObject()', () => { websitePublicKey: '69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC', data: '{"blob":"dyXvXANMbHj1iDyz.Qj97JtSqR2n%2BuoY1V%2FbdgbrG7p%2FmKiqdU9AwJ6MifEt0np4vfYn6TTJDJEfZDlcz9Q1XMn9przeOV%2FCr2%2FIpi%2FC1s%3D"}', funcaptchaApiJSSubdomain: 'mywebsite-api.funcaptcha.com', + userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', proxyType: 'socks5', proxyAddress: 'https://proxy.com', proxyPort: 6045, @@ -206,7 +219,7 @@ describe('Check unit tests for SerializeObject()', () => { websiteKey: '472fc7af-86a4-4382-9a49-ca9090474471', isInvisible: true, data: 'some data', - userAgent: expect(null == undefined).toBe(true), + userAgent: expect(true).toBe(true), }, }); }); @@ -237,7 +250,7 @@ describe('Check unit tests for SerializeObject()', () => { websiteKey: '472fc7af-86a4-4382-9a49-ca9090474471', isInvisible: true, data: 'some data', - userAgent: expect(null == undefined).toBe(true), + userAgent: expect(true).toBe(true), proxyType: 'https', proxyAddress: 'https://proxy.com', proxyPort: 6045, @@ -381,6 +394,8 @@ describe('Check unit tests for SerializeObject()', () => { enterprisePayload: { s: 'SOME_ADDITIONAL_TOKEN', }, + apiDomain: 'www.recaptcha.net', + cookies: 'cookieA=value#A', }), }); @@ -393,6 +408,8 @@ describe('Check unit tests for SerializeObject()', () => { enterprisePayload: { s: 'SOME_ADDITIONAL_TOKEN', }, + apiDomain: 'www.recaptcha.net', + cookies: 'cookieA=value#A', }, }); }); @@ -408,6 +425,8 @@ describe('Check unit tests for SerializeObject()', () => { s: 'SOME_ADDITIONAL_TOKEN', }, pageAction: 'login', + apiDomain: 'www.recaptcha.net', + cookies: 'cookieA=value#A', proxy: { proxyType: 'http', proxyAddress: '8.8.8.8', @@ -433,6 +452,9 @@ describe('Check unit tests for SerializeObject()', () => { 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', + pageAction: 'login', + apiDomain: 'www.recaptcha.net', + cookies: 'cookieA=value#A', }, }); }); @@ -616,11 +638,80 @@ describe('Check unit tests for SerializeObject()', () => { }); }); + it(`should serialize ImpervaRequest`, () => { + const serialized = SerializeObject({ + clientKey: '', + task: new ImpervaRequest({ + websiteURL: 'https://www.example.com', + userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + metadata: { + incapsulaScriptUrl: '_Incapsula_Resource?SWJIYLWA=719d34d31c8e3a6e6fffd425f7e032f3', + incapsulaCookies: 'incap_ses_1166_2930313=br7iX33ZNCtf3HlpEXcuEDzz72cAAAAA0suDnBGrq/iA0J4oERYzjQ==', + reese84UrlEndpoint: 'Built-with-the-For-hopence-Hurleysurfecting-the-', + }, + }), + }); + + expect(serialized).toMatchObject({ + clientKey: '', + task: { + type: 'CustomTask', + class: 'Imperva', + websiteURL: 'https://www.example.com', + userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + metadata: { + incapsulaScriptUrl: '_Incapsula_Resource?SWJIYLWA=719d34d31c8e3a6e6fffd425f7e032f3', + incapsulaCookies: 'incap_ses_1166_2930313=br7iX33ZNCtf3HlpEXcuEDzz72cAAAAA0suDnBGrq/iA0J4oERYzjQ==', + reese84UrlEndpoint: 'Built-with-the-For-hopence-Hurleysurfecting-the-', + }, + }, + }); + }); + + it(`should serialize ImpervaRequest with proxy`, () => { + const serialized = SerializeObject({ + clientKey: '', + task: new ImpervaRequest({ + websiteURL: 'https://www.example.com', + metadata: { + incapsulaScriptUrl: '_Incapsula_Resource?SWJIYLWA=719d34d31c8e3a6e6fffd425f7e032f3', + incapsulaCookies: 'incap_ses_1166_2930313=br7iX33ZNCtf3HlpEXcuEDzz72cAAAAA0suDnBGrq/iA0J4oERYzjQ==', + }, + proxy: { + proxyType: 'http', + proxyAddress: '8.8.8.8', + proxyPort: 8080, + proxyLogin: 'proxyLoginHere', + proxyPassword: 'proxyPasswordHere', + }, + }), + }); + + expect(serialized).toMatchObject({ + clientKey: '', + task: { + type: 'CustomTask', + class: 'Imperva', + websiteURL: 'https://www.example.com', + metadata: { + incapsulaScriptUrl: '_Incapsula_Resource?SWJIYLWA=719d34d31c8e3a6e6fffd425f7e032f3', + incapsulaCookies: 'incap_ses_1166_2930313=br7iX33ZNCtf3HlpEXcuEDzz72cAAAAA0suDnBGrq/iA0J4oERYzjQ==', + }, + proxyType: 'http', + proxyAddress: '8.8.8.8', + proxyPort: 8080, + proxyLogin: 'proxyLoginHere', + proxyPassword: 'proxyPasswordHere', + }, + }); + }); + it(`should serialize AltchaRequest`, () => { const serialized = SerializeObject({ clientKey: '', task: new AltchaRequest({ websiteURL: 'site.com', + websiteKey: 'websiteKey', userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', metadata: { challenge: '3dd28253be6cc0c54d95f7f98c517e68744597cc6e66109619d1ac975c39181c', @@ -637,6 +728,7 @@ describe('Check unit tests for SerializeObject()', () => { type: 'CustomTask', class: 'altcha', websiteURL: 'site.com', + websiteKey: 'websiteKey', userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', metadata: { challenge: '3dd28253be6cc0c54d95f7f98c517e68744597cc6e66109619d1ac975c39181c', @@ -653,6 +745,7 @@ describe('Check unit tests for SerializeObject()', () => { clientKey: '', task: new AltchaRequest({ websiteURL: 'site.com', + websiteKey: 'websiteKey', userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', metadata: { challenge: '3dd28253be6cc0c54d95f7f98c517e68744597cc6e66109619d1ac975c39181c', @@ -676,6 +769,7 @@ describe('Check unit tests for SerializeObject()', () => { type: 'CustomTask', class: 'altcha', websiteURL: 'site.com', + websiteKey: 'websiteKey', userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', metadata: { challenge: '3dd28253be6cc0c54d95f7f98c517e68744597cc6e66109619d1ac975c39181c', @@ -699,6 +793,9 @@ describe('Check unit tests for SerializeObject()', () => { websiteURL: 'site.com', userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', websiteKey: '6Lcg7CMUAAAAANphynKgn9YAgA4tQ2KI_iqRyTwd', + metadata: { + captchaUrl: 'https://example.com/captcha', + }, }), }); @@ -710,6 +807,9 @@ describe('Check unit tests for SerializeObject()', () => { websiteURL: 'site.com', userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', websiteKey: '6Lcg7CMUAAAAANphynKgn9YAgA4tQ2KI_iqRyTwd', + metadata: { + captchaUrl: 'https://example.com/captcha', + }, }, }); }); @@ -721,6 +821,9 @@ describe('Check unit tests for SerializeObject()', () => { websiteURL: 'site.com', userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', websiteKey: '6Lcg7CMUAAAAANphynKgn9YAgA4tQ2KI_iqRyTwd', + metadata: { + captchaUrl: 'https://example.com/captcha', + }, proxy: { proxyType: 'socks4', proxyAddress: 'https://proxy.com', @@ -739,6 +842,9 @@ describe('Check unit tests for SerializeObject()', () => { websiteURL: 'site.com', userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', websiteKey: '6Lcg7CMUAAAAANphynKgn9YAgA4tQ2KI_iqRyTwd', + metadata: { + captchaUrl: 'https://example.com/captcha', + }, proxyType: 'socks4', proxyAddress: 'https://proxy.com', proxyPort: 6045, @@ -758,6 +864,7 @@ describe('Check unit tests for SerializeObject()', () => { captchaScript: 'https://41bcdd4fb3cb.610cd090.us-east-1.captcha.awswaf.com/41bcdd4fb3cb/0d21de737ccb/cd77baa6c832/captcha.js', context: 'qoJYgnKsc...aormh/dYYK+Y=', iv: 'CgAAXFFFFSAAABVk', + userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', }), }); @@ -771,6 +878,145 @@ describe('Check unit tests for SerializeObject()', () => { captchaScript: 'https://41bcdd4fb3cb.610cd090.us-east-1.captcha.awswaf.com/41bcdd4fb3cb/0d21de737ccb/cd77baa6c832/captcha.js', context: 'qoJYgnKsc...aormh/dYYK+Y=', iv: 'CgAAXFFFFSAAABVk', + userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + }, + }); + }); + + it(`should serialize AlibabaRequest`, () => { + const serialized = SerializeObject({ + clientKey: '', + task: new AlibabaRequest({ + websiteURL: 'https://www.example.com', + userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + metadata: { + sceneId: '1ww7426c4', + prefix: 'dlw3kug', + }, + }), + }); + + expect(serialized).toMatchObject({ + clientKey: '', + task: { + type: 'CustomTask', + class: 'alibaba', + websiteURL: 'https://www.example.com', + userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + metadata: { + sceneId: '1ww7426c4', + prefix: 'dlw3kug', + }, + }, + }); + }); + + it(`should serialize AlibabaRequest with proxy`, () => { + const serialized = SerializeObject({ + clientKey: '', + task: new AlibabaRequest({ + websiteURL: 'https://www.example.com', + userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + metadata: { + sceneId: '1ww7426c4', + prefix: 'dlw3kug', + userId: 'HpadJlQnz2zSKcSmjXBaqQvjYUvP4jMJIk/ZwGNDNiM=', + }, + proxy: { + proxyType: 'http', + proxyAddress: '8.8.8.8', + proxyPort: 8080, + proxyLogin: 'proxyLoginHere', + proxyPassword: 'proxyPasswordHere', + }, + }), + }); + + expect(serialized).toMatchObject({ + clientKey: '', + task: { + type: 'CustomTask', + class: 'alibaba', + websiteURL: 'https://www.example.com', + userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + metadata: { + sceneId: '1ww7426c4', + prefix: 'dlw3kug', + userId: 'HpadJlQnz2zSKcSmjXBaqQvjYUvP4jMJIk/ZwGNDNiM=', + }, + proxyType: 'http', + proxyAddress: '8.8.8.8', + proxyPort: 8080, + proxyLogin: 'proxyLoginHere', + proxyPassword: 'proxyPasswordHere', + }, + }); + }); + + it(`should serialize FriendlyRequest`, () => { + const serialized = SerializeObject({ + clientKey: '', + task: new FriendlyRequest({ + websiteURL: 'https://example.com', + websiteKey: 'FFMGEMAD2K3JJ35P', + userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + metadata: { + apiGetLib: 'https://cdn.jsdelivr.net/npm/friendly-challenge@0.9.15/widget.module.min.js', + }, + }), + }); + + expect(serialized).toMatchObject({ + clientKey: '', + task: { + type: 'CustomTask', + class: 'friendly', + websiteURL: 'https://example.com', + websiteKey: 'FFMGEMAD2K3JJ35P', + userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + metadata: { + apiGetLib: 'https://cdn.jsdelivr.net/npm/friendly-challenge@0.9.15/widget.module.min.js', + }, + }, + }); + }); + + it(`should serialize FriendlyRequest with proxy`, () => { + const serialized = SerializeObject({ + clientKey: '', + task: new FriendlyRequest({ + websiteURL: 'https://example.com', + websiteKey: 'FFMGEMAD2K3JJ35P', + userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + metadata: { + apiGetLib: 'https://cdn.jsdelivr.net/npm/friendly-challenge@0.9.15/widget.module.min.js', + }, + proxy: { + proxyType: 'http', + proxyAddress: '8.8.8.8', + proxyPort: 8080, + proxyLogin: 'proxyLoginHere', + proxyPassword: 'proxyPasswordHere', + }, + }), + }); + + expect(serialized).toMatchObject({ + clientKey: '', + task: { + type: 'CustomTask', + class: 'friendly', + websiteURL: 'https://example.com', + websiteKey: 'FFMGEMAD2K3JJ35P', + userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + metadata: { + apiGetLib: 'https://cdn.jsdelivr.net/npm/friendly-challenge@0.9.15/widget.module.min.js', + }, + proxyType: 'http', + proxyAddress: '8.8.8.8', + proxyPort: 8080, + proxyLogin: 'proxyLoginHere', + proxyPassword: 'proxyPasswordHere', }, }); }); diff --git a/src/Requests/Task.ts b/src/Requests/Task.ts index 741de75..02dd683 100644 --- a/src/Requests/Task.ts +++ b/src/Requests/Task.ts @@ -23,6 +23,8 @@ import { YidunRequest } from './YidunRequest'; import { MTCaptchaRequest } from './MTCaptchaRequest'; import { CastleRequest } from './CastleRequest'; import { HuntRequest } from './HuntRequest'; +import { AlibabaRequest } from './AlibabaRequest'; +import { FriendlyRequest } from './FriendlyRequest'; import { TSPDRequest } from './TSPDRequest'; /** @@ -54,4 +56,6 @@ export type Task = | MTCaptchaRequest | CastleRequest | TSPDRequest - | HuntRequest; + | HuntRequest + | AlibabaRequest + | FriendlyRequest; diff --git a/src/Requests/TenDIRequest/TenDIRequestBase.ts b/src/Requests/TenDIRequest/TenDIRequestBase.ts index 3bfb2d9..c386ff6 100644 --- a/src/Requests/TenDIRequest/TenDIRequestBase.ts +++ b/src/Requests/TenDIRequest/TenDIRequestBase.ts @@ -1,9 +1,14 @@ import { CaptchaRequestBase, CaptchaRequestBaseIn } from '../CaptchaRequestBase'; +export type TenDIMetadata = { + captchaUrl?: string; +}; + export type TenDIRequestBaseIn = { websiteURL: string; websiteKey: string; userAgent?: string; + metadata?: TenDIMetadata; _class: string; } & CaptchaRequestBaseIn; @@ -26,16 +31,22 @@ export abstract class TenDIRequestBase extends CaptchaRequestBase { */ public userAgent?: string; + /** + * Additional metadata required to solve TenDI. + */ + public metadata?: TenDIMetadata; + /** * Class of captcha object */ public class: string; - constructor({ type, nocache, websiteURL, userAgent, websiteKey, _class }: TenDIRequestBaseIn) { + constructor({ type, nocache, websiteURL, userAgent, websiteKey, metadata, _class }: TenDIRequestBaseIn) { super({ type, nocache }); this.websiteURL = websiteURL; this.websiteKey = websiteKey; this.userAgent = userAgent; + this.metadata = metadata; this.class = _class; } } diff --git a/src/Requests/TurnstileRequest/Turnstile.i.spec.ts b/src/Requests/TurnstileRequest/Turnstile.i.spec.ts index 4acaed3..2d30b5f 100644 --- a/src/Requests/TurnstileRequest/Turnstile.i.spec.ts +++ b/src/Requests/TurnstileRequest/Turnstile.i.spec.ts @@ -33,6 +33,7 @@ describe('Check integration tests for TurnstileTask', () => { pageData: 'pageDataHere', data: 'dataHere', htmlPageBase64: 'htmlPageBase64Here', + apiJsUrl: 'https://challenges.cloudflare.com/turnstile/v0/api.js', userAgent: 'userAgentHere', }); @@ -40,7 +41,7 @@ describe('Check integration tests for TurnstileTask', () => { expect(srv.caughtRequests[0]).toHaveProperty( 'body', - '{"clientKey":"","task":{"type":"TurnstileTask","websiteURL":"https://tsinvisble.zlsupport.com","websiteKey":"0x4AAAAAAABUY0VLtOUMAHxE","cloudflareTaskType":"cf_clearance","userAgent":"userAgentHere","htmlPageBase64":"htmlPageBase64Here","data":"dataHere","pageData":"pageDataHere","proxyType":"http","proxyAddress":"8.8.8.8","proxyPort":8080,"proxyLogin":"proxyLoginHere","proxyPassword":"proxyPasswordHere"},"softId":54}', + '{"clientKey":"","task":{"type":"TurnstileTask","websiteURL":"https://tsinvisble.zlsupport.com","websiteKey":"0x4AAAAAAABUY0VLtOUMAHxE","cloudflareTaskType":"cf_clearance","userAgent":"userAgentHere","htmlPageBase64":"htmlPageBase64Here","data":"dataHere","pageData":"pageDataHere","apiJsUrl":"https://challenges.cloudflare.com/turnstile/v0/api.js","proxyType":"http","proxyAddress":"8.8.8.8","proxyPort":8080,"proxyLogin":"proxyLoginHere","proxyPassword":"proxyPasswordHere"},"softId":54}', ); expect(srv.caughtRequests[1]).toHaveProperty('body', '{"clientKey":"","taskId":7654322}'); expect(task).toHaveProperty('solution'); diff --git a/src/Requests/TurnstileRequest/TurnstileRequest.ts b/src/Requests/TurnstileRequest/TurnstileRequest.ts index 6a7b62e..cd720f8 100644 --- a/src/Requests/TurnstileRequest/TurnstileRequest.ts +++ b/src/Requests/TurnstileRequest/TurnstileRequest.ts @@ -17,6 +17,7 @@ export type TurnstileCfClearanceType = Pick