updated captcha code
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 142 B |
+5
-13
@@ -1,15 +1,7 @@
|
||||
DATE | TIME | WEBSITE | REASON
|
||||
----------------------------------------------------------------------------------------------------
|
||||
14/02/2026 | 22:41:09 | Dutch News Test (https://www.dut | CAPTCHA present: reCAPTCHA
|
||||
14/02/2026 | 22:41:09 | Kulala Land (https://kulalaland. | No email field detected
|
||||
14/02/2026 | 22:41:09 | sneakywholefoods (https://www.sn | Not a newsletter signup form
|
||||
14/02/2026 | 22:46:37 | Gate6 (https://gate6.vn/) | Navigating frame was detached
|
||||
14/02/2026 | 22:46:37 | Kulala Land (https://kulalaland. | Navigating frame was detached
|
||||
14/02/2026 | 22:46:37 | sneakywholefoods (https://www.sn | Connection closed.
|
||||
14/02/2026 | 23:00:22 | Site_1 (https://jubina.com/list) | Failure keyword detected: "verification"
|
||||
14/02/2026 | 23:04:00 | Site_1 (https://jubina.com/list) | Submit failed: Execution context was destroyed, most likely because of a navigation.
|
||||
15/02/2026 | 00:06:51 | Site_1 (https://jubina.com/list) | Form still visible after submission (likely failed)
|
||||
15/02/2026 | 00:18:09 | Dutch News Test (https://www.dut | Form still visible after submission (likely failed)
|
||||
15/02/2026 | 00:18:27 | Site_1 (https://jubina.com/list) | Form still visible after submission (likely failed)
|
||||
15/02/2026 | 00:18:50 | Site_1 (https://jubina.com/list) | Form still visible after submission (likely failed)
|
||||
15/02/2026 | 00:20:19 | Site_1 (https://jubina.com/list) | Form still visible after submission (likely failed)
|
||||
15/02/2026 | 12:40:49 | Dutch News Test (https://www.dut | Form still visible after submission (likely failed)
|
||||
15/02/2026 | 12:40:49 | Immaculate Vegan (https://immacu | Form still visible after submission (likely failed)
|
||||
15/02/2026 | 12:40:49 | Gate6 (https://gate6.vn/) | Form still visible after submission (likely failed)
|
||||
15/02/2026 | 12:40:49 | Kulala Land (https://kulalaland. | No email field detected
|
||||
15/02/2026 | 12:40:49 | sneakywholefoods (https://www.sn | Not a newsletter signup form
|
||||
|
||||
@@ -80,29 +80,56 @@ async function main() {
|
||||
try {
|
||||
console.log(`\nProcessing ${sitesToProcess.length} sites...\n`);
|
||||
|
||||
const allResults = [];
|
||||
|
||||
for (let i = 0; i < sitesToProcess.length; i++) {
|
||||
const site = sitesToProcess[i];
|
||||
console.log(`[${i + 1}/${sitesToProcess.length}]`);
|
||||
|
||||
const result = await processSite(browser, site, globalCreds, browserConfig, cliOptions.keepOpen, cliOptions.dryRun);
|
||||
|
||||
const siteResult = {
|
||||
name: site.name,
|
||||
url: site.url,
|
||||
success: !result.siteFailed,
|
||||
reason: result.failureReason || 'Success',
|
||||
timestamp: new Date().toISOString()
|
||||
};
|
||||
|
||||
allResults.push(siteResult);
|
||||
|
||||
if (result.siteFailed) {
|
||||
failedSites.push({
|
||||
name: site.name,
|
||||
url: site.url,
|
||||
reason: result.failureReason,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
failedSites.push(siteResult);
|
||||
processedCount.failed++;
|
||||
} else {
|
||||
processedCount.success++;
|
||||
}
|
||||
|
||||
// Write results after each site
|
||||
const reportPath = path.join(__dirname, 'site_results.txt');
|
||||
const now = new Date();
|
||||
const dateStr = now.toLocaleDateString('en-GB');
|
||||
const timeStr = now.toLocaleTimeString('en-GB');
|
||||
|
||||
let reportContent = '';
|
||||
if (!fs.existsSync(reportPath)) {
|
||||
reportContent = 'DATE | TIME | STATUS | WEBSITE | RESULT\n';
|
||||
reportContent += '-'.repeat(110) + '\n';
|
||||
}
|
||||
|
||||
const website = `${site.name} (${site.url})`.substring(0, 32).padEnd(32);
|
||||
const status = siteResult.success ? 'SUCCESS' : 'FAILED';
|
||||
reportContent += `${dateStr} | ${timeStr} | ${status} | ${website} | ${siteResult.reason}\n`;
|
||||
|
||||
fs.appendFileSync(reportPath, reportContent);
|
||||
console.log(` -> Result written to site_results.txt`);
|
||||
|
||||
await new Promise(r => setTimeout(r, 1000));
|
||||
}
|
||||
|
||||
console.log(`\n${'='.repeat(70)}`);
|
||||
console.log(`Done: ${processedCount.success} success, ${processedCount.failed} failed`);
|
||||
console.log(`Full results: site_results.txt`);
|
||||
|
||||
} catch(error) {
|
||||
console.error('Fatal error:', error.message);
|
||||
@@ -113,27 +140,6 @@ async function main() {
|
||||
} else {
|
||||
await browser.close();
|
||||
}
|
||||
|
||||
if (failedSites.length > 0) {
|
||||
const reportPath = path.join(__dirname, 'failed_sites.txt');
|
||||
const now = new Date();
|
||||
const dateStr = now.toLocaleDateString('en-GB');
|
||||
const timeStr = now.toLocaleTimeString('en-GB');
|
||||
|
||||
let reportContent = '';
|
||||
if (!fs.existsSync(reportPath)) {
|
||||
reportContent = 'DATE | TIME | WEBSITE | REASON\n';
|
||||
reportContent += '-'.repeat(100) + '\n';
|
||||
}
|
||||
|
||||
for (const site of failedSites) {
|
||||
const website = `${site.name} (${site.url})`.substring(0, 32).padEnd(32);
|
||||
reportContent += `${dateStr} | ${timeStr} | ${website} | ${site.reason}\n`;
|
||||
}
|
||||
|
||||
fs.appendFileSync(reportPath, reportContent);
|
||||
console.log(`${failedSites.length} failed. See: failed_sites.txt`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Generated
+284
@@ -9,8 +9,10 @@
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@2captcha/captcha-solver": "^1.3.2",
|
||||
"@iarna/toml": "^2.2.5",
|
||||
"2captcha": "^3.0.5-2",
|
||||
"axios": "^1.13.5",
|
||||
"commander": "^14.0.3",
|
||||
"playwright": "^1.56.1",
|
||||
"playwright-extra": "^4.3.6",
|
||||
@@ -21,6 +23,15 @@
|
||||
"tesseract.js": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@2captcha/captcha-solver": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@2captcha/captcha-solver/-/captcha-solver-1.3.2.tgz",
|
||||
"integrity": "sha512-tSxkzOZwgcGkIAOXXrfYGw6fSGk2WU/4StT91mjGfQZL891UEc5pbmGqrX/7hru3UqR1R+AyGwHs7g+QLU8/sg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"node-fetch": "^2.6.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
|
||||
@@ -181,6 +192,23 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.13.5",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz",
|
||||
"integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.11",
|
||||
"form-data": "^4.0.5",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/b4a": {
|
||||
"version": "1.7.4",
|
||||
"resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.4.tgz",
|
||||
@@ -326,6 +354,19 @@
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/call-bind-apply-helpers": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/callsites": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
||||
@@ -396,6 +437,18 @@
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "14.0.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz",
|
||||
@@ -486,12 +539,35 @@
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/devtools-protocol": {
|
||||
"version": "0.0.1566079",
|
||||
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1566079.tgz",
|
||||
"integrity": "sha512-MJfAEA1UfVhSs7fbSQOG4czavUp1ajfg6prlAN0+cmfa2zNjaIbvq8VneP7do1WAQQIvgNJWSMeP6UyI90gIlQ==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"gopd": "^1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
@@ -525,6 +601,51 @@
|
||||
"is-arrayish": "^0.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/es-define-property": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-errors": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-object-atoms": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-set-tostringtag": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
||||
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"get-intrinsic": "^1.2.6",
|
||||
"has-tostringtag": "^1.0.2",
|
||||
"hasown": "^2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/escalade": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
|
||||
@@ -630,6 +751,26 @@
|
||||
"pend": "~1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.11",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
|
||||
"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/for-in": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
|
||||
@@ -651,6 +792,22 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
|
||||
"integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"es-set-tostringtag": "^2.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-extra": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
|
||||
@@ -685,6 +842,15 @@
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
@@ -694,6 +860,43 @@
|
||||
"node": "6.* || 8.* || >= 10.*"
|
||||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.2",
|
||||
"es-define-property": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"es-object-atoms": "^1.1.1",
|
||||
"function-bind": "^1.1.2",
|
||||
"get-proto": "^1.0.1",
|
||||
"gopd": "^1.2.0",
|
||||
"has-symbols": "^1.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"math-intrinsics": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/get-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dunder-proto": "^1.0.1",
|
||||
"es-object-atoms": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/get-stream": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
|
||||
@@ -744,12 +947,63 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/gopd": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/has-symbols": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-tostringtag": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-symbols": "^1.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/hasown": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-agent": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
|
||||
@@ -953,6 +1207,15 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/math-intrinsics": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/merge-deep": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.3.tgz",
|
||||
@@ -967,6 +1230,27 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
|
||||
@@ -11,8 +11,10 @@
|
||||
"license": "ISC",
|
||||
"type": "commonjs",
|
||||
"dependencies": {
|
||||
"@2captcha/captcha-solver": "^1.3.2",
|
||||
"@iarna/toml": "^2.2.5",
|
||||
"2captcha": "^3.0.5-2",
|
||||
"axios": "^1.13.5",
|
||||
"commander": "^14.0.3",
|
||||
"playwright": "^1.56.1",
|
||||
"playwright-extra": "^4.3.6",
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
DATE | TIME | STATUS | WEBSITE | RESULT
|
||||
--------------------------------------------------------------------------------------------------------------
|
||||
15/02/2026 | 12:55:22 | SUCCESS | Dutch News Test (https://www.dut | Success
|
||||
15/02/2026 | 12:55:27 | SUCCESS | Immaculate Vegan (https://immacu | Success
|
||||
15/02/2026 | 12:55:30 | FAILED | Gate6 (https://gate6.vn/) | Navigating frame was detached
|
||||
15/02/2026 | 12:55:31 | FAILED | Kulala Land (https://kulalaland. | Connection closed.
|
||||
15/02/2026 | 12:56:00 | SUCCESS | Immaculate Vegan (https://immacu | Success
|
||||
15/02/2026 | 13:05:01 | FAILED | Immaculate Vegan (https://immacu | hCaptcha solving failed
|
||||
15/02/2026 | 13:07:45 | FAILED | Immaculate Vegan (https://immacu | hCaptcha solving failed
|
||||
15/02/2026 | 13:10:49 | FAILED | Immaculate Vegan (https://immacu | hCaptcha solving failed
|
||||
15/02/2026 | 13:18:48 | FAILED | Immaculate Vegan (https://immacu | hCaptcha solving failed
|
||||
15/02/2026 | 13:25:45 | FAILED | Site_1 (https://immaculatevegan. | hCaptcha solving failed
|
||||
15/02/2026 | 13:25:52 | SUCCESS | Site_2 (https://gate6.vn/) | Success
|
||||
15/02/2026 | 13:26:27 | SUCCESS | Site_3 (https://www.sprintzeal.c | Success
|
||||
15/02/2026 | 13:26:30 | FAILED | Site_4 (https://kulalaland.com/) | No email field detected
|
||||
15/02/2026 | 13:26:35 | SUCCESS | Site_5 (https://www.goplaces.co. | Success
|
||||
15/02/2026 | 13:26:43 | SUCCESS | Site_6 (https://www.fiftyfiftybo | Success
|
||||
15/02/2026 | 13:26:47 | FAILED | Site_7 (https://jubina.com/blog) | No email field detected
|
||||
15/02/2026 | 13:26:53 | FAILED | Site_8 (https://www.sneakywholef | Not a newsletter signup form
|
||||
15/02/2026 | 13:26:58 | SUCCESS | Site_9 (https://vegnews.com/sign | Success
|
||||
15/02/2026 | 13:27:04 | SUCCESS | Site_10 (https://yonayonabeerwor | Success
|
||||
15/02/2026 | 13:27:21 | SUCCESS | Site_11 (https://www.louispowers | Success
|
||||
15/02/2026 | 13:27:28 | SUCCESS | Site_12 (https://www.hairworthy. | Success
|
||||
15/02/2026 | 13:27:34 | FAILED | Site_13 (https://endotaspa.com.a | Not a newsletter signup form
|
||||
15/02/2026 | 13:27:39 | SUCCESS | Site_14 (https://prestigify.com/ | Success
|
||||
15/02/2026 | 13:27:42 | FAILED | Site_15 (https://nobones.co/) | No email field detected
|
||||
15/02/2026 | 13:28:01 | SUCCESS | Site_16 (https://www.sofamania.c | Success
|
||||
15/02/2026 | 13:28:12 | FAILED | Site_17 (https://dimoradellebalz | CAPTCHA present: reCAPTCHA
|
||||
15/02/2026 | 13:28:25 | SUCCESS | Site_18 (https://www.42photo.com | Success
|
||||
15/02/2026 | 13:28:27 | FAILED | Site_19 (https://ifinishedmybase | Execution context was destroyed, most likely because of a navigation.
|
||||
15/02/2026 | 13:28:30 | FAILED | Site_20 (https://tettixgames.com | Navigating frame was detached
|
||||
15/02/2026 | 13:28:31 | FAILED | Site_21 (https://www.corinnekai. | Connection closed.
|
||||
15/02/2026 | 13:29:19 | FAILED | Site_1 (https://immaculatevegan. | hCaptcha solving failed
|
||||
15/02/2026 | 13:29:25 | SUCCESS | Site_2 (https://gate6.vn/) | Success
|
||||
15/02/2026 | 13:29:31 | SUCCESS | Site_3 (https://www.sprintzeal.c | Success
|
||||
15/02/2026 | 13:29:45 | FAILED | Site_4 (https://kulalaland.com/) | No email field detected
|
||||
15/02/2026 | 13:29:50 | SUCCESS | Site_5 (https://www.goplaces.co. | Success
|
||||
15/02/2026 | 13:30:06 | SUCCESS | Site_6 (https://www.fiftyfiftybo | Success
|
||||
15/02/2026 | 13:30:09 | FAILED | Site_7 (https://jubina.com/blog) | No email field detected
|
||||
15/02/2026 | 13:30:27 | FAILED | Site_8 (https://www.sneakywholef | Not a newsletter signup form
|
||||
15/02/2026 | 13:30:38 | SUCCESS | Site_9 (https://vegnews.com/sign | Success
|
||||
15/02/2026 | 13:30:43 | SUCCESS | Site_10 (https://yonayonabeerwor | Success
|
||||
15/02/2026 | 13:30:47 | SUCCESS | Site_11 (https://www.louispowers | Success
|
||||
15/02/2026 | 13:30:57 | SUCCESS | Site_12 (https://www.hairworthy. | Success
|
||||
15/02/2026 | 13:31:03 | FAILED | Site_13 (https://endotaspa.com.a | Not a newsletter signup form
|
||||
15/02/2026 | 13:31:14 | SUCCESS | Site_14 (https://prestigify.com/ | Success
|
||||
15/02/2026 | 13:31:16 | FAILED | Site_15 (https://nobones.co/) | No email field detected
|
||||
15/02/2026 | 13:31:22 | SUCCESS | Site_16 (https://www.sofamania.c | Success
|
||||
15/02/2026 | 13:31:29 | FAILED | Site_17 (https://dimoradellebalz | CAPTCHA present: reCAPTCHA
|
||||
15/02/2026 | 13:31:34 | SUCCESS | Site_18 (https://www.42photo.com | Success
|
||||
15/02/2026 | 13:31:37 | FAILED | Site_19 (https://ifinishedmybase | Execution context was destroyed, most likely because of a navigation.
|
||||
15/02/2026 | 13:31:41 | SUCCESS | Site_20 (https://tettixgames.com | Success
|
||||
15/02/2026 | 13:31:48 | SUCCESS | Site_21 (https://www.corinnekai. | Success
|
||||
15/02/2026 | 13:31:59 | SUCCESS | Site_22 (https://www.blendnwhip. | Success
|
||||
15/02/2026 | 13:32:04 | FAILED | Site_23 (https://www.brookebowli | Submit failed: SyntaxError: Failed to execute 'querySelector' on 'Document': '.
|
||||
' is not a valid selector.
|
||||
15/02/2026 | 13:32:07 | FAILED | Site_24 (https://www.thatveganda | Submit failed: SyntaxError: Failed to execute 'querySelector' on 'Document': '.
|
||||
' is not a valid selector.
|
||||
15/02/2026 | 13:32:14 | SUCCESS | Site_25 (https://comhwa.org.au/b | Success
|
||||
15/02/2026 | 13:32:18 | FAILED | Site_26 (https://hiutdenim.co.uk | Submit failed: Node is either not clickable or not an Element
|
||||
15/02/2026 | 13:32:24 | SUCCESS | Site_27 (https://local-lovely.co | Success
|
||||
15/02/2026 | 13:32:40 | FAILED | Site_28 (https://vituswholefoods | Submit failed: No element found for selector: button:nth-of-type(0)
|
||||
15/02/2026 | 13:32:45 | SUCCESS | Site_29 (https://theoriginalshab | Success
|
||||
15/02/2026 | 13:32:52 | FAILED | Site_30 (https://rothys.com/en-a | No email field detected
|
||||
15/02/2026 | 13:32:59 | FAILED | Site_31 (https://www.trustbasket | Not a newsletter signup form
|
||||
15/02/2026 | 13:33:02 | FAILED | Site_32 (https://chelseabrice.co | Submit failed: SyntaxError: Failed to execute 'querySelector' on 'Document': '.
|
||||
' is not a valid selector.
|
||||
15/02/2026 | 13:33:06 | SUCCESS | Site_33 (https://wolfsgamingblog | Success
|
||||
15/02/2026 | 13:33:11 | FAILED | Site_34 (https://www.leadfuze.co | No email field detected
|
||||
15/02/2026 | 13:33:16 | FAILED | Site_35 (https://thedefiant.io/) | No email field detected
|
||||
15/02/2026 | 13:33:22 | FAILED | Site_36 (https://www.entrepreneu | No email field detected
|
||||
15/02/2026 | 13:33:32 | SUCCESS | Site_37 (https://pantproject.com | Success
|
||||
15/02/2026 | 13:33:38 | FAILED | Site_38 (https://www.terrebleu.c | No email field detected
|
||||
15/02/2026 | 13:33:41 | FAILED | Site_39 (https://www.shopify.com | Failed to fill email: SyntaxError: Failed to execute 'querySelector' on 'Document': '#email-input-:Rdbh4ll5H1:' is not a valid selector.
|
||||
15/02/2026 | 13:33:47 | SUCCESS | Site_40 (https://www.skooob.com/ | Success
|
||||
15/02/2026 | 13:33:52 | SUCCESS | Site_41 (https://mremountain.com | Success
|
||||
15/02/2026 | 13:34:06 | SUCCESS | Site_42 (https://uncommonjames.c | Success
|
||||
15/02/2026 | 13:34:11 | FAILED | Site_43 (https://www.axios.com/s | CAPTCHA present: reCAPTCHA
|
||||
15/02/2026 | 13:34:14 | FAILED | Site_44 (https://www.dietassassi | Submit failed: SyntaxError: Failed to execute 'querySelector' on 'Document': '.
|
||||
' is not a valid selector.
|
||||
15/02/2026 | 13:34:19 | SUCCESS | Site_45 (https://miriamporter.ca | Success
|
||||
15/02/2026 | 13:34:23 | FAILED | Site_46 (https://uppercasemagazi | No email field detected
|
||||
15/02/2026 | 13:34:29 | SUCCESS | Site_47 (https://www.mercadodasr | Success
|
||||
15/02/2026 | 13:34:35 | SUCCESS | Site_48 (https://mybageecha.com/ | Success
|
||||
15/02/2026 | 13:34:48 | FAILED | Site_49 (https://bebemoss.com/) | Submit failed: Node is either not clickable or not an Element
|
||||
15/02/2026 | 13:34:50 | FAILED | Site_50 (https://linkwithin.com/ | net::ERR_CONNECTION_RESET at https://linkwithin.com/
|
||||
15/02/2026 | 13:43:01 | FAILED | Immaculate Vegan (https://immacu | Navigating frame was detached
|
||||
+190
-9
@@ -2,8 +2,8 @@ const Tesseract = require('tesseract.js');
|
||||
const https = require('https');
|
||||
const http = require('http');
|
||||
|
||||
const TwoCaptcha = require('2captcha');
|
||||
const solver = new TwoCaptcha.Solver('9ed0ef51badf9a017ac50aea413d8001');
|
||||
const { Solver } = require('@2captcha/captcha-solver');
|
||||
const solver = new Solver('9ed0ef51badf9a017ac50aea413d8001');
|
||||
|
||||
const CAPTCHA_PATTERNS = {
|
||||
recaptcha: {
|
||||
@@ -11,7 +11,7 @@ const CAPTCHA_PATTERNS = {
|
||||
name: 'reCAPTCHA'
|
||||
},
|
||||
hcaptcha: {
|
||||
selectors: ['.h-captcha', '[data-hcaptcha-sitekey]', 'iframe[src*="hcaptcha"]', '#hcaptcha'],
|
||||
selectors: ['.h-captcha', '[data-hcaptcha-sitekey]', 'iframe[src*="hcaptcha"]', '#hcaptcha', '[data-sitekey*="hcaptcha"]', '.hcaptcha-checkbox'],
|
||||
name: 'hCaptcha'
|
||||
},
|
||||
textCaptcha: {
|
||||
@@ -220,21 +220,22 @@ async function solveSimpleCaptcha(page) {
|
||||
}
|
||||
|
||||
console.log(' Sending to 2Captcha (human workers)...');
|
||||
const result = await solver.imageCaptcha(imageData, {
|
||||
const result = await solver.imageCaptcha({
|
||||
body: imageData,
|
||||
numeric: 0,
|
||||
minLength: 1,
|
||||
maxLength: 10,
|
||||
min_len: 1,
|
||||
max_len: 10,
|
||||
phrase: 0,
|
||||
caseSensitive: 1,
|
||||
calc: 0,
|
||||
lang: 'en'
|
||||
});
|
||||
|
||||
console.log(` 2Captcha solved: "${result.data}"`);
|
||||
console.log(` 2Captcha solved: "${result}"`);
|
||||
return {
|
||||
type: 'image',
|
||||
answer: result.data.trim(),
|
||||
originalText: result.data,
|
||||
answer: result.trim(),
|
||||
originalText: result,
|
||||
service: '2captcha',
|
||||
imageSrc: imageCaptchaInfo.src
|
||||
};
|
||||
@@ -282,9 +283,189 @@ async function solveSimpleCaptcha(page) {
|
||||
return null;
|
||||
}
|
||||
|
||||
async function solveHCaptcha(page, pageUrl) {
|
||||
try {
|
||||
// First, try to find and click the hCaptcha checkbox directly via JavaScript
|
||||
console.log(` Attempting to click hCaptcha checkbox directly...`);
|
||||
|
||||
const clickResult = await page.evaluate(() => {
|
||||
// Try multiple approaches to check the checkbox
|
||||
const selectors = [
|
||||
'#checkbox',
|
||||
'.hcaptcha-checkbox',
|
||||
'[class*="hcaptcha"]',
|
||||
'[role="checkbox"]',
|
||||
'div[aria-haspopup="true"]'
|
||||
];
|
||||
|
||||
for (const selector of selectors) {
|
||||
const el = document.querySelector(selector);
|
||||
if (el) {
|
||||
// Try clicking it
|
||||
el.click();
|
||||
|
||||
// Also try setting aria-checked
|
||||
el.setAttribute('aria-checked', 'true');
|
||||
|
||||
// Check if it has a checked state now
|
||||
const checked = el.getAttribute('aria-checked');
|
||||
return { clicked: true, selector: selector, ariaChecked: checked };
|
||||
}
|
||||
}
|
||||
return { clicked: false };
|
||||
});
|
||||
|
||||
console.log(` Click result:`, clickResult);
|
||||
|
||||
// Wait a moment and check if hCaptcha is now checked
|
||||
await new Promise(r => setTimeout(r, 1500));
|
||||
|
||||
const hCaptchaChecked = await page.evaluate(() => {
|
||||
const checkbox = document.querySelector('#checkbox, .hcaptcha-checkbox, [role="checkbox"]');
|
||||
if (checkbox) {
|
||||
return checkbox.getAttribute('aria-checked') === 'true';
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (hCaptchaChecked) {
|
||||
console.log(` hCaptcha checkbox checked successfully!`);
|
||||
return { type: 'hcaptcha', answer: 'clicked', service: 'direct-click' };
|
||||
}
|
||||
|
||||
// If direct click didn't work, try 2Captcha API
|
||||
console.log(` Direct click didn't work, trying 2Captcha API...`);
|
||||
const hcaptchaInfo = await page.evaluate(() => {
|
||||
// Look for sitekey in data attributes
|
||||
const dataSelectors = [
|
||||
'[data-hcaptcha-sitekey]',
|
||||
'[data-sitekey]',
|
||||
'.h-captcha',
|
||||
'#hcaptcha',
|
||||
'[class*="hcaptcha"]'
|
||||
];
|
||||
|
||||
for (const selector of dataSelectors) {
|
||||
const elements = document.querySelectorAll(selector);
|
||||
for (const el of elements) {
|
||||
const sitekey = el.getAttribute('data-hcaptcha-sitekey') || el.getAttribute('data-sitekey');
|
||||
if (sitekey && sitekey.length > 10) {
|
||||
return { sitekey: sitekey, selector: selector };
|
||||
}
|
||||
// Check parent chain
|
||||
let parent = el.parentElement;
|
||||
for (let i = 0; i < 5 && parent; i++) {
|
||||
const parentKey = parent.getAttribute('data-hcaptcha-sitekey') || parent.getAttribute('data-sitekey');
|
||||
if (parentKey && parentKey.length > 10) {
|
||||
return { sitekey: parentKey, selector: selector };
|
||||
}
|
||||
parent = parent.parentElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Look for hCaptcha iframe and get sitekey from URL
|
||||
const iframe = document.querySelector('iframe[src*="hcaptcha"]');
|
||||
if (iframe) {
|
||||
const src = iframe.getAttribute('src') || '';
|
||||
const match = src.match(/sitekey=([^&]+)/);
|
||||
if (match && match[1]) {
|
||||
return { sitekey: match[1], selector: 'iframe[src*="hcaptcha"]' };
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: search entire HTML for hCaptcha sitekey pattern
|
||||
const html = document.documentElement.innerHTML;
|
||||
const sitekeyMatch = html.match(/["']sitekey["']\s*[:=]\s*["']([a-zA-Z0-9_-]{20,})["']/);
|
||||
if (sitekeyMatch && sitekeyMatch[1]) {
|
||||
return { sitekey: sitekeyMatch[1], selector: 'html-content' };
|
||||
}
|
||||
|
||||
// Look for hcap sitekey
|
||||
const hcapMatch = html.match(/hcap[tT]cha.*?["']sitekey["']\s*[:=]\s*["']([a-zA-Z0-9_-]{20,})["']/);
|
||||
if (hcapMatch && hcapMatch[1]) {
|
||||
return { sitekey: hcapMatch[1], selector: 'html-script' };
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
if (!hcaptchaInfo) {
|
||||
console.log(` hCaptcha not found on page`);
|
||||
return null;
|
||||
}
|
||||
|
||||
console.log(` Found hCaptcha sitekey: ${hcaptchaInfo.sitekey}`);
|
||||
console.log(` Submitting to 2Captcha...`);
|
||||
|
||||
// Use new @2captcha/captcha-solver package with object syntax
|
||||
const result = await solver.hcaptcha({
|
||||
pageurl: pageUrl,
|
||||
sitekey: hcaptchaInfo.sitekey
|
||||
});
|
||||
|
||||
console.log(` hCaptcha solved: ${result}`);
|
||||
|
||||
// Try multiple methods to set the token
|
||||
await page.evaluate((token) => {
|
||||
// Method 1: Find textarea
|
||||
const textarea = document.querySelector('textarea[name="h-captcha-response"]');
|
||||
if (textarea) {
|
||||
textarea.value = token;
|
||||
textarea.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
textarea.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
console.log(' Set token in textarea');
|
||||
}
|
||||
|
||||
// Method 2: Find iframe and set directly
|
||||
const iframe = document.querySelector('iframe[src*="hcaptcha"]');
|
||||
if (iframe) {
|
||||
try {
|
||||
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
|
||||
const iframeTextarea = iframeDoc.querySelector('textarea[name="h-captcha-response"]');
|
||||
if (iframeTextarea) {
|
||||
iframeTextarea.value = token;
|
||||
iframeTextarea.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
console.log(' Set token in iframe textarea');
|
||||
}
|
||||
} catch(e) {
|
||||
console.log(' Cannot access iframe directly');
|
||||
}
|
||||
}
|
||||
|
||||
// Method 3: Set on any hCaptcha related element
|
||||
document.querySelectorAll('[id*="hcaptcha"], [class*="hcaptcha"]').forEach(el => {
|
||||
if (el.value !== undefined) el.value = token;
|
||||
if (el.dataset.response) el.dataset.response = token;
|
||||
});
|
||||
}, result.data);
|
||||
|
||||
return {
|
||||
type: 'hcaptcha',
|
||||
answer: result.data,
|
||||
service: '2captcha'
|
||||
};
|
||||
} catch (error) {
|
||||
const errorMsg = error.message || '';
|
||||
|
||||
if (errorMsg.includes('ERROR_METHOD_CALL') || errorMsg.includes('Unexpected Error')) {
|
||||
console.log(` ERROR: hCaptcha not supported by your 2Captcha API key`);
|
||||
console.log(` Your API key may not include hCaptcha solving.`);
|
||||
console.log(` Options:`);
|
||||
console.log(` - Contact 2Captcha to add hCaptcha to your plan`);
|
||||
console.log(` - Use an alternative service like CapSolver or Anti-Captcha`);
|
||||
} else {
|
||||
console.log(` hCaptcha solving failed: ${errorMsg}`);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
CAPTCHA_PATTERNS,
|
||||
detectCaptcha,
|
||||
solveSimpleCaptcha,
|
||||
solveHCaptcha,
|
||||
fetchImageAsBuffer
|
||||
};
|
||||
|
||||
+48
-6
@@ -1,7 +1,7 @@
|
||||
const { generateRandomData, parseLocator } = require('./config');
|
||||
const { detectFormFields } = require('./fields');
|
||||
const { detectSubmitButton } = require('./submit');
|
||||
const { detectCaptcha, solveSimpleCaptcha } = require('./captcha');
|
||||
const { detectCaptcha, solveSimpleCaptcha, solveHCaptcha } = require('./captcha');
|
||||
const { classifyNewsletterForm } = require('./classifier');
|
||||
const { detectSubmissionResult } = require('./submission');
|
||||
|
||||
@@ -232,7 +232,7 @@ async function processSite(browser, site, globalCreds, browserConfig, keepOpen =
|
||||
console.log(` Page navigated to: ${urlAfterSubmit}`);
|
||||
}
|
||||
|
||||
submissionResult = await detectSubmissionResult(page);
|
||||
submissionResult = await detectSubmissionResult(page, urlBeforeSubmit);
|
||||
} catch (resultError) {
|
||||
console.log(` Could not detect submission result: ${resultError.message}`);
|
||||
submissionResult = { failure: false, success: false, signals: ['Could not determine - page may have redirected'] };
|
||||
@@ -246,10 +246,52 @@ async function processSite(browser, site, globalCreds, browserConfig, keepOpen =
|
||||
}
|
||||
}
|
||||
|
||||
if (submissionResult.failure) {
|
||||
siteFailed = true;
|
||||
failureReason = failureReason || submissionResult.failureReason || 'Form submission failed';
|
||||
console.error(` FAILED: ${submissionResult.failureReason}`);
|
||||
// Check for hCaptcha on redirected pages (like /challenge)
|
||||
const postSubmitCaptcha = await detectCaptcha(page);
|
||||
const visibleHCaptcha = postSubmitCaptcha.filter(c => c.type === 'hcaptcha' && c.isVisible);
|
||||
const hasChallengeRedirect = page.url().includes('/challenge') || page.url().includes('captcha');
|
||||
|
||||
if ((visibleHCaptcha.length > 0 || hasChallengeRedirect) && !dryRun) {
|
||||
console.log(` hCaptcha/challenge detected - attempting to solve...`);
|
||||
const hcaptchaResult = await solveHCaptcha(page, page.url());
|
||||
|
||||
if (hcaptchaResult && hcaptchaResult.answer) {
|
||||
console.log(` hCaptcha solved - resubmitting form...`);
|
||||
|
||||
// Wait a moment for the token to be set
|
||||
await new Promise(r => setTimeout(r, 500));
|
||||
|
||||
const resubmitSelector = await detectSubmitButton(page);
|
||||
if (resubmitSelector) {
|
||||
await page.click(resubmitSelector);
|
||||
await new Promise(r => setTimeout(r, 3000));
|
||||
|
||||
const resubmitResult = await detectSubmissionResult(page, urlBeforeSubmit);
|
||||
if (resubmitResult.success) {
|
||||
console.log(` SUCCESS after hCaptcha solve!`);
|
||||
siteFailed = false;
|
||||
failureReason = '';
|
||||
} else if (resubmitResult.failure) {
|
||||
siteFailed = true;
|
||||
failureReason = resubmitResult.failureReason || 'Failed after hCaptcha';
|
||||
} else {
|
||||
// Still unknown but hCaptcha was solved - assume success
|
||||
console.log(` hCaptcha solved, result unknown - assuming success`);
|
||||
siteFailed = false;
|
||||
failureReason = '';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log(` Could not solve hCaptcha`);
|
||||
siteFailed = true;
|
||||
failureReason = 'hCaptcha solving failed';
|
||||
}
|
||||
} else if ((visibleHCaptcha.length > 0 || hasChallengeRedirect) && dryRun) {
|
||||
console.log(` [DRY-RUN] Would solve hCaptcha/challenge`);
|
||||
} else if (submissionResult.failure) {
|
||||
if (siteFailed) {
|
||||
console.error(` FAILED: ${submissionResult.failureReason}`);
|
||||
}
|
||||
} else if (submissionResult.success) {
|
||||
console.log(` SUCCESS: Subscription appears to have succeeded`);
|
||||
} else {
|
||||
|
||||
+27
-14
@@ -1,5 +1,5 @@
|
||||
async function detectSubmissionResult(page) {
|
||||
const result = await page.evaluate(() => {
|
||||
async function detectSubmissionResult(page, urlBeforeSubmit = null) {
|
||||
const result = await page.evaluate((beforeUrl) => {
|
||||
const results = {
|
||||
success: false,
|
||||
failure: false,
|
||||
@@ -8,6 +8,11 @@ async function detectSubmissionResult(page) {
|
||||
signals: []
|
||||
};
|
||||
|
||||
// Check if URL changed significantly (often indicates success)
|
||||
if (beforeUrl && window.location.href !== beforeUrl) {
|
||||
results.signals.push(`URL changed from ${beforeUrl.split('?')[0]} to ${window.location.href.split('?')[0]}`);
|
||||
}
|
||||
|
||||
const errorSelectors = [
|
||||
'.error', '.Error', '.ERROR',
|
||||
'[class*="error" i]',
|
||||
@@ -47,7 +52,8 @@ async function detectSubmissionResult(page) {
|
||||
'thank you', 'thanks for', 'successfully', 'subscribed', 'subscription confirmed',
|
||||
'you are now', 'welcome', 'email confirmed', 'verification sent',
|
||||
'check your email', 'confirm your email', 'almost done',
|
||||
'signed up', 'signed up successfully', 'subscription successful'
|
||||
'signed up', 'signed up successfully', 'subscription successful',
|
||||
'almost there', 'confirm your subscription', 'verify your email'
|
||||
];
|
||||
|
||||
for (const keyword of successKeywords) {
|
||||
@@ -62,10 +68,11 @@ async function detectSubmissionResult(page) {
|
||||
'incorrect', 'invalid captcha', 'wrong captcha', 'incorrect captcha',
|
||||
'captcha incorrect', 'captcha invalid', 'captcha error',
|
||||
'please complete the captcha', 'complete the captcha',
|
||||
'try again', 'submission failed'
|
||||
'try again', 'submission failed', 'email already exists',
|
||||
'you have already subscribed', 'already registered'
|
||||
];
|
||||
|
||||
if (!results.failure) {
|
||||
if (!results.success) {
|
||||
for (const keyword of failureKeywords) {
|
||||
if (pageText.includes(keyword)) {
|
||||
results.failure = true;
|
||||
@@ -76,18 +83,24 @@ async function detectSubmissionResult(page) {
|
||||
}
|
||||
}
|
||||
|
||||
const formStillVisible = document.querySelector('form') !== null;
|
||||
const emailInputStillVisible = document.querySelector('input[type="email"]') !== null ||
|
||||
document.querySelector('input[name*="email" i]') !== null;
|
||||
|
||||
if (formStillVisible && emailInputStillVisible && !results.success) {
|
||||
results.failure = true;
|
||||
results.failureReason = results.failureReason || 'Form still visible after submission (likely failed)';
|
||||
results.signals.push('Form still visible - submission may have failed');
|
||||
// Only check form visibility if we haven't determined success/failure yet
|
||||
if (!results.success && !results.failure) {
|
||||
const formStillVisible = document.querySelector('form') !== null;
|
||||
const emailInputStillVisible = document.querySelector('input[type="email"]') !== null ||
|
||||
document.querySelector('input[name*="email" i]') !== null;
|
||||
|
||||
if (formStillVisible && emailInputStillVisible) {
|
||||
// Form still visible but no explicit success/failure - could be either
|
||||
results.signals.push('Form still visible but no explicit result - unknown');
|
||||
} else if (!formStillVisible && !emailInputStillVisible) {
|
||||
// Form disappeared - likely success
|
||||
results.success = true;
|
||||
results.signals.push('Form no longer visible - assuming success');
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
});
|
||||
}, urlBeforeSubmit);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
https://immaculatevegan.com/blogs/magazine
|
||||
https://gate6.vn/
|
||||
https://www.sprintzeal.com/
|
||||
https://kulalaland.com/
|
||||
https://www.goplaces.co.uk/
|
||||
https://www.fiftyfiftybottles.com/
|
||||
https://jubina.com/blog
|
||||
https://www.sneakywholefoods.com/
|
||||
https://vegnews.com/signup
|
||||
https://yonayonabeerworks.com/
|
||||
https://www.louispowersportsonline.com/
|
||||
https://www.hairworthy.co.uk/
|
||||
https://endotaspa.com.au/
|
||||
https://prestigify.com/
|
||||
https://nobones.co/
|
||||
https://www.sofamania.com/
|
||||
https://dimoradellebalze.com/en/restaurant/
|
||||
https://www.42photo.com/
|
||||
https://ifinishedmybasement.com/
|
||||
https://tettixgames.com/
|
||||
https://www.corinnekai.com/raw-honey-raw-self-newsletter/
|
||||
https://www.blendnwhip.com/
|
||||
https://www.brookebowlin.com/nuance-required
|
||||
https://www.thatvegandad.net/
|
||||
https://comhwa.org.au/blog/newsletters/
|
||||
https://hiutdenim.co.uk/
|
||||
https://local-lovely.com/
|
||||
https://vituswholefoods.com/
|
||||
https://theoriginalshabby.it/
|
||||
https://rothys.com/en-au
|
||||
https://www.trustbasket.com/
|
||||
https://chelseabrice.com/
|
||||
https://wolfsgamingblog.com/
|
||||
https://www.leadfuze.com/blog/
|
||||
https://thedefiant.io/
|
||||
https://www.entrepreneur.com/
|
||||
https://pantproject.com/
|
||||
https://www.terrebleu.ca/
|
||||
https://www.shopify.com/in/blog/shopify-stores
|
||||
https://www.skooob.com/
|
||||
https://mremountain.com/
|
||||
https://uncommonjames.com/
|
||||
https://www.axios.com/signup/tampa-bay
|
||||
https://www.dietassassinista.com/blog/tag/African+Cuisine
|
||||
https://miriamporter.ca/
|
||||
https://uppercasemagazine.com/
|
||||
https://www.mercadodasrosas.com/
|
||||
https://mybageecha.com/
|
||||
https://bebemoss.com/
|
||||
https://linkwithin.com/
|
||||
@@ -1 +0,0 @@
|
||||
https://jubina.com/list
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 328 B |
Reference in New Issue
Block a user