puppeteer-pro 1.6.2 → 1.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -33,7 +33,8 @@ const solver = PuppeteerPro.solveRecaptchas('WIT_AI_ACCESS_TOKEN');
33
33
  await page.screenshot({ path: 'are-you-headless.png' });
34
34
 
35
35
  console.log('Testing the recaptcha solver..')
36
- await page.goto('https://www.google.com/recaptcha/api2/demo');
36
+ await page.goto('https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php');
37
+ await solver.waitForCaptcha(page); // Captcha script is deferred, so will load after page.goto completes
37
38
  await solver.solveRecaptcha(page);
38
39
  await page.screenshot({ path: 'is-recaptcha-solved.png' });
39
40
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "puppeteer-pro",
3
- "version": "1.6.2",
3
+ "version": "1.6.4",
4
4
  "description": "A simple puppeteer wrapper to enable useful plugins with ease",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -37,24 +37,24 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "axios": "^0.27.2",
40
- "ghost-cursor": "^1.1.13",
40
+ "ghost-cursor": "^1.1.15",
41
41
  "user-agents": "^1.0.1074"
42
42
  },
43
43
  "devDependencies": {
44
- "@types/jest": "^28.1.6",
45
- "@types/node": "^18.6.2",
44
+ "@types/jest": "^28.1.8",
45
+ "@types/node": "^18.7.23",
46
46
  "@types/user-agents": "^1.0.2",
47
- "@typescript-eslint/eslint-plugin": "^5.31.0",
48
- "@typescript-eslint/parser": "^5.31.0",
47
+ "@typescript-eslint/eslint-plugin": "^5.38.1",
48
+ "@typescript-eslint/parser": "^5.38.1",
49
49
  "copyfiles": "^2.4.1",
50
50
  "dotenv-safe": "^8.2.0",
51
- "eslint": "^8.20.0",
51
+ "eslint": "^8.24.0",
52
52
  "eslint-plugin-deprecation": "^1.3.2",
53
53
  "jest": "^28.1.3",
54
- "puppeteer": "^15.5.0",
54
+ "puppeteer": "^18.0.5",
55
55
  "rimraf": "^3.0.2",
56
- "ts-jest": "^28.0.7",
56
+ "ts-jest": "^28.0.8",
57
57
  "ts-node": "^10.9.1",
58
- "typescript": "^4.7.4"
58
+ "typescript": "^4.8.3"
59
59
  }
60
60
  }
