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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
29 changes: 16 additions & 13 deletions src/CapMonsterCloudClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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> = T extends TemuRequest
? TemuResponse
: T extends BasiliskRequest
? BasiliskResponse
: T extends ImpervaRequest
? ImpervaResponse
: never;

/**
* Base type for capmonster.cloud Client exceptions
Expand Down Expand Up @@ -235,23 +247,14 @@ export class CapMonsterCloudClient {
cancellationController?: AbortController,
): Promise<CaptchaResult<TenDIResponse>>;
/**
* 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<CaptchaResult<BasiliskResponse>>;
/**
* Solve Imperva task
* You will get response within 10 - 180 secs period depending on service workload.
*/
public async Solve(
task: ImpervaRequest,
public async Solve<T extends CustomTaskUnion>(
task: T,
resultTimeouts?: GetResultTimeouts,
cancellationController?: AbortController,
): Promise<CaptchaResult<ImpervaResponse>>;
): Promise<CaptchaResult<ResponseForCustomTask<T>>>;
/**
* Solve Binance task
* You will get response within 10 - 180 secs period depending on service workload.
Expand Down
82 changes: 82 additions & 0 deletions src/CapMonsterCloudClientFactory.i.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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: '<your capmonster.cloud API key>', 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":"<your capmonster.cloud API key>","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":"<your capmonster.cloud API key>","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: '<your capmonster.cloud API key>', 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":"<your capmonster.cloud API key>","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":"<your capmonster.cloud API key>","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();
});
});
20 changes: 20 additions & 0 deletions src/Requests/TemuRequest/TemuRequest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { TaskType } from '../../TaskType';
import { TemuRequestBase, TemuRequestBaseIn } from './TemuRequestBase';
import { ProxyInfo, ProxyInfoIn } from '../ProxyInfo';

export type TemuRequestIn = Pick<TemuRequestBaseIn, Exclude<keyof TemuRequestBaseIn, 'type' | '_class'>> & {
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));
}
}
}
44 changes: 44 additions & 0 deletions src/Requests/TemuRequest/TemuRequestBase.ts
Original file line number Diff line number Diff line change
@@ -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;
}
}
1 change: 1 addition & 0 deletions src/Requests/TemuRequest/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './TemuRequest';
39 changes: 39 additions & 0 deletions src/Responses/TemuResponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// type Domains = Record<string, DomainCookies>;

// 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;
};
4 changes: 4 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -46,6 +47,7 @@ export default {
BinanceRequest,
ComplexImageTaskRecognitionRequest,
ProsopoRequest,
TemuRequest,
};

export {
Expand Down Expand Up @@ -93,4 +95,6 @@ export {
ComplexImageRecognitionRequestIn,
ProsopoRequest,
ProsopoRequestIn,
TemuRequest,
TemuRequestIn,
};