From 7d0d5c4dab4fda7928c65c562eb49c5ed0f4bd2d Mon Sep 17 00:00:00 2001 From: bezzz Date: Wed, 13 Aug 2025 11:00:48 +0300 Subject: [PATCH] CCL-6505 added temu captcha solver --- README.md | 1 + package.json | 2 +- src/CapMonsterCloudClient.ts | 29 ++++---- src/CapMonsterCloudClientFactory.i.spec.ts | 82 +++++++++++++++++++++ src/Requests/TemuRequest/TemuRequest.ts | 20 +++++ src/Requests/TemuRequest/TemuRequestBase.ts | 44 +++++++++++ src/Requests/TemuRequest/index.ts | 1 + src/Responses/TemuResponse.ts | 39 ++++++++++ src/index.ts | 4 + 9 files changed, 208 insertions(+), 14 deletions(-) create mode 100644 src/Requests/TemuRequest/TemuRequest.ts create mode 100644 src/Requests/TemuRequest/TemuRequestBase.ts create mode 100644 src/Requests/TemuRequest/index.ts create mode 100644 src/Responses/TemuResponse.ts diff --git a/README.md b/README.md index 803fcfb..fbfff1a 100644 --- a/README.md +++ b/README.md @@ -88,5 +88,6 @@ DEBUG=cmc-* node app.js - [RecaptchaV2EnterpriseRequest](https://zenno.link/doc-recaptcha2e-proxy-en) - [RecaptchaV2Request](https://zenno.link/doc-recaptcha2-proxy-en) - [RecaptchaV3ProxylessRequest](https://zenno.link/doc-recaptcha3-en) +- [Temu](https://zenno.link/doc-temu-en) - [TenDIRequest](https://zenno.link/doc-tendi-en) - [TurnstileRequest](https://zenno.link/doc-turnstile-proxy-en) diff --git a/package.json b/package.json index ee38fd3..c57319b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@zennolab_com/capmonstercloud-client", - "version": "2.1.0", + "version": "2.2.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 1a9c0d3..bd395c1 100644 --- a/src/CapMonsterCloudClient.ts +++ b/src/CapMonsterCloudClient.ts @@ -47,6 +47,18 @@ import { ComplexImageTaskRecognitionRequest } from './Requests/ComplexImageTaskR import { ComplexImageRecognitionResponse } from './Responses/ComplexImageRecognitionResponse'; import { ProsopoRequest } from './Requests/ProsopoRequest'; import { ProsopoResponse } from './Responses/ProsopoResponse'; +import { TemuRequest } from './Requests/TemuRequest'; +import { TemuResponse } from './Responses/TemuResponse'; + +type CustomTaskUnion = TemuRequest | BasiliskRequest | ImpervaRequest; + +type ResponseForCustomTask = T extends TemuRequest + ? TemuResponse + : T extends BasiliskRequest + ? BasiliskResponse + : T extends ImpervaRequest + ? ImpervaResponse + : never; /** * Base type for capmonster.cloud Client exceptions @@ -235,23 +247,14 @@ export class CapMonsterCloudClient { cancellationController?: AbortController, ): Promise>; /** - * Solve Basilisk task + * Solve CustomTask 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, + public async Solve( + task: T, resultTimeouts?: GetResultTimeouts, cancellationController?: AbortController, - ): Promise>; + ): Promise>>; /** * Solve Binance 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 48a8fa6..7e80165 100644 --- a/src/CapMonsterCloudClientFactory.i.spec.ts +++ b/src/CapMonsterCloudClientFactory.i.spec.ts @@ -16,6 +16,7 @@ import { ComplexImageTaskRecognitionRequest } from './Requests/ComplexImageTaskR import { AmazonRequest } from './Requests/AmazonRequest'; import { HCaptchaRequest } from './Requests/HCaptchaRequest'; import { ProsopoRequest } from './Requests/ProsopoRequest'; +import { TemuRequest } from './Requests/TemuRequest'; const { version } = require('../package.json'); // eslint-disable-line @typescript-eslint/no-var-requires @@ -1008,4 +1009,85 @@ describe('Check integration tests for CapMonsterCloudClientFactory()', () => { expect(await srv.destroy()).toBeUndefined(); }); + + it('should solve Temu Task', async () => { + expect.assertions(5); + + const srv = await createServerMock({ + responses: [ + { responseBody: '{"errorId":0,"taskId":1234567}' }, + { + responseBody: + '{"errorId":0,"status":"ready","solution":{"domains": {"www.temu.com": {"cookies": {"privacy_setting_detail":"%7B%22firstPAds"}}}, "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 temuRequest = new TemuRequest({ + websiteURL: 'https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=middle', + metadata: { + cookie: 'region=141; language=en; currency=EUR; api_uid=CnBpI2fwFW2Bo', + }, + }); + + const task = await cmcClient.Solve(temuRequest); + + expect(srv.caughtRequests[0]).toHaveProperty( + 'body', + '{"clientKey":"","task":{"type":"CustomTask","websiteURL":"https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=middle","metadata":{"cookie":"region=141; language=en; currency=EUR; api_uid=CnBpI2fwFW2Bo"},"class":"Temu"},"softId":54}', + ); + expect(srv.caughtRequests[1]).toHaveProperty('body', '{"clientKey":"","taskId":1234567}'); + expect(task).toHaveProperty('solution'); + expect(task).toHaveProperty('solution.domains', { 'www.temu.com': { cookies: { privacy_setting_detail: '%7B%22firstPAds' } } }); + + expect(await srv.destroy()).toBeUndefined(); + }); + + it('should solve Temu Task with Proxy', async () => { + expect.assertions(5); + + const srv = await createServerMock({ + responses: [ + { responseBody: '{"errorId":0,"taskId":1234567}' }, + { + responseBody: + '{"errorId":0,"status":"ready","solution":{"domains": {"www.temu.com": {"cookies": {"privacy_setting_detail":"%7B%22firstPAds"}}}, "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 temuRequest = new TemuRequest({ + websiteURL: 'https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=middle', + metadata: { + cookie: 'region=141; language=en; currency=EUR; api_uid=CnBpI2fwFW2Bo', + }, + proxy: { + proxyType: 'http', + proxyAddress: '8.8.8.8', + proxyPort: 8080, + proxyLogin: 'proxyLoginHere', + proxyPassword: 'proxyPasswordHere', + }, + }); + + const task = await cmcClient.Solve(temuRequest); + + expect(srv.caughtRequests[0]).toHaveProperty( + 'body', + '{"clientKey":"","task":{"type":"CustomTask","websiteURL":"https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=middle","metadata":{"cookie":"region=141; language=en; currency=EUR; api_uid=CnBpI2fwFW2Bo"},"class":"Temu","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.domains', { 'www.temu.com': { cookies: { privacy_setting_detail: '%7B%22firstPAds' } } }); + + expect(await srv.destroy()).toBeUndefined(); + }); }); diff --git a/src/Requests/TemuRequest/TemuRequest.ts b/src/Requests/TemuRequest/TemuRequest.ts new file mode 100644 index 0000000..17bedcc --- /dev/null +++ b/src/Requests/TemuRequest/TemuRequest.ts @@ -0,0 +1,20 @@ +import { TaskType } from '../../TaskType'; +import { TemuRequestBase, TemuRequestBaseIn } from './TemuRequestBase'; +import { ProxyInfo, ProxyInfoIn } from '../ProxyInfo'; + +export type TemuRequestIn = Pick> & { + proxy?: ProxyInfoIn; +}; +/** + * Temu recognition request. + * {@link https://zenno.link/doc-temu-en} + */ +export class TemuRequest extends TemuRequestBase { + constructor({ proxy, ...argsObj }: TemuRequestIn) { + super({ type: TaskType.CustomTask, _class: 'Temu', ...argsObj }); + + if (proxy) { + Object.assign(this, new ProxyInfo(proxy)); + } + } +} diff --git a/src/Requests/TemuRequest/TemuRequestBase.ts b/src/Requests/TemuRequest/TemuRequestBase.ts new file mode 100644 index 0000000..04acf99 --- /dev/null +++ b/src/Requests/TemuRequest/TemuRequestBase.ts @@ -0,0 +1,44 @@ +import { CaptchaRequestBase, CaptchaRequestBaseIn } from '../CaptchaRequestBase'; + +type MetadataWithCookie = { + cookie: string; +}; +export type TemuRequestBaseIn = { + websiteURL: string; + userAgent?: string; + metadata: MetadataWithCookie; + _class: string; +} & CaptchaRequestBaseIn; + +/** + * Base Temu recognition request + */ +export abstract class TemuRequestBase extends CaptchaRequestBase { + /** + * The full URL of the page where the CAPTCHA is loaded + */ + public websiteURL!: string; + + /** + * Browser User-Agent. Pass only the actual UA from Windows OS + */ + public userAgent?: string; + + /** + * Class of captcha object + */ + public class: string; + + /** + * Cookies obtained via document.cookie on the page where the CAPTCHA is loaded + */ + public metadata: MetadataWithCookie; + + constructor({ type, nocache, websiteURL, userAgent, metadata, _class }: TemuRequestBaseIn) { + super({ type, nocache }); + this.websiteURL = websiteURL; + this.metadata = metadata; + this.userAgent = userAgent; + this.class = _class; + } +} diff --git a/src/Requests/TemuRequest/index.ts b/src/Requests/TemuRequest/index.ts new file mode 100644 index 0000000..28f0beb --- /dev/null +++ b/src/Requests/TemuRequest/index.ts @@ -0,0 +1 @@ +export * from './TemuRequest'; diff --git a/src/Responses/TemuResponse.ts b/src/Responses/TemuResponse.ts new file mode 100644 index 0000000..df6a3f5 --- /dev/null +++ b/src/Responses/TemuResponse.ts @@ -0,0 +1,39 @@ +// type Domains = Record; + +// type DomainCookies = { +// cookies: Cookies; +// }; + +type Cookies = { + privacy_setting_detail: string; + region: string; + language: string; + currency: string; + api_uid: string; + webp: string; + _nano_fp: string; + verifyAuthToken: string; + timezone: string; + _bee: string; + ___utmvc: string; + reese84: string; +}; + +/** + * Temu recognition response base + */ + +type SiteResponseType = { + cookies: Cookies; +}; + +type DomainsProps = { + [site: string]: SiteResponseType; +}; + +/** + * Imperva recognition response base + */ +export type TemuResponse = { + domains: DomainsProps; +}; diff --git a/src/index.ts b/src/index.ts index 7200a55..5ec46c9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,6 +23,7 @@ import { ImpervaRequest, ImpervaRequestIn } from './Requests/ImpervaRequest'; import { BinanceRequest, BinanceRequestIn } from './Requests/BinanceRequest'; import { ComplexImageRecognitionRequestIn, ComplexImageTaskRecognitionRequest } from './Requests/ComplexImageTaskRecognitionRequest'; import { ProsopoRequest, ProsopoRequestIn } from './Requests/ProsopoRequest'; +import { TemuRequest, TemuRequestIn } from './Requests/TemuRequest'; export default { CapMonsterCloudClientFactory, @@ -46,6 +47,7 @@ export default { BinanceRequest, ComplexImageTaskRecognitionRequest, ProsopoRequest, + TemuRequest, }; export { @@ -93,4 +95,6 @@ export { ComplexImageRecognitionRequestIn, ProsopoRequest, ProsopoRequestIn, + TemuRequest, + TemuRequestIn, };