@@ -5,6 +5,7 @@ export declare class SolveRecaptchaPlugin extends Plugin {
5
5
  dependencies: AvoidDetectionPlugin[];
6
6
  witAiAccessToken?: string;
7
7
  constructor(witAiAccessToken: string);
8
+ waitForCaptcha(page: Puppeteer.Page, timeout?: number): Promise<Puppeteer.JSHandle<false> | Puppeteer.JSHandle<true>>;
8
9
  hasCaptcha(page: Puppeteer.Page): Promise<boolean>;
9
10
  solveRecaptcha(page: Puppeteer.Page): Promise<void>;
10
11
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/solve.recaptcha/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,SAAS,MAAM,WAAW,CAAC;AAGvC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAMlE,qBAAa,oBAAqB,SAAQ,MAAM;IAC9C,YAAY,yBAAgC;IAC5C,gBAAgB,CAAC,EAAE,MAAM,CAAC;gBAEd,gBAAgB,EAAE,MAAM;IAK9B,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI;IAI/B,cAAc,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI;CAkE1C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/solve.recaptcha/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,SAAS,MAAM,WAAW,CAAC;AAGvC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAMlE,qBAAa,oBAAqB,SAAQ,MAAM;IAC9C,YAAY,yBAAgC;IAC5C,gBAAgB,CAAC,EAAE,MAAM,CAAC;gBAEd,gBAAgB,EAAE,MAAM;IAK9B,cAAc,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,MAAM;IAKrD,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI;IAK/B,cAAc,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI;CAqE1C"}
@@ -14,25 +14,31 @@ class SolveRecaptchaPlugin extends index_1.Plugin {
14
14
  this.dependencies = [new index_2.AvoidDetectionPlugin()];
15
15
  this.witAiAccessToken = witAiAccessToken;
16
16
  }
17
+ async waitForCaptcha(page, timeout) {
18
+ return page.waitForFunction(() => !!document.querySelector('iframe[src*="api2/anchor"]')
19
+ && !!document.querySelector('iframe[src*="api2/bframe"]'), { timeout });
20
+ }
17
21
  async hasCaptcha(page) {
18
- return page.evaluate(() => { var _a, _b; return !!((_b = (_a = document.querySelector('iframe[src*="api2/anchor"]')) === null || _a === void 0 ? void 0 : _a.contentDocument) === null || _b === void 0 ? void 0 : _b.querySelector('#recaptcha-anchor')); });
22
+ return page.evaluate(() => !!document.querySelector('iframe[src*="api2/anchor"]')
23
+ && !!document.querySelector('iframe[src*="api2/bframe"]'));
19
24
  }
20
25
  async solveRecaptcha(page) {
21
- var _a;
22
26
  if (this.isStopped)
23
27
  return;
24
28
  if (!this.witAiAccessToken)
25
29
  return;
26
30
  if (!(await this.hasCaptcha(page)))
27
31
  return;
32
+ const anchorFrame = page.frames().find(x => x.url().includes('api2/anchor'));
33
+ if (!anchorFrame)
34
+ return;
28
35
  const cursor = (0, ghost_cursor_1.createCursor)(page);
29
- async function waitForSelector(iframeUrlIncludes, selector) {
30
- await page.waitForFunction((_iframeUrlIncludes, _selector) => { var _a, _b; return (_b = (_a = document.querySelector(`iframe[src*="${_iframeUrlIncludes}"]`)) === null || _a === void 0 ? void 0 : _a.contentDocument) === null || _b === void 0 ? void 0 : _b.querySelector(_selector); }, {}, iframeUrlIncludes, selector);
36
+ async function waitForSelector(iframe, selector) {
37
+ await iframe.waitForFunction((_selector) => document.querySelector(_selector), {}, selector);
31
38
  }
32
- async function findAndClick(iframeUrlIncludes, selector) {
33
- var _a;
34
- await waitForSelector(iframeUrlIncludes, selector);
35
- const element = await ((_a = page.frames().find(frame => frame.url().includes(iframeUrlIncludes))) === null || _a === void 0 ? void 0 : _a.$(selector));
39
+ async function findAndClick(iframe, selector) {
40
+ await waitForSelector(iframe, selector);
41
+ const element = await iframe.$(selector);
36
42
  if (!element)
37
43
  return;
38
44
  await sleep(randomBetween(1 * 1000, 3 * 1000));
@@ -42,19 +48,19 @@ class SolveRecaptchaPlugin extends index_1.Plugin {
42
48
  async function isFinished() {
43
49
  if (--numTriesLeft === 0)
44
50
  return true;
45
- return page.evaluate(() => { var _a, _b; return !!((_b = (_a = document.querySelector('iframe[src*="api2/anchor"]')) === null || _a === void 0 ? void 0 : _a.contentDocument) === null || _b === void 0 ? void 0 : _b.querySelector('.recaptcha-checkbox-checked')); });
51
+ return anchorFrame === null || anchorFrame === void 0 ? void 0 : anchorFrame.evaluate(() => !!document.querySelector('.recaptcha-checkbox-checked'));
46
52
  }
47
- await findAndClick('api2/anchor', '#recaptcha-anchor');
48
- await findAndClick('api2/bframe', '.rc-button-audio');
53
+ await findAndClick(anchorFrame, '#recaptcha-anchor');
54
+ const bframeFrame = page.frames().find(x => x.url().includes('api2/bframe'));
55
+ if (!bframeFrame)
56
+ return;
57
+ await findAndClick(bframeFrame, '.rc-button-audio');
49
58
  while (!(await isFinished())) {
50
- await waitForSelector('api2/bframe', '.rc-audiochallenge-tdownload-link');
51
- const audioUrl = await page.evaluate(async () => {
52
- var _a, _b, _c;
53
- return (_c = (_b = (_a = document.querySelector('iframe[src*="api2/bframe"]')) === null || _a === void 0 ? void 0 : _a.contentDocument) === null || _b === void 0 ? void 0 : _b.querySelector('.rc-audiochallenge-tdownload-link')) === null || _c === void 0 ? void 0 : _c.href;
54
- });
59
+ await waitForSelector(bframeFrame, '.rc-audiochallenge-tdownload-link');
60
+ const audioUrl = await bframeFrame.evaluate(async () => { var _a; return (_a = document.querySelector('.rc-audiochallenge-tdownload-link')) === null || _a === void 0 ? void 0 : _a.href; });
55
61
  if (!audioUrl)
56
62
  return;
57
- const audioArray = await page.evaluate(injection, audioUrl);
63
+ const audioArray = await bframeFrame.evaluate(injection, audioUrl);
58
64
  if (!audioArray)
59
65
  return;
60
66
  const audioBuffer = Buffer.from(new Int8Array(audioArray));
@@ -66,13 +72,13 @@ class SolveRecaptchaPlugin extends index_1.Plugin {
66
72
  });
67
73
  const data = typeof response.data === 'string' ? JSON.parse(response.data.split('\r\n').slice(-1)[0] || '{}') : response.data;
68
74
  if (data === null || data === void 0 ? void 0 : data.text) {
69
- const responseInput = await ((_a = page.frames().find(frame => frame.url().includes('api2/bframe'))) === null || _a === void 0 ? void 0 : _a.$('#audio-response'));
75
+ const responseInput = await bframeFrame.$('#audio-response');
70
76
  await (responseInput === null || responseInput === void 0 ? void 0 : responseInput.type(data.text));
71
- await findAndClick('api2/bframe', '#recaptcha-verify-button');
77
+ await findAndClick(bframeFrame, '#recaptcha-verify-button');
72
78
  await sleep(1000);
73
79
  }
74
80
  else {
75
- await findAndClick('api2/bframe', '#recaptcha-reload-button');
81
+ await findAndClick(bframeFrame, '#recaptcha-reload-button');
76
82
  }
77
83
  }
78
84
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/plugins/solve.recaptcha/index.ts"],"names":[],"mappings":"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","sourcesContent":["import axios from 'axios';\nimport * as path from 'path';\nimport * as Puppeteer from 'puppeteer';\nimport { createCursor } from 'ghost-cursor';\n\nimport { Plugin } from '../../index';\nimport { AvoidDetectionPlugin } from './../avoid.detection/index';\n\n// eslint-disable-next-line @typescript-eslint/no-var-requires\nconst injection = require(path.resolve(`${__dirname}/injections`) + '/utils.js');\nconst randomBetween = (min: number, max: number) => Math.floor(Math.random() * (max - min)) + min;\n\nexport class SolveRecaptchaPlugin extends Plugin {\n dependencies = [new AvoidDetectionPlugin()];\n witAiAccessToken?: string;\n\n constructor(witAiAccessToken: string) {\n super();\n this.witAiAccessToken = witAiAccessToken;\n }\n\n async hasCaptcha(page: Puppeteer.Page) {\n return page.evaluate(() => !!document.querySelector<HTMLIFrameElement>('iframe[src*=\"api2/anchor\"]')?.contentDocument?.querySelector('#recaptcha-anchor'));\n }\n\n async solveRecaptcha(page: Puppeteer.Page) {\n if (this.isStopped) return;\n if (!this.witAiAccessToken) return;\n if (!(await this.hasCaptcha(page))) return;\n\n const cursor = createCursor(page);\n\n async function waitForSelector(iframeUrlIncludes: string, selector: string) {\n await page.waitForFunction((_iframeUrlIncludes: string, _selector: string) => document.querySelector<HTMLIFrameElement>(`iframe[src*=\"${_iframeUrlIncludes}\"]`)?.contentDocument?.querySelector(_selector), {}, iframeUrlIncludes, selector);\n }\n\n async function findAndClick(iframeUrlIncludes: string, selector: string) {\n await waitForSelector(iframeUrlIncludes, selector);\n\n const element = await page.frames().find(frame => frame.url().includes(iframeUrlIncludes))?.$(selector);\n if (!element) return;\n\n await sleep(randomBetween(1 * 1000, 3 * 1000));\n await cursor.click(element);\n }\n\n let numTriesLeft = 5;\n async function isFinished() {\n if (--numTriesLeft === 0) return true;\n return page.evaluate(() => !!document.querySelector<HTMLIFrameElement>('iframe[src*=\"api2/anchor\"]')?.contentDocument?.querySelector('.recaptcha-checkbox-checked'));\n }\n\n await findAndClick('api2/anchor', '#recaptcha-anchor');\n await findAndClick('api2/bframe', '.rc-button-audio');\n\n while (!(await isFinished())) {\n await waitForSelector('api2/bframe', '.rc-audiochallenge-tdownload-link');\n\n const audioUrl = await page.evaluate(async () => {\n return document.querySelector<HTMLIFrameElement>('iframe[src*=\"api2/bframe\"]')?.contentDocument?.querySelector<HTMLLinkElement>('.rc-audiochallenge-tdownload-link')?.href;\n });\n\n if (!audioUrl) return;\n\n const audioArray = await page.evaluate(injection, audioUrl);\n\n if (!audioArray) return;\n\n const audioBuffer = Buffer.from(new Int8Array(audioArray));\n\n const response = await axios.post<any>('https://api.wit.ai/speech?v=20220527', audioBuffer, {\n headers: {\n Authorization: `Bearer ${this.witAiAccessToken}`,\n 'Content-Type': 'audio/wav'\n }\n });\n\n const data = typeof response.data === 'string' ? JSON.parse(response.data.split('\\r\\n').slice(-1)[0] || '{}') : response.data;\n\n if (data?.text) {\n const responseInput = await page.frames().find(frame => frame.url().includes('api2/bframe'))?.$('#audio-response');\n await responseInput?.type(data.text);\n\n await findAndClick('api2/bframe', '#recaptcha-verify-button');\n\n await sleep(1000);\n } else {\n await findAndClick('api2/bframe', '#recaptcha-reload-button');\n }\n }\n }\n}\n\nfunction sleep(timeout: number) {\n return new Promise(resolve => setTimeout(resolve, timeout));\n}"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/plugins/solve.recaptcha/index.ts"],"names":[],"mappings":"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","sourcesContent":["import axios from 'axios';\nimport * as path from 'path';\nimport * as Puppeteer from 'puppeteer';\nimport { createCursor } from 'ghost-cursor';\n\nimport { Plugin } from '../../index';\nimport { AvoidDetectionPlugin } from './../avoid.detection/index';\n\n// eslint-disable-next-line @typescript-eslint/no-var-requires\nconst injection = require(path.resolve(`${__dirname}/injections`) + '/utils.js');\nconst randomBetween = (min: number, max: number) => Math.floor(Math.random() * (max - min)) + min;\n\nexport class SolveRecaptchaPlugin extends Plugin {\n dependencies = [new AvoidDetectionPlugin()];\n witAiAccessToken?: string;\n\n constructor(witAiAccessToken: string) {\n super();\n this.witAiAccessToken = witAiAccessToken;\n }\n\n async waitForCaptcha(page: Puppeteer.Page, timeout?: number) {\n return page.waitForFunction(() => !!document.querySelector<HTMLIFrameElement>('iframe[src*=\"api2/anchor\"]')\n && !!document.querySelector<HTMLIFrameElement>('iframe[src*=\"api2/bframe\"]'), { timeout });\n }\n\n async hasCaptcha(page: Puppeteer.Page) {\n return page.evaluate(() => !!document.querySelector<HTMLIFrameElement>('iframe[src*=\"api2/anchor\"]')\n && !!document.querySelector<HTMLIFrameElement>('iframe[src*=\"api2/bframe\"]'));\n }\n\n async solveRecaptcha(page: Puppeteer.Page) {\n if (this.isStopped) return;\n if (!this.witAiAccessToken) return;\n if (!(await this.hasCaptcha(page))) return;\n\n const anchorFrame = page.frames().find(x => x.url().includes('api2/anchor'));\n if (!anchorFrame) return;\n\n const cursor = createCursor(page);\n\n async function waitForSelector(iframe: Puppeteer.Frame, selector: string) {\n await iframe.waitForFunction((_selector: string) => document.querySelector(_selector), {}, selector);\n }\n\n async function findAndClick(iframe: Puppeteer.Frame, selector: string) {\n await waitForSelector(iframe, selector);\n\n const element = await iframe.$(selector);\n if (!element) return;\n\n await sleep(randomBetween(1 * 1000, 3 * 1000));\n await cursor.click(element);\n }\n\n let numTriesLeft = 5;\n async function isFinished() {\n if (--numTriesLeft === 0) return true;\n return anchorFrame?.evaluate(() => !!document.querySelector('.recaptcha-checkbox-checked'));\n }\n\n await findAndClick(anchorFrame, '#recaptcha-anchor');\n\n const bframeFrame = page.frames().find(x => x.url().includes('api2/bframe'));\n if (!bframeFrame) return;\n\n await findAndClick(bframeFrame, '.rc-button-audio');\n\n while (!(await isFinished())) {\n await waitForSelector(bframeFrame, '.rc-audiochallenge-tdownload-link');\n\n const audioUrl = await bframeFrame.evaluate(async () => document.querySelector<HTMLLinkElement>('.rc-audiochallenge-tdownload-link')?.href);\n if (!audioUrl) return;\n\n const audioArray = await bframeFrame.evaluate(injection, audioUrl);\n if (!audioArray) return;\n\n const audioBuffer = Buffer.from(new Int8Array(audioArray));\n\n const response = await axios.post<any>('https://api.wit.ai/speech?v=20220527', audioBuffer, {\n headers: {\n Authorization: `Bearer ${this.witAiAccessToken}`,\n 'Content-Type': 'audio/wav'\n }\n });\n\n const data = typeof response.data === 'string' ? JSON.parse(response.data.split('\\r\\n').slice(-1)[0] || '{}') : response.data;\n\n if (data?.text) {\n const responseInput = await bframeFrame.$('#audio-response');\n await responseInput?.type(data.text);\n\n await findAndClick(bframeFrame, '#recaptcha-verify-button');\n\n await sleep(1000);\n } else {\n await findAndClick(bframeFrame, '#recaptcha-reload-button');\n }\n }\n }\n}\n\nfunction sleep(timeout: number) {\n return new Promise(resolve => setTimeout(resolve, timeout));\n}"]}