aurix-ai 2.7.2 → 2.7.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/dist/agent/AgentLoop.d.ts.map +1 -1
- package/dist/agent/AgentLoop.js +1 -52
- package/dist/agent/AgentLoop.js.map +1 -1
- package/dist/cli/App.d.ts.map +1 -1
- package/dist/cli/App.js +6 -0
- package/dist/cli/App.js.map +1 -1
- package/dist/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +7 -0
- package/dist/cli/commands.js.map +1 -1
- package/dist/tools/Browser.d.ts.map +1 -1
- package/dist/tools/Browser.js +46 -625
- package/dist/tools/Browser.js.map +1 -1
- package/dist/tools/captcha/CaptchaRouter.d.ts +6 -0
- package/dist/tools/captcha/CaptchaRouter.d.ts.map +1 -0
- package/dist/tools/captcha/CaptchaRouter.js +371 -0
- package/dist/tools/captcha/CaptchaRouter.js.map +1 -0
- package/dist/tools/captcha/RecaptchaSolver.d.ts +2 -0
- package/dist/tools/captcha/RecaptchaSolver.d.ts.map +1 -0
- package/dist/tools/captcha/RecaptchaSolver.js +1114 -0
- package/dist/tools/captcha/RecaptchaSolver.js.map +1 -0
- package/dist/tools/captcha/common.d.ts +35 -0
- package/dist/tools/captcha/common.d.ts.map +1 -0
- package/dist/tools/captcha/common.js +445 -0
- package/dist/tools/captcha/common.js.map +1 -0
- package/dist/tools/captcha/index.d.ts +5 -0
- package/dist/tools/captcha/index.d.ts.map +1 -0
- package/dist/tools/captcha/index.js +4 -0
- package/dist/tools/captcha/index.js.map +1 -0
- package/package.json +1 -2
- package/scripts/build.cjs +0 -15
- package/scripts/run-task.mjs +86 -0
- package/native/token-counter/index.d.ts +0 -7
- package/native/token-counter/index.js +0 -316
- package/native/token-counter/node_modules/.package-lock.json +0 -568
- package/native/token-counter/node_modules/2/array.js +0 -25
- package/native/token-counter/node_modules/2/index.js +0 -12
- package/native/token-counter/node_modules/2/iterator.js +0 -13
- package/native/token-counter/node_modules/2/license.txt +0 -21
- package/native/token-counter/node_modules/2/map.js +0 -27
- package/native/token-counter/node_modules/2/number.js +0 -109
- package/native/token-counter/node_modules/2/object.js +0 -23
- package/native/token-counter/node_modules/2/package.json +0 -60
- package/native/token-counter/node_modules/2/readme.md +0 -246
- package/native/token-counter/node_modules/2/string.js +0 -11
- package/native/token-counter/node_modules/2/test.js +0 -520
- package/native/token-counter/node_modules/@lamansky/every/index.js +0 -16
- package/native/token-counter/node_modules/@lamansky/every/license.txt +0 -21
- package/native/token-counter/node_modules/@lamansky/every/package.json +0 -38
- package/native/token-counter/node_modules/@lamansky/every/readme.md +0 -46
- package/native/token-counter/node_modules/@lamansky/flatten/index.js +0 -5
- package/native/token-counter/node_modules/@lamansky/flatten/license.txt +0 -21
- package/native/token-counter/node_modules/@lamansky/flatten/package.json +0 -35
- package/native/token-counter/node_modules/@lamansky/flatten/readme.md +0 -41
- package/native/token-counter/node_modules/@napi-rs/cli/LICENSE +0 -21
- package/native/token-counter/node_modules/@napi-rs/cli/README.md +0 -96
- package/native/token-counter/node_modules/@napi-rs/cli/package.json +0 -65
- package/native/token-counter/node_modules/@napi-rs/cli/scripts/index.js +0 -51371
- package/native/token-counter/node_modules/add-counter/index.js +0 -3
- package/native/token-counter/node_modules/add-counter/license.txt +0 -21
- package/native/token-counter/node_modules/add-counter/package.json +0 -34
- package/native/token-counter/node_modules/add-counter/readme.md +0 -36
- package/native/token-counter/node_modules/array-pad/LICENSE +0 -22
- package/native/token-counter/node_modules/array-pad/README.md +0 -80
- package/native/token-counter/node_modules/array-pad/index.js +0 -30
- package/native/token-counter/node_modules/array-pad/package.json +0 -28
- package/native/token-counter/node_modules/arrify/index.js +0 -8
- package/native/token-counter/node_modules/arrify/license +0 -21
- package/native/token-counter/node_modules/arrify/package.json +0 -33
- package/native/token-counter/node_modules/arrify/readme.md +0 -36
- package/native/token-counter/node_modules/case-insensitive/index.js +0 -72
- package/native/token-counter/node_modules/case-insensitive/license.txt +0 -21
- package/native/token-counter/node_modules/case-insensitive/package.json +0 -39
- package/native/token-counter/node_modules/case-insensitive/readme.md +0 -39
- package/native/token-counter/node_modules/case-insensitive/test.js +0 -114
- package/native/token-counter/node_modules/class-chain/index.js +0 -32
- package/native/token-counter/node_modules/class-chain/license.txt +0 -21
- package/native/token-counter/node_modules/class-chain/package.json +0 -39
- package/native/token-counter/node_modules/class-chain/readme.md +0 -23
- package/native/token-counter/node_modules/class-chain/test.js +0 -77
- package/native/token-counter/node_modules/copy-own/index.js +0 -10
- package/native/token-counter/node_modules/copy-own/license.txt +0 -21
- package/native/token-counter/node_modules/copy-own/package.json +0 -37
- package/native/token-counter/node_modules/copy-own/readme.md +0 -67
- package/native/token-counter/node_modules/def-props/index.js +0 -43
- package/native/token-counter/node_modules/def-props/license.txt +0 -21
- package/native/token-counter/node_modules/def-props/node_modules/is-obj/index.d.ts +0 -22
- package/native/token-counter/node_modules/def-props/node_modules/is-obj/index.js +0 -6
- package/native/token-counter/node_modules/def-props/node_modules/is-obj/license +0 -9
- package/native/token-counter/node_modules/def-props/node_modules/is-obj/package.json +0 -34
- package/native/token-counter/node_modules/def-props/node_modules/is-obj/readme.md +0 -39
- package/native/token-counter/node_modules/def-props/package.json +0 -51
- package/native/token-counter/node_modules/def-props/readme.md +0 -117
- package/native/token-counter/node_modules/empty-iterator/index.js +0 -3
- package/native/token-counter/node_modules/empty-iterator/license.txt +0 -21
- package/native/token-counter/node_modules/empty-iterator/package.json +0 -33
- package/native/token-counter/node_modules/empty-iterator/readme.md +0 -23
- package/native/token-counter/node_modules/enforce-range/index.js +0 -15
- package/native/token-counter/node_modules/enforce-range/license.txt +0 -21
- package/native/token-counter/node_modules/enforce-range/node_modules/2/array.js +0 -43
- package/native/token-counter/node_modules/enforce-range/node_modules/2/index.js +0 -10
- package/native/token-counter/node_modules/enforce-range/node_modules/2/iterator.js +0 -26
- package/native/token-counter/node_modules/enforce-range/node_modules/2/license.txt +0 -21
- package/native/token-counter/node_modules/enforce-range/node_modules/2/map.js +0 -47
- package/native/token-counter/node_modules/enforce-range/node_modules/2/number.js +0 -33
- package/native/token-counter/node_modules/enforce-range/node_modules/2/object.js +0 -61
- package/native/token-counter/node_modules/enforce-range/node_modules/2/package.json +0 -41
- package/native/token-counter/node_modules/enforce-range/node_modules/2/readme.md +0 -210
- package/native/token-counter/node_modules/enforce-range/node_modules/2/string.js +0 -37
- package/native/token-counter/node_modules/enforce-range/node_modules/2/test.js +0 -413
- package/native/token-counter/node_modules/enforce-range/package.json +0 -36
- package/native/token-counter/node_modules/enforce-range/readme.md +0 -53
- package/native/token-counter/node_modules/english-list/.travis.yml +0 -6
- package/native/token-counter/node_modules/english-list/LICENSE +0 -22
- package/native/token-counter/node_modules/english-list/README.md +0 -44
- package/native/token-counter/node_modules/english-list/index.js +0 -34
- package/native/token-counter/node_modules/english-list/package.json +0 -31
- package/native/token-counter/node_modules/english-list/test.log +0 -6
- package/native/token-counter/node_modules/errate/index.js +0 -19
- package/native/token-counter/node_modules/errate/license.txt +0 -21
- package/native/token-counter/node_modules/errate/package.json +0 -39
- package/native/token-counter/node_modules/errate/readme.md +0 -79
- package/native/token-counter/node_modules/ffn/index.js +0 -9
- package/native/token-counter/node_modules/ffn/license.txt +0 -21
- package/native/token-counter/node_modules/ffn/package.json +0 -34
- package/native/token-counter/node_modules/ffn/readme.md +0 -51
- package/native/token-counter/node_modules/get-own-property/index.js +0 -5
- package/native/token-counter/node_modules/get-own-property/license.txt +0 -21
- package/native/token-counter/node_modules/get-own-property/package.json +0 -31
- package/native/token-counter/node_modules/get-own-property/readme.md +0 -22
- package/native/token-counter/node_modules/has-duplicates/index.js +0 -11
- package/native/token-counter/node_modules/has-duplicates/license.txt +0 -21
- package/native/token-counter/node_modules/has-duplicates/package.json +0 -32
- package/native/token-counter/node_modules/has-duplicates/readme.md +0 -23
- package/native/token-counter/node_modules/has-duplicates/test.js +0 -30
- package/native/token-counter/node_modules/if-else-throw/index.js +0 -8
- package/native/token-counter/node_modules/if-else-throw/license.txt +0 -21
- package/native/token-counter/node_modules/if-else-throw/package.json +0 -37
- package/native/token-counter/node_modules/if-else-throw/readme.md +0 -32
- package/native/token-counter/node_modules/is-array-of-length/index.js +0 -7
- package/native/token-counter/node_modules/is-array-of-length/license.txt +0 -21
- package/native/token-counter/node_modules/is-array-of-length/package.json +0 -42
- package/native/token-counter/node_modules/is-array-of-length/readme.md +0 -41
- package/native/token-counter/node_modules/is-class-of/index.js +0 -7
- package/native/token-counter/node_modules/is-class-of/license.txt +0 -21
- package/native/token-counter/node_modules/is-class-of/package.json +0 -35
- package/native/token-counter/node_modules/is-class-of/readme.md +0 -57
- package/native/token-counter/node_modules/is-global-object/index.js +0 -6
- package/native/token-counter/node_modules/is-global-object/license.txt +0 -21
- package/native/token-counter/node_modules/is-global-object/package.json +0 -34
- package/native/token-counter/node_modules/is-global-object/readme.md +0 -22
- package/native/token-counter/node_modules/is-instance-of/index.js +0 -28
- package/native/token-counter/node_modules/is-instance-of/license.txt +0 -21
- package/native/token-counter/node_modules/is-instance-of/package.json +0 -44
- package/native/token-counter/node_modules/is-instance-of/readme.md +0 -55
- package/native/token-counter/node_modules/is-iterable/index.js +0 -5
- package/native/token-counter/node_modules/is-iterable/license +0 -21
- package/native/token-counter/node_modules/is-iterable/package.json +0 -30
- package/native/token-counter/node_modules/is-iterable/readme.md +0 -23
- package/native/token-counter/node_modules/is-nil/LICENSE +0 -21
- package/native/token-counter/node_modules/is-nil/README.md +0 -47
- package/native/token-counter/node_modules/is-nil/index.js +0 -6
- package/native/token-counter/node_modules/is-nil/package.json +0 -46
- package/native/token-counter/node_modules/is-obj/index.js +0 -5
- package/native/token-counter/node_modules/is-obj/license +0 -21
- package/native/token-counter/node_modules/is-obj/package.json +0 -33
- package/native/token-counter/node_modules/is-obj/readme.md +0 -34
- package/native/token-counter/node_modules/is-object/.eslintignore +0 -1
- package/native/token-counter/node_modules/is-object/.eslintrc +0 -5
- package/native/token-counter/node_modules/is-object/.nycrc +0 -13
- package/native/token-counter/node_modules/is-object/.testem.json +0 -14
- package/native/token-counter/node_modules/is-object/CHANGELOG.md +0 -121
- package/native/token-counter/node_modules/is-object/LICENSE +0 -19
- package/native/token-counter/node_modules/is-object/README.md +0 -48
- package/native/token-counter/node_modules/is-object/index.js +0 -5
- package/native/token-counter/node_modules/is-object/package.json +0 -78
- package/native/token-counter/node_modules/is-object/test/index.js +0 -44
- package/native/token-counter/node_modules/is-plain-object/LICENSE +0 -21
- package/native/token-counter/node_modules/is-plain-object/README.md +0 -104
- package/native/token-counter/node_modules/is-plain-object/index.d.ts +0 -5
- package/native/token-counter/node_modules/is-plain-object/index.js +0 -37
- package/native/token-counter/node_modules/is-plain-object/package.json +0 -79
- package/native/token-counter/node_modules/isobject/LICENSE +0 -21
- package/native/token-counter/node_modules/isobject/README.md +0 -122
- package/native/token-counter/node_modules/isobject/index.d.ts +0 -5
- package/native/token-counter/node_modules/isobject/index.js +0 -12
- package/native/token-counter/node_modules/isobject/package.json +0 -74
- package/native/token-counter/node_modules/lodash.set/LICENSE +0 -47
- package/native/token-counter/node_modules/lodash.set/README.md +0 -18
- package/native/token-counter/node_modules/lodash.set/index.js +0 -990
- package/native/token-counter/node_modules/lodash.set/package.json +0 -17
- package/native/token-counter/node_modules/longest-first/index.js +0 -3
- package/native/token-counter/node_modules/longest-first/license.txt +0 -21
- package/native/token-counter/node_modules/longest-first/package.json +0 -36
- package/native/token-counter/node_modules/longest-first/readme.md +0 -29
- package/native/token-counter/node_modules/m-o/index.js +0 -27
- package/native/token-counter/node_modules/m-o/license.txt +0 -21
- package/native/token-counter/node_modules/m-o/node_modules/new-object/index.js +0 -23
- package/native/token-counter/node_modules/m-o/node_modules/new-object/license.txt +0 -21
- package/native/token-counter/node_modules/m-o/node_modules/new-object/package.json +0 -40
- package/native/token-counter/node_modules/m-o/node_modules/new-object/readme.md +0 -55
- package/native/token-counter/node_modules/m-o/package.json +0 -45
- package/native/token-counter/node_modules/m-o/readme.md +0 -87
- package/native/token-counter/node_modules/map-iter/index.js +0 -6
- package/native/token-counter/node_modules/map-iter/license.txt +0 -21
- package/native/token-counter/node_modules/map-iter/package.json +0 -40
- package/native/token-counter/node_modules/map-iter/readme.md +0 -46
- package/native/token-counter/node_modules/new-object/index.js +0 -5
- package/native/token-counter/node_modules/new-object/license.txt +0 -21
- package/native/token-counter/node_modules/new-object/package.json +0 -49
- package/native/token-counter/node_modules/new-object/readme.md +0 -145
- package/native/token-counter/node_modules/ofn/index.js +0 -22
- package/native/token-counter/node_modules/ofn/license.txt +0 -21
- package/native/token-counter/node_modules/ofn/package.json +0 -40
- package/native/token-counter/node_modules/ofn/readme.md +0 -63
- package/native/token-counter/node_modules/otherwise/index.js +0 -11
- package/native/token-counter/node_modules/otherwise/license.txt +0 -21
- package/native/token-counter/node_modules/otherwise/package.json +0 -38
- package/native/token-counter/node_modules/otherwise/readme.md +0 -29
- package/native/token-counter/node_modules/parser-factory/index.js +0 -138
- package/native/token-counter/node_modules/parser-factory/license.txt +0 -21
- package/native/token-counter/node_modules/parser-factory/node_modules/arrify/index.d.ts +0 -38
- package/native/token-counter/node_modules/parser-factory/node_modules/arrify/index.js +0 -23
- package/native/token-counter/node_modules/parser-factory/node_modules/arrify/license +0 -9
- package/native/token-counter/node_modules/parser-factory/node_modules/arrify/package.json +0 -35
- package/native/token-counter/node_modules/parser-factory/node_modules/arrify/readme.md +0 -39
- package/native/token-counter/node_modules/parser-factory/package.json +0 -38
- package/native/token-counter/node_modules/parser-factory/readme.md +0 -15
- package/native/token-counter/node_modules/pfn/index.js +0 -5
- package/native/token-counter/node_modules/pfn/license.txt +0 -21
- package/native/token-counter/node_modules/pfn/package.json +0 -41
- package/native/token-counter/node_modules/pfn/readme.md +0 -111
- package/native/token-counter/node_modules/pfn/strict.js +0 -8
- package/native/token-counter/node_modules/plainify/index.js +0 -5
- package/native/token-counter/node_modules/plainify/license.txt +0 -21
- package/native/token-counter/node_modules/plainify/package.json +0 -36
- package/native/token-counter/node_modules/plainify/readme.md +0 -47
- package/native/token-counter/node_modules/possible-function/changelog.md +0 -7
- package/native/token-counter/node_modules/possible-function/index.js +0 -43
- package/native/token-counter/node_modules/possible-function/license.txt +0 -21
- package/native/token-counter/node_modules/possible-function/package.json +0 -34
- package/native/token-counter/node_modules/possible-function/readme.md +0 -77
- package/native/token-counter/node_modules/possible-function/test.js +0 -32
- package/native/token-counter/node_modules/qfn/index.js +0 -11
- package/native/token-counter/node_modules/qfn/license.txt +0 -21
- package/native/token-counter/node_modules/qfn/package.json +0 -40
- package/native/token-counter/node_modules/qfn/readme.md +0 -45
- package/native/token-counter/node_modules/roadblock/index.js +0 -3
- package/native/token-counter/node_modules/roadblock/license.txt +0 -21
- package/native/token-counter/node_modules/roadblock/package.json +0 -40
- package/native/token-counter/node_modules/roadblock/readme.md +0 -59
- package/native/token-counter/node_modules/round-to/index.d.ts +0 -56
- package/native/token-counter/node_modules/round-to/index.js +0 -37
- package/native/token-counter/node_modules/round-to/license +0 -9
- package/native/token-counter/node_modules/round-to/package.json +0 -38
- package/native/token-counter/node_modules/round-to/readme.md +0 -71
- package/native/token-counter/node_modules/rtrim-array/index.js +0 -10
- package/native/token-counter/node_modules/rtrim-array/license.txt +0 -21
- package/native/token-counter/node_modules/rtrim-array/package.json +0 -41
- package/native/token-counter/node_modules/rtrim-array/readme.md +0 -75
- package/native/token-counter/node_modules/sbo/index.js +0 -25
- package/native/token-counter/node_modules/sbo/license.txt +0 -21
- package/native/token-counter/node_modules/sbo/package.json +0 -50
- package/native/token-counter/node_modules/sbo/readme.md +0 -105
- package/native/token-counter/node_modules/sorp/index.js +0 -3
- package/native/token-counter/node_modules/sorp/license.txt +0 -21
- package/native/token-counter/node_modules/sorp/package.json +0 -34
- package/native/token-counter/node_modules/sorp/readme.md +0 -25
- package/native/token-counter/node_modules/trim-call/index.js +0 -6
- package/native/token-counter/node_modules/trim-call/license.txt +0 -21
- package/native/token-counter/node_modules/trim-call/package.json +0 -40
- package/native/token-counter/node_modules/trim-call/readme.md +0 -80
- package/native/token-counter/node_modules/type-error/LICENSE +0 -21
- package/native/token-counter/node_modules/type-error/README.md +0 -24
- package/native/token-counter/node_modules/type-error/index.js +0 -35
- package/native/token-counter/node_modules/type-error/package.json +0 -11
- package/native/token-counter/node_modules/vfn/index.js +0 -21
- package/native/token-counter/node_modules/vfn/license.txt +0 -21
- package/native/token-counter/node_modules/vfn/package.json +0 -40
- package/native/token-counter/node_modules/vfn/readme.md +0 -81
- package/native/token-counter/node_modules/wfn/index.js +0 -43
- package/native/token-counter/node_modules/wfn/license.txt +0 -21
- package/native/token-counter/node_modules/wfn/package.json +0 -38
- package/native/token-counter/node_modules/wfn/readme.md +0 -81
- package/native/token-counter/package-lock.json +0 -578
- package/native/token-counter/package.json +0 -21
- package/native/token-counter/token-counter.linux-x64-gnu.node +0 -0
package/dist/tools/Browser.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { launchPersistentContext, ensureBinary } from 'cloakbrowser';
|
|
2
2
|
import { homedir } from 'os';
|
|
3
3
|
import { join } from 'path';
|
|
4
|
-
import { readdirSync, readFileSync, unlinkSync } from 'fs';
|
|
5
4
|
import { loadConfig } from '../agent/Config.js';
|
|
5
|
+
import { visionClassify, readFileBase64, findGridTiles, humanClick, humanMove, humanHold, warmupBehavior, solveCaptchaGrid, autoSolveCaptcha, analyzeImageChallenge, _lastGridAnalyzeTime, bezierPoint, easeInOut, } from './captcha/index.js';
|
|
6
6
|
function ok(msg, details) {
|
|
7
7
|
const lines = [`[OK] ${msg}`];
|
|
8
8
|
if (details)
|
|
@@ -33,318 +33,6 @@ async function autoScreenshot(p, label) {
|
|
|
33
33
|
catch { }
|
|
34
34
|
return path;
|
|
35
35
|
}
|
|
36
|
-
// ─── Vision-Based Captcha Auto-Solve ──────────────────────────────────────
|
|
37
|
-
let _lastGridAnalyzeTime = 0;
|
|
38
|
-
function readFileBase64(path) {
|
|
39
|
-
return readFileSync(path).toString('base64');
|
|
40
|
-
}
|
|
41
|
-
async function visionClassify(imageBase64, prompt) {
|
|
42
|
-
const config = loadConfig();
|
|
43
|
-
const visionModel = config.visionModel || config.model || 'gpt-4o';
|
|
44
|
-
const visionBaseUrl = config.visionBaseUrl || config.baseUrl;
|
|
45
|
-
const visionApiKey = config.visionApiKey || config.apiKey;
|
|
46
|
-
const body = {
|
|
47
|
-
model: visionModel,
|
|
48
|
-
messages: [{
|
|
49
|
-
role: 'user',
|
|
50
|
-
content: [
|
|
51
|
-
{ type: 'text', text: prompt },
|
|
52
|
-
{ type: 'image_url', image_url: { url: `data:image/png;base64,${imageBase64}` } },
|
|
53
|
-
],
|
|
54
|
-
}],
|
|
55
|
-
max_tokens: 100,
|
|
56
|
-
};
|
|
57
|
-
const controller = new AbortController();
|
|
58
|
-
const fetchTimeout = setTimeout(() => controller.abort(), 15_000);
|
|
59
|
-
try {
|
|
60
|
-
const resp = await fetch(`${visionBaseUrl}/chat/completions`, {
|
|
61
|
-
method: 'POST',
|
|
62
|
-
headers: {
|
|
63
|
-
'Content-Type': 'application/json',
|
|
64
|
-
...(visionApiKey ? { Authorization: `Bearer ${visionApiKey}` } : {}),
|
|
65
|
-
},
|
|
66
|
-
body: JSON.stringify(body),
|
|
67
|
-
signal: controller.signal,
|
|
68
|
-
});
|
|
69
|
-
if (!resp.ok)
|
|
70
|
-
throw new Error(`Vision API error: ${resp.status}`);
|
|
71
|
-
const text = await resp.text();
|
|
72
|
-
if (text.includes('data: ')) {
|
|
73
|
-
let content = '';
|
|
74
|
-
for (const line of text.split('\n')) {
|
|
75
|
-
if (line.startsWith('data: ') && line.trim() !== 'data: [DONE]') {
|
|
76
|
-
try {
|
|
77
|
-
const ev = JSON.parse(line.slice(6));
|
|
78
|
-
const delta = ev.choices?.[0]?.delta;
|
|
79
|
-
if (delta?.content)
|
|
80
|
-
content += delta.content;
|
|
81
|
-
if (delta?.text)
|
|
82
|
-
content += delta.text;
|
|
83
|
-
if (ev.choices?.[0]?.message?.content)
|
|
84
|
-
content += ev.choices[0].message.content;
|
|
85
|
-
}
|
|
86
|
-
catch { }
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
return content.trim();
|
|
90
|
-
}
|
|
91
|
-
const json = JSON.parse(text);
|
|
92
|
-
return (json.choices?.[0]?.message?.content || '').trim();
|
|
93
|
-
}
|
|
94
|
-
finally {
|
|
95
|
-
clearTimeout(fetchTimeout);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
async function solveCaptchaGrid(page, frame, provider) {
|
|
99
|
-
const results = [];
|
|
100
|
-
const isRecaptcha = provider === 'recaptcha';
|
|
101
|
-
let instruction = '';
|
|
102
|
-
try {
|
|
103
|
-
const instrEl = frame.locator('.rc-imageselect-instructions, .prompt-text, .prompt-text-h, .geetest_tip_content, .mtcaptcha-label');
|
|
104
|
-
if (await instrEl.count() > 0) {
|
|
105
|
-
instruction = (await instrEl.first().textContent() || '').trim();
|
|
106
|
-
}
|
|
107
|
-
if (!instruction) {
|
|
108
|
-
const strongText = frame.locator('strong').first();
|
|
109
|
-
if (await strongText.count() > 0)
|
|
110
|
-
instruction = (await strongText.textContent() || '').trim();
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
catch { }
|
|
114
|
-
if (!instruction) {
|
|
115
|
-
results.push('[WARN] Could not extract captcha instruction, cannot auto-solve');
|
|
116
|
-
return results.join('\n');
|
|
117
|
-
}
|
|
118
|
-
results.push(`Auto-solving: "${instruction}"`);
|
|
119
|
-
try {
|
|
120
|
-
const home = homedir();
|
|
121
|
-
for (const f of readdirSync(home)) {
|
|
122
|
-
if (/^\.aurix-tile-(\d+|after-\d+)\.png$/.test(f)) {
|
|
123
|
-
try {
|
|
124
|
-
unlinkSync(join(home, f));
|
|
125
|
-
}
|
|
126
|
-
catch { }
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
catch { }
|
|
131
|
-
const tiles = await findGridTiles(frame, provider);
|
|
132
|
-
const gridScreenshotPath = join(homedir(), '.aurix-captcha-grid.png');
|
|
133
|
-
try {
|
|
134
|
-
const gridEl = frame.locator('.rc-imageselect-table-33, .rc-imageselect-table-44, .task, .challenge-view, table').first();
|
|
135
|
-
if (await gridEl.count() > 0)
|
|
136
|
-
await gridEl.screenshot({ path: gridScreenshotPath });
|
|
137
|
-
else
|
|
138
|
-
await frame.locator('body').screenshot({ path: gridScreenshotPath });
|
|
139
|
-
}
|
|
140
|
-
catch {
|
|
141
|
-
try {
|
|
142
|
-
await page.screenshot({ path: gridScreenshotPath });
|
|
143
|
-
}
|
|
144
|
-
catch { }
|
|
145
|
-
}
|
|
146
|
-
const classifyPrompt = `Look at this captcha grid image. The instruction is: "${instruction}". Which tile images match this instruction? Reply with ONLY the 0-based indices separated by commas (e.g. "0,3,5"). If none match, reply "none".`;
|
|
147
|
-
let matchedIndices = [];
|
|
148
|
-
try {
|
|
149
|
-
const gridBase64 = readFileBase64(gridScreenshotPath);
|
|
150
|
-
const response = await visionClassify(gridBase64, classifyPrompt);
|
|
151
|
-
results.push(`Vision model: "${response}"`);
|
|
152
|
-
if (response.toLowerCase().includes('none')) {
|
|
153
|
-
results.push('Vision: no matching tiles, clicking verify directly');
|
|
154
|
-
}
|
|
155
|
-
else {
|
|
156
|
-
matchedIndices = response.split(',')
|
|
157
|
-
.map(s => parseInt(s.trim()))
|
|
158
|
-
.filter(n => !isNaN(n) && n >= 0 && n < tiles.length);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
catch (e) {
|
|
162
|
-
results.push(`[WARN] Vision model failed: ${e.message}`);
|
|
163
|
-
results.push('Auto-solve requires a vision-capable model. Falling back to manual mode.');
|
|
164
|
-
results.push('Use "captcha-grid" to see tiles and "click-tile" to select them manually.');
|
|
165
|
-
return results.join('\n');
|
|
166
|
-
}
|
|
167
|
-
if (matchedIndices.length === 0) {
|
|
168
|
-
results.push('No matching tiles found, attempting verify directly');
|
|
169
|
-
}
|
|
170
|
-
for (const idx of matchedIndices) {
|
|
171
|
-
try {
|
|
172
|
-
if (idx >= tiles.length)
|
|
173
|
-
continue;
|
|
174
|
-
await tiles[idx].click({ force: true, timeout: 3000 });
|
|
175
|
-
await page.waitForTimeout(200 + Math.random() * 200);
|
|
176
|
-
results.push(` Clicked tile ${idx}`);
|
|
177
|
-
}
|
|
178
|
-
catch (e) {
|
|
179
|
-
try {
|
|
180
|
-
const currentTiles = await findGridTiles(frame, provider);
|
|
181
|
-
if (idx < currentTiles.length) {
|
|
182
|
-
await currentTiles[idx].click({ force: true, timeout: 3000 });
|
|
183
|
-
await page.waitForTimeout(200 + Math.random() * 200);
|
|
184
|
-
results.push(` Clicked tile ${idx} (re-fetched)`);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
catch (e2) {
|
|
188
|
-
results.push(` Failed to click tile ${idx}: ${e2.message}`);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
if (isRecaptcha && matchedIndices.length > 0) {
|
|
193
|
-
await page.waitForTimeout(800 + Math.random() * 400);
|
|
194
|
-
}
|
|
195
|
-
results.push('Clicking verify...');
|
|
196
|
-
try {
|
|
197
|
-
let verifyBtn = frame.locator('#recaptcha-verify-button, .rc-button-submit, .button-submit, [id*="verify"]');
|
|
198
|
-
if (await verifyBtn.count() === 0) {
|
|
199
|
-
verifyBtn = frame.locator('button:has-text("Verify"), button:has-text("Next"), button:has-text("Submit")');
|
|
200
|
-
}
|
|
201
|
-
if (await verifyBtn.count() > 0) {
|
|
202
|
-
await verifyBtn.click({ force: true, timeout: 5000 });
|
|
203
|
-
await page.waitForTimeout(2000);
|
|
204
|
-
const errorText = await frame.locator('.rc-imageselect-incorrect-response, .error-message, .incorrect').count();
|
|
205
|
-
if (errorText > 0) {
|
|
206
|
-
results.push('Verification failed, challenge will retry');
|
|
207
|
-
return results.join('\n');
|
|
208
|
-
}
|
|
209
|
-
const newChallenge = await frame.locator('.rc-imageselect-instructions, .prompt-text').count();
|
|
210
|
-
if (newChallenge > 0) {
|
|
211
|
-
const newInstr = (await frame.locator('.rc-imageselect-instructions, .prompt-text').first().textContent() || '').trim();
|
|
212
|
-
if (newInstr !== instruction) {
|
|
213
|
-
results.push(`New challenge appeared: "${newInstr}"`);
|
|
214
|
-
return results.join('\n');
|
|
215
|
-
}
|
|
216
|
-
results.push('Same challenge still present');
|
|
217
|
-
return results.join('\n');
|
|
218
|
-
}
|
|
219
|
-
const verifyResultPath = join(homedir(), '.aurix-captcha-verify-result.png');
|
|
220
|
-
await page.screenshot({ path: verifyResultPath }).catch(() => { });
|
|
221
|
-
results.push(`[OK] Captcha solved! Screenshot: ${verifyResultPath}`);
|
|
222
|
-
return results.join('\n');
|
|
223
|
-
}
|
|
224
|
-
else {
|
|
225
|
-
results.push('[WARN] No verify button found');
|
|
226
|
-
return results.join('\n');
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
catch (e) {
|
|
230
|
-
results.push(`Verify failed: ${e.message}`);
|
|
231
|
-
return results.join('\n');
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
// ─── Human-Like Mouse Utilities ────────────────────────────────────────────
|
|
235
|
-
function bezierPoint(t, points) {
|
|
236
|
-
if (points.length === 1)
|
|
237
|
-
return points[0];
|
|
238
|
-
const next = [];
|
|
239
|
-
for (let i = 0; i < points.length - 1; i++) {
|
|
240
|
-
next.push([
|
|
241
|
-
points[i][0] + (points[i + 1][0] - points[i][0]) * t,
|
|
242
|
-
points[i][1] + (points[i + 1][1] - points[i][1]) * t,
|
|
243
|
-
]);
|
|
244
|
-
}
|
|
245
|
-
return bezierPoint(t, next);
|
|
246
|
-
}
|
|
247
|
-
function easeInOut(t) {
|
|
248
|
-
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
|
|
249
|
-
}
|
|
250
|
-
async function humanMove(x, y, page) {
|
|
251
|
-
const mouse = page.mouse;
|
|
252
|
-
const vp = page.viewportSize() || { width: 1280, height: 720 };
|
|
253
|
-
// Start from a random position if we don't know current pos
|
|
254
|
-
const startX = Math.random() * vp.width * 0.3;
|
|
255
|
-
const startY = Math.random() * vp.height * 0.3;
|
|
256
|
-
// Generate 2-4 control points for bezier curve
|
|
257
|
-
const numControls = 2 + Math.floor(Math.random() * 3);
|
|
258
|
-
const controlPoints = [[startX, startY]];
|
|
259
|
-
for (let i = 0; i < numControls; i++) {
|
|
260
|
-
const frac = (i + 1) / (numControls + 1);
|
|
261
|
-
const cx = startX + (x - startX) * frac + (Math.random() - 0.5) * 80;
|
|
262
|
-
const cy = startY + (y - startY) * frac + (Math.random() - 0.5) * 60;
|
|
263
|
-
controlPoints.push([cx, cy]);
|
|
264
|
-
}
|
|
265
|
-
controlPoints.push([x, y]);
|
|
266
|
-
// Step through the curve with eased timing
|
|
267
|
-
const totalSteps = 25 + Math.floor(Math.random() * 20);
|
|
268
|
-
for (let step = 0; step <= totalSteps; step++) {
|
|
269
|
-
const rawT = step / totalSteps;
|
|
270
|
-
const t = easeInOut(rawT);
|
|
271
|
-
const [px, py] = bezierPoint(t, controlPoints);
|
|
272
|
-
// Sine-wave micro-tremor (not uniform random)
|
|
273
|
-
const tremor = Math.sin(step * 0.3 + Math.random() * 0.5) * 0.4;
|
|
274
|
-
const tremorY = Math.cos(step * 0.25 + Math.random() * 0.5) * 0.3;
|
|
275
|
-
await mouse.move(px + tremor, py + tremorY);
|
|
276
|
-
// Variable step delay: faster in middle, slower at start/end
|
|
277
|
-
const speedFactor = 1 - Math.abs(rawT - 0.5) * 2;
|
|
278
|
-
const delay = 8 + Math.random() * 12 + speedFactor * 5;
|
|
279
|
-
await page.waitForTimeout(delay);
|
|
280
|
-
}
|
|
281
|
-
// Occasional overshoot + correction
|
|
282
|
-
if (Math.random() > 0.6) {
|
|
283
|
-
const overX = x + (Math.random() - 0.5) * 8;
|
|
284
|
-
const overY = y + (Math.random() - 0.5) * 8;
|
|
285
|
-
await mouse.move(overX, overY);
|
|
286
|
-
await page.waitForTimeout(30 + Math.random() * 40);
|
|
287
|
-
await mouse.move(x, y);
|
|
288
|
-
await page.waitForTimeout(20 + Math.random() * 30);
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
let lastWarmupTime = 0;
|
|
292
|
-
async function warmupBehavior(page) {
|
|
293
|
-
const now = Date.now();
|
|
294
|
-
if (now - lastWarmupTime < 30000)
|
|
295
|
-
return;
|
|
296
|
-
lastWarmupTime = now;
|
|
297
|
-
const vp = page.viewportSize() || { width: 1280, height: 720 };
|
|
298
|
-
const spots = 1 + Math.floor(Math.random() * 2);
|
|
299
|
-
for (let i = 0; i < spots; i++) {
|
|
300
|
-
const rx = Math.random() * vp.width;
|
|
301
|
-
const ry = Math.random() * vp.height;
|
|
302
|
-
await humanMove(rx, ry, page);
|
|
303
|
-
await page.waitForTimeout(150 + Math.random() * 300);
|
|
304
|
-
}
|
|
305
|
-
if (Math.random() > 0.5) {
|
|
306
|
-
const scrollDelta = Math.floor(Math.random() * 150) - 75;
|
|
307
|
-
await page.mouse.wheel(0, scrollDelta);
|
|
308
|
-
await page.waitForTimeout(200 + Math.random() * 300);
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
async function humanHold(x, y, duration, page) {
|
|
312
|
-
const mouse = page.mouse;
|
|
313
|
-
const holdSteps = Math.floor(duration / 80);
|
|
314
|
-
const breathFreq = 0.15 + Math.random() * 0.1;
|
|
315
|
-
const breathAmpX = 0.3 + Math.random() * 0.4;
|
|
316
|
-
const breathAmpY = 0.2 + Math.random() * 0.3;
|
|
317
|
-
await mouse.down();
|
|
318
|
-
for (let i = 0; i < holdSteps; i++) {
|
|
319
|
-
// Sine-wave breathing movement (natural hand tremor)
|
|
320
|
-
const breathX = Math.sin(i * breathFreq) * breathAmpX;
|
|
321
|
-
const breathY = Math.cos(i * breathFreq * 0.7) * breathAmpY;
|
|
322
|
-
// Occasional micro-adjustment
|
|
323
|
-
const adjX = Math.random() > 0.95 ? (Math.random() - 0.5) * 2 : 0;
|
|
324
|
-
const adjY = Math.random() > 0.95 ? (Math.random() - 0.5) * 2 : 0;
|
|
325
|
-
await mouse.move(x + breathX + adjX, y + breathY + adjY);
|
|
326
|
-
await page.waitForTimeout(60 + Math.random() * 40);
|
|
327
|
-
}
|
|
328
|
-
// Release with slight upward drift
|
|
329
|
-
await mouse.move(x + (Math.random() - 0.5) * 3, y - 1 - Math.random() * 2);
|
|
330
|
-
await page.waitForTimeout(30 + Math.random() * 50);
|
|
331
|
-
await mouse.up();
|
|
332
|
-
}
|
|
333
|
-
async function humanClick(locator, page) {
|
|
334
|
-
const box = await locator.first().boundingBox();
|
|
335
|
-
if (box) {
|
|
336
|
-
const clickX = box.x + box.width * (0.3 + Math.random() * 0.4);
|
|
337
|
-
const clickY = box.y + box.height * (0.3 + Math.random() * 0.4);
|
|
338
|
-
await humanMove(clickX, clickY, page);
|
|
339
|
-
await page.waitForTimeout(60 + Math.random() * 100);
|
|
340
|
-
await page.mouse.down();
|
|
341
|
-
await page.waitForTimeout(50 + Math.random() * 80);
|
|
342
|
-
await page.mouse.up();
|
|
343
|
-
}
|
|
344
|
-
else {
|
|
345
|
-
await locator.first().click({ force: true });
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
36
|
const sessions = new Map();
|
|
349
37
|
const sessionProxies = new Map();
|
|
350
38
|
const MAX_BROWSER_SESSIONS = 3;
|
|
@@ -692,283 +380,6 @@ async function resolveLocator(p, target) {
|
|
|
692
380
|
}
|
|
693
381
|
return locator;
|
|
694
382
|
}
|
|
695
|
-
async function autoSolveCaptcha(p) {
|
|
696
|
-
const results = [];
|
|
697
|
-
const frames = p.frames();
|
|
698
|
-
let recaptchaAnchor = null;
|
|
699
|
-
let recaptchaBframe = null;
|
|
700
|
-
let geetestSlider = null;
|
|
701
|
-
let turnstileFrame = null;
|
|
702
|
-
for (const frame of frames) {
|
|
703
|
-
const url = frame.url();
|
|
704
|
-
if (url.includes('/recaptcha/') && url.includes('/anchor'))
|
|
705
|
-
recaptchaAnchor = frame;
|
|
706
|
-
if (url.includes('/recaptcha/') && url.includes('/bframe'))
|
|
707
|
-
recaptchaBframe = frame;
|
|
708
|
-
if (url.includes('geetest.com') || url.includes('captcha.com')) {
|
|
709
|
-
const hasSlider = await frame.locator('.geetest_slider_button, .geetest_slider').count();
|
|
710
|
-
if (hasSlider > 0)
|
|
711
|
-
geetestSlider = frame;
|
|
712
|
-
}
|
|
713
|
-
if (url.includes('challenges.cloudflare') || url.includes('turnstile'))
|
|
714
|
-
turnstileFrame = frame;
|
|
715
|
-
}
|
|
716
|
-
if (turnstileFrame) {
|
|
717
|
-
try {
|
|
718
|
-
const checkbox = turnstileFrame.locator('input[type="checkbox"], .cf-turnstile, [role="checkbox"]').first();
|
|
719
|
-
if (await checkbox.count() > 0) {
|
|
720
|
-
await checkbox.click({ timeout: 5000 });
|
|
721
|
-
await p.waitForTimeout(3000);
|
|
722
|
-
// Don't claim "solved" — verify the widget actually reported success.
|
|
723
|
-
const tsOk = await turnstileFrame.locator('input[type="hidden"][name="cf-turnstile-response"], [data-state="success"], .success').count().catch(() => 0);
|
|
724
|
-
const tsError = await turnstileFrame.locator('.error, [data-state="error"], [data-state="failed"]').count().catch(() => 0);
|
|
725
|
-
if (tsOk > 0)
|
|
726
|
-
results.push('Turnstile: checkbox clicked, widget reports success');
|
|
727
|
-
else if (tsError > 0)
|
|
728
|
-
results.push('Turnstile: checkbox clicked but widget shows an error — may need a screenshot to inspect');
|
|
729
|
-
else
|
|
730
|
-
results.push('Turnstile: checkbox clicked, outcome unconfirmed — take a screenshot to verify the page advanced before submitting');
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
catch (e) {
|
|
734
|
-
results.push(`Turnstile: auto-click attempted (${e.message?.slice(0, 80)})`);
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
if (recaptchaAnchor && !recaptchaBframe) {
|
|
738
|
-
try {
|
|
739
|
-
const checkbox = recaptchaAnchor.locator('#recaptcha-anchor, .recaptcha-checkbox-border, .rc-anchor-checkbox').first();
|
|
740
|
-
if (await checkbox.count() > 0) {
|
|
741
|
-
await checkbox.click({ timeout: 5000 });
|
|
742
|
-
await p.waitForTimeout(2000);
|
|
743
|
-
// The checkbox click may pass instantly OR pop an image challenge.
|
|
744
|
-
// Report which actually happened instead of claiming success.
|
|
745
|
-
const checked = await recaptchaAnchor.locator('.recaptcha-checkbox-checked, .rc-anchor-checkbox-checked').count().catch(() => 0);
|
|
746
|
-
const challengeOpened = p.frames().some((f) => f.url().includes('/recaptcha/') && f.url().includes('/bframe'));
|
|
747
|
-
if (checked > 0)
|
|
748
|
-
results.push('reCAPTCHA: checkbox verified (checked) — no image challenge');
|
|
749
|
-
else if (challengeOpened)
|
|
750
|
-
results.push('reCAPTCHA: checkbox clicked, image challenge appeared — use captcha-grid to solve it');
|
|
751
|
-
else
|
|
752
|
-
results.push('reCAPTCHA: checkbox clicked, outcome unconfirmed — take a screenshot to verify before submitting');
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
catch (e) {
|
|
756
|
-
results.push(`reCAPTCHA checkbox: auto-click attempted (${e.message?.slice(0, 80)})`);
|
|
757
|
-
}
|
|
758
|
-
}
|
|
759
|
-
if (geetestSlider) {
|
|
760
|
-
try {
|
|
761
|
-
const sliderInfo = await geetestSlider.evaluate(() => {
|
|
762
|
-
const info = {};
|
|
763
|
-
const cut = document.querySelector('.geetest_cut, .geetest_piece_bg, [class*="geetest_cut"], [class*="slider_cut"]');
|
|
764
|
-
if (cut) {
|
|
765
|
-
const cutRect = cut.getBoundingClientRect();
|
|
766
|
-
const style = window.getComputedStyle(cut);
|
|
767
|
-
info.cut = { left: cutRect.left, width: cutRect.width, styleLeft: parseFloat(style.left) || null, transform: style.transform || null };
|
|
768
|
-
}
|
|
769
|
-
const bg = document.querySelector('.geetest_canvas_bg, .geetest_bg, [class*="geetest_canvas"], canvas[class*="bg"]');
|
|
770
|
-
if (bg)
|
|
771
|
-
info.bg = { left: bg.getBoundingClientRect().left, width: bg.getBoundingClientRect().width };
|
|
772
|
-
const piece = document.querySelector('.geetest_piece, [class*="slider_piece"]');
|
|
773
|
-
if (piece)
|
|
774
|
-
info.piece = { width: piece.getBoundingClientRect().width };
|
|
775
|
-
const slider = document.querySelector('.geetest_slider_button, [class*="slider_button"]');
|
|
776
|
-
if (slider) {
|
|
777
|
-
const r = slider.getBoundingClientRect();
|
|
778
|
-
info.slider = { left: r.left, width: r.width, centerX: r.left + r.width / 2, centerY: r.top + r.height / 2 };
|
|
779
|
-
}
|
|
780
|
-
return info;
|
|
781
|
-
});
|
|
782
|
-
let gapOffset = null;
|
|
783
|
-
if (sliderInfo.cut && sliderInfo.bg) {
|
|
784
|
-
if (sliderInfo.cut.styleLeft && sliderInfo.cut.styleLeft > 0)
|
|
785
|
-
gapOffset = Math.round(sliderInfo.cut.styleLeft);
|
|
786
|
-
else
|
|
787
|
-
gapOffset = Math.round(sliderInfo.cut.left - sliderInfo.bg.left);
|
|
788
|
-
}
|
|
789
|
-
if (gapOffset === null && sliderInfo.cut?.transform && sliderInfo.cut.transform !== 'none') {
|
|
790
|
-
const match = sliderInfo.cut.transform.match(/matrix\(.*?,\s*([\d.]+)/);
|
|
791
|
-
if (match)
|
|
792
|
-
gapOffset = Math.round(parseFloat(match[1]));
|
|
793
|
-
}
|
|
794
|
-
if (gapOffset !== null && sliderInfo.slider) {
|
|
795
|
-
const pieceHalf = Math.round((sliderInfo.piece?.width || 44) / 2);
|
|
796
|
-
const dragDistance = gapOffset - pieceHalf;
|
|
797
|
-
const startX = sliderInfo.slider.centerX;
|
|
798
|
-
const startY = sliderInfo.slider.centerY;
|
|
799
|
-
const endX = startX + dragDistance;
|
|
800
|
-
await p.mouse.move(startX, startY);
|
|
801
|
-
await p.waitForTimeout(150);
|
|
802
|
-
await p.mouse.down();
|
|
803
|
-
await p.waitForTimeout(200);
|
|
804
|
-
const steps = 18 + Math.floor(Math.random() * 8);
|
|
805
|
-
for (let i = 1; i <= steps; i++) {
|
|
806
|
-
const progress = i / steps;
|
|
807
|
-
const eased = progress < 0.5 ? 2 * progress * progress : 1 - Math.pow(-2 * progress + 2, 2) / 2;
|
|
808
|
-
const x = startX + dragDistance * eased + (Math.random() - 0.5) * 2;
|
|
809
|
-
const y = startY + (Math.random() - 0.5) * 2;
|
|
810
|
-
await p.mouse.move(x, y);
|
|
811
|
-
await p.waitForTimeout(10 + Math.random() * 20);
|
|
812
|
-
}
|
|
813
|
-
await p.mouse.move(endX, startY);
|
|
814
|
-
await p.waitForTimeout(150);
|
|
815
|
-
await p.mouse.up();
|
|
816
|
-
await p.waitForTimeout(2000);
|
|
817
|
-
results.push(`GeeTest: slider dragged ${dragDistance}px — outcome unconfirmed, take a screenshot to verify the gap was matched`);
|
|
818
|
-
}
|
|
819
|
-
else {
|
|
820
|
-
results.push('GeeTest slider detected but gap position could not be auto-detected');
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
catch (e) {
|
|
824
|
-
results.push(`GeeTest slider: auto-solve attempted (${e.message?.slice(0, 80)})`);
|
|
825
|
-
}
|
|
826
|
-
}
|
|
827
|
-
if (recaptchaBframe) {
|
|
828
|
-
const gridResult = await analyzeImageChallenge(p, recaptchaBframe, 'recaptcha');
|
|
829
|
-
results.push('reCAPTCHA image challenge detected — grid analysis:');
|
|
830
|
-
results.push(gridResult);
|
|
831
|
-
}
|
|
832
|
-
const funcaptchaFrame = frames.find(f => f.url().includes('funcaptcha') || f.url().includes('arkoselabs'));
|
|
833
|
-
if (funcaptchaFrame) {
|
|
834
|
-
results.push('FunCaptcha detected — screenshotting puzzle...');
|
|
835
|
-
try {
|
|
836
|
-
const fcScreenshotPath = join(homedir(), '.aurix-funcaptcha-puzzle.png');
|
|
837
|
-
await funcaptchaFrame.locator('body').screenshot({ path: fcScreenshotPath }).catch(() => p.screenshot({ path: fcScreenshotPath }));
|
|
838
|
-
results.push(`Puzzle screenshot: ${fcScreenshotPath}`);
|
|
839
|
-
results.push('Analyze the puzzle image and determine the correct answer, then use click/evaluate to solve it.');
|
|
840
|
-
}
|
|
841
|
-
catch {
|
|
842
|
-
results.push('REQUIRES_VISION: FunCaptcha detected — needs image analysis to solve');
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
return results;
|
|
846
|
-
}
|
|
847
|
-
async function findGridTiles(frame, provider) {
|
|
848
|
-
switch (provider) {
|
|
849
|
-
case 'recaptcha': {
|
|
850
|
-
const tiles33 = frame.locator('.rc-imageselect-table-33 td, .rc-image-tile-33 td');
|
|
851
|
-
if (await tiles33.count() > 0)
|
|
852
|
-
return tiles33.all();
|
|
853
|
-
const tiles44 = frame.locator('.rc-imageselect-table-44 td, .rc-image-tile-44 td');
|
|
854
|
-
if (await tiles44.count() > 0)
|
|
855
|
-
return tiles44.all();
|
|
856
|
-
const generic = frame.locator('table td');
|
|
857
|
-
if (await generic.count() > 0)
|
|
858
|
-
return generic.all();
|
|
859
|
-
return [];
|
|
860
|
-
}
|
|
861
|
-
case 'hcaptcha': {
|
|
862
|
-
const tiles = frame.locator('.task-image, .image, .task .answer');
|
|
863
|
-
if (await tiles.count() > 0)
|
|
864
|
-
return tiles.all();
|
|
865
|
-
return [];
|
|
866
|
-
}
|
|
867
|
-
case 'mtcaptcha':
|
|
868
|
-
case 'geetest': {
|
|
869
|
-
const items = frame.locator('.geetest_item_wrap, .geetest_ques_tips img, .mtcaptcha-item');
|
|
870
|
-
if (await items.count() > 0)
|
|
871
|
-
return items.all();
|
|
872
|
-
return [];
|
|
873
|
-
}
|
|
874
|
-
default: {
|
|
875
|
-
const tiles = frame.locator('.task-image, .rc-imageselect-table-33 td, .rc-imageselect-table-44 td, table td');
|
|
876
|
-
if (await tiles.count() > 0)
|
|
877
|
-
return tiles.all();
|
|
878
|
-
return [];
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
async function analyzeImageChallenge(page, frame, provider) {
|
|
883
|
-
const results = [];
|
|
884
|
-
let instruction = '';
|
|
885
|
-
try {
|
|
886
|
-
const instrEl = frame.locator('.rc-imageselect-instructions, .prompt-text, .prompt-text-h, .geetest_tip_content, .mtcaptcha-label');
|
|
887
|
-
if (await instrEl.count() > 0) {
|
|
888
|
-
instruction = (await instrEl.first().textContent()) || '';
|
|
889
|
-
instruction = instruction.trim();
|
|
890
|
-
}
|
|
891
|
-
if (!instruction) {
|
|
892
|
-
const strongText = frame.locator('strong').first();
|
|
893
|
-
if (await strongText.count() > 0) {
|
|
894
|
-
instruction = (await strongText.textContent()) || '';
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
}
|
|
898
|
-
catch { }
|
|
899
|
-
if (instruction) {
|
|
900
|
-
results.push(`Instruction: "${instruction}"`);
|
|
901
|
-
}
|
|
902
|
-
else {
|
|
903
|
-
results.push('Instruction: (could not extract — check screenshot)');
|
|
904
|
-
}
|
|
905
|
-
const tiles = await findGridTiles(frame, provider);
|
|
906
|
-
const gridSize = tiles.length <= 9 ? '3x3' : tiles.length <= 16 ? '4x4' : `${tiles.length}-tile`;
|
|
907
|
-
results.push(`Grid: ${gridSize} (${tiles.length} tiles found, valid indices: 0-${tiles.length - 1})`);
|
|
908
|
-
_lastGridAnalyzeTime = Date.now();
|
|
909
|
-
// Clear stale tile screenshots from a previous challenge so the model never
|
|
910
|
-
// reads an old .aurix-tile-N.png that no longer matches the current grid.
|
|
911
|
-
try {
|
|
912
|
-
const home = homedir();
|
|
913
|
-
for (const f of readdirSync(home)) {
|
|
914
|
-
if (/^\.aurix-tile-(\d+|after-\d+)\.png$/.test(f)) {
|
|
915
|
-
try {
|
|
916
|
-
unlinkSync(join(home, f));
|
|
917
|
-
}
|
|
918
|
-
catch { }
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
}
|
|
922
|
-
catch { }
|
|
923
|
-
const screenshotPath = join(homedir(), '.aurix-captcha-grid.png');
|
|
924
|
-
try {
|
|
925
|
-
const gridEl = frame.locator('.rc-imageselect-table-33, .rc-imageselect-table-44, .task, .challenge-view, .geetest_panel, table').first();
|
|
926
|
-
if (await gridEl.count() > 0) {
|
|
927
|
-
await gridEl.screenshot({ path: screenshotPath });
|
|
928
|
-
}
|
|
929
|
-
else {
|
|
930
|
-
await frame.locator('body').screenshot({ path: screenshotPath });
|
|
931
|
-
}
|
|
932
|
-
}
|
|
933
|
-
catch {
|
|
934
|
-
try {
|
|
935
|
-
await page.screenshot({ path: screenshotPath });
|
|
936
|
-
}
|
|
937
|
-
catch { }
|
|
938
|
-
}
|
|
939
|
-
results.push(`Grid screenshot: ${screenshotPath}`);
|
|
940
|
-
for (let i = 0; i < tiles.length; i++) {
|
|
941
|
-
const tilePath = join(homedir(), `.aurix-tile-${i}.png`);
|
|
942
|
-
try {
|
|
943
|
-
await tiles[i].screenshot({ path: tilePath });
|
|
944
|
-
results.push(` Tile ${i}: ${tilePath}`);
|
|
945
|
-
}
|
|
946
|
-
catch {
|
|
947
|
-
results.push(` Tile ${i}: (screenshot failed)`);
|
|
948
|
-
}
|
|
949
|
-
}
|
|
950
|
-
const isRecaptcha = provider === 'recaptcha';
|
|
951
|
-
const selectedClass = isRecaptcha ? '.rc-imageselect-dynamic-selected' : '.task-image.selected, .task .selected';
|
|
952
|
-
const selectedCount = await frame.locator(selectedClass).count();
|
|
953
|
-
if (selectedCount > 0) {
|
|
954
|
-
results.push(`Already selected: ${selectedCount} tile(s)`);
|
|
955
|
-
}
|
|
956
|
-
results.push('');
|
|
957
|
-
results.push('=== IMAGE SELECTION STEPS ===');
|
|
958
|
-
results.push('Read EACH tile image above to determine which ones match the instruction.');
|
|
959
|
-
results.push('Then execute these actions IN ORDER:');
|
|
960
|
-
results.push('');
|
|
961
|
-
results.push('Step 1: For each matching tile, call: browser action="click-tile" value="<index>"');
|
|
962
|
-
results.push(' Example: if tiles 0, 3, and 5 match → click-tile 0, then click-tile 3, then click-tile 5');
|
|
963
|
-
if (provider === 'recaptcha') {
|
|
964
|
-
results.push(' IMPORTANT: After clicking a tile, a NEW tile replaces it. Read the new tile screenshot to check if it also matches.');
|
|
965
|
-
}
|
|
966
|
-
results.push('Step 2: After clicking ALL matching tiles, call: browser action="captcha-verify"');
|
|
967
|
-
results.push('Step 3: If the grid refreshes with new tiles, call captcha-grid again and repeat from Step 1');
|
|
968
|
-
results.push('');
|
|
969
|
-
results.push('Do NOT skip any step. Start by reading the tile images now.');
|
|
970
|
-
return results.join('\n');
|
|
971
|
-
}
|
|
972
383
|
export const browserTool = {
|
|
973
384
|
name: 'browser',
|
|
974
385
|
description: `Persistent Chromium browser. Profile: ~/.aurix-browser-profile.
|
|
@@ -1533,7 +944,7 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
|
|
|
1533
944
|
case 'solve-captcha': {
|
|
1534
945
|
const p = await ensureBrowser();
|
|
1535
946
|
const results = [];
|
|
1536
|
-
const _solveTimeout =
|
|
947
|
+
const _solveTimeout = 120_000;
|
|
1537
948
|
const _solveLogic = async () => {
|
|
1538
949
|
const frames = p.frames();
|
|
1539
950
|
let captchaType = 'unknown';
|
|
@@ -1585,14 +996,14 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
|
|
|
1585
996
|
try {
|
|
1586
997
|
if (recaptchaBframe) {
|
|
1587
998
|
results.push('Image challenge already visible. Auto-solving...');
|
|
1588
|
-
const maxRetries =
|
|
999
|
+
const maxRetries = 5;
|
|
1589
1000
|
let solved = false;
|
|
1590
1001
|
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
1591
1002
|
if (attempt > 0)
|
|
1592
1003
|
results.push(`\nRetry attempt ${attempt}/${maxRetries - 1}...`);
|
|
1593
1004
|
const solveResult = await solveCaptchaGrid(p, recaptchaBframe, 'recaptcha');
|
|
1594
1005
|
results.push(solveResult);
|
|
1595
|
-
if (solveResult.includes('
|
|
1006
|
+
if (solveResult.includes('CAPTCHA SOLVED')) {
|
|
1596
1007
|
solved = true;
|
|
1597
1008
|
break;
|
|
1598
1009
|
}
|
|
@@ -1606,6 +1017,7 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
|
|
|
1606
1017
|
solved = true;
|
|
1607
1018
|
break;
|
|
1608
1019
|
}
|
|
1020
|
+
recaptchaBframe = newChallenge;
|
|
1609
1021
|
}
|
|
1610
1022
|
if (!solved && !results.some(r => r.includes('Falling back'))) {
|
|
1611
1023
|
results.push(`\nAuto-solve exhausted after ${maxRetries} attempts. Use "captcha-grid" and "click-tile" for manual solving.`);
|
|
@@ -1629,17 +1041,17 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
|
|
|
1629
1041
|
await humanClick(checkbox, p);
|
|
1630
1042
|
await p.waitForTimeout(3000);
|
|
1631
1043
|
const updatedFrames = p.frames();
|
|
1632
|
-
|
|
1044
|
+
let challengeFrame = updatedFrames.find(f => f.url().includes('/recaptcha/') && f.url().includes('/bframe'));
|
|
1633
1045
|
if (challengeFrame) {
|
|
1634
1046
|
results.push('Image challenge appeared. Auto-solving...');
|
|
1635
|
-
const maxRetries =
|
|
1047
|
+
const maxRetries = 5;
|
|
1636
1048
|
let solved = false;
|
|
1637
1049
|
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
1638
1050
|
if (attempt > 0)
|
|
1639
1051
|
results.push(`\nRetry attempt ${attempt}/${maxRetries - 1}...`);
|
|
1640
1052
|
const solveResult = await solveCaptchaGrid(p, challengeFrame, 'recaptcha');
|
|
1641
1053
|
results.push(solveResult);
|
|
1642
|
-
if (solveResult.includes('
|
|
1054
|
+
if (solveResult.includes('CAPTCHA SOLVED')) {
|
|
1643
1055
|
solved = true;
|
|
1644
1056
|
break;
|
|
1645
1057
|
}
|
|
@@ -1654,6 +1066,7 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
|
|
|
1654
1066
|
solved = true;
|
|
1655
1067
|
break;
|
|
1656
1068
|
}
|
|
1069
|
+
challengeFrame = newChallenge;
|
|
1657
1070
|
}
|
|
1658
1071
|
if (!solved && !results.some(r => r.includes('Falling back'))) {
|
|
1659
1072
|
results.push(`\nAuto-solve exhausted after ${maxRetries} attempts. Use "captcha-grid" and "click-tile" for manual solving.`);
|
|
@@ -1684,14 +1097,14 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
|
|
|
1684
1097
|
}
|
|
1685
1098
|
if (challengeFrame) {
|
|
1686
1099
|
results.push('Image challenge appeared after clicking anchor. Auto-solving...');
|
|
1687
|
-
const maxRetries =
|
|
1100
|
+
const maxRetries = 5;
|
|
1688
1101
|
let solved = false;
|
|
1689
1102
|
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
1690
1103
|
if (attempt > 0)
|
|
1691
1104
|
results.push(`\nRetry attempt ${attempt}/${maxRetries - 1}...`);
|
|
1692
1105
|
const solveResult = await solveCaptchaGrid(p, challengeFrame, 'recaptcha');
|
|
1693
1106
|
results.push(solveResult);
|
|
1694
|
-
if (solveResult.includes('
|
|
1107
|
+
if (solveResult.includes('CAPTCHA SOLVED')) {
|
|
1695
1108
|
solved = true;
|
|
1696
1109
|
break;
|
|
1697
1110
|
}
|
|
@@ -1705,6 +1118,7 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
|
|
|
1705
1118
|
solved = true;
|
|
1706
1119
|
break;
|
|
1707
1120
|
}
|
|
1121
|
+
challengeFrame = newChallenge;
|
|
1708
1122
|
}
|
|
1709
1123
|
if (!solved && !results.some(r => r.includes('Falling back'))) {
|
|
1710
1124
|
results.push(`\nAuto-solve exhausted after ${maxRetries} attempts. Use "captcha-grid" and "click-tile" for manual solving.`);
|
|
@@ -1744,17 +1158,17 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
|
|
|
1744
1158
|
await humanClick(checkbox, p);
|
|
1745
1159
|
await p.waitForTimeout(3000);
|
|
1746
1160
|
const updatedFrames = p.frames();
|
|
1747
|
-
|
|
1161
|
+
let challengeFrame = updatedFrames.find((f) => f.url().includes('hcaptcha') && f.url().includes('challenge'));
|
|
1748
1162
|
if (challengeFrame) {
|
|
1749
1163
|
results.push('Image challenge appeared. Auto-solving...');
|
|
1750
|
-
const maxRetries =
|
|
1164
|
+
const maxRetries = 5;
|
|
1751
1165
|
let solved = false;
|
|
1752
1166
|
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
1753
1167
|
if (attempt > 0)
|
|
1754
1168
|
results.push(`\nRetry attempt ${attempt}/${maxRetries - 1}...`);
|
|
1755
1169
|
const solveResult = await solveCaptchaGrid(p, challengeFrame, 'hcaptcha');
|
|
1756
1170
|
results.push(solveResult);
|
|
1757
|
-
if (solveResult.includes('
|
|
1171
|
+
if (solveResult.includes('CAPTCHA SOLVED')) {
|
|
1758
1172
|
solved = true;
|
|
1759
1173
|
break;
|
|
1760
1174
|
}
|
|
@@ -1769,6 +1183,7 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
|
|
|
1769
1183
|
solved = true;
|
|
1770
1184
|
break;
|
|
1771
1185
|
}
|
|
1186
|
+
challengeFrame = newChallenge;
|
|
1772
1187
|
}
|
|
1773
1188
|
if (!solved && !results.some(r => r.includes('Falling back'))) {
|
|
1774
1189
|
results.push(`\nAuto-solve exhausted after ${maxRetries} attempts. Use "captcha-grid" and "click-tile" for manual solving.`);
|
|
@@ -2163,7 +1578,7 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
|
|
|
2163
1578
|
try {
|
|
2164
1579
|
return await Promise.race([
|
|
2165
1580
|
_solveLogic(),
|
|
2166
|
-
new Promise((_, rej) => setTimeout(() => rej(new Error('solve-captcha timed out (
|
|
1581
|
+
new Promise((_, rej) => setTimeout(() => rej(new Error('solve-captcha timed out (120s)')), _solveTimeout)),
|
|
2167
1582
|
]);
|
|
2168
1583
|
}
|
|
2169
1584
|
catch (e) {
|
|
@@ -2269,27 +1684,23 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
|
|
|
2269
1684
|
results.push(`Clicking ${tileIndices.length} tile(s): [${tileIndices.join(', ')}]`);
|
|
2270
1685
|
for (const tileIndex of tileIndices) {
|
|
2271
1686
|
try {
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
results.push(` Tile ${tileIndex}: out of range (${currentTiles.length} tiles now), skipping`);
|
|
1687
|
+
if (tileIndex >= initialTiles.length) {
|
|
1688
|
+
results.push(` Tile ${tileIndex}: out of range (${initialTiles.length} tiles), skipping`);
|
|
2275
1689
|
continue;
|
|
2276
1690
|
}
|
|
2277
|
-
const tile =
|
|
1691
|
+
const tile = initialTiles[tileIndex];
|
|
2278
1692
|
const selectedBefore = await challengeFrame.locator(selectedClass).count().catch(() => 0);
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
await p.mouse.down();
|
|
2286
|
-
await p.waitForTimeout(60 + Math.random() * 100);
|
|
2287
|
-
await p.mouse.up();
|
|
1693
|
+
try {
|
|
1694
|
+
await challengeFrame.evaluate((idx) => {
|
|
1695
|
+
const tds = document.querySelectorAll('table td');
|
|
1696
|
+
if (tds[idx])
|
|
1697
|
+
tds[idx].click();
|
|
1698
|
+
}, tileIndex);
|
|
2288
1699
|
}
|
|
2289
|
-
|
|
2290
|
-
await tile.click({ force: true });
|
|
1700
|
+
catch {
|
|
1701
|
+
await tile.click({ force: true, timeout: 3000 });
|
|
2291
1702
|
}
|
|
2292
|
-
await p.waitForTimeout(
|
|
1703
|
+
await p.waitForTimeout(300 + Math.random() * 300);
|
|
2293
1704
|
const selectedCount = await challengeFrame.locator(selectedClass).count().catch(() => 0);
|
|
2294
1705
|
const clickStatus = selectedCount !== selectedBefore
|
|
2295
1706
|
? `selected (${selectedBefore} → ${selectedCount})`
|
|
@@ -2359,16 +1770,26 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
|
|
|
2359
1770
|
if (await verifyBtn.count() === 0) {
|
|
2360
1771
|
return err('No verify button found', 'Use "captcha-grid" to analyze the challenge first');
|
|
2361
1772
|
}
|
|
2362
|
-
|
|
1773
|
+
try {
|
|
1774
|
+
await challengeFrame.evaluate(() => {
|
|
1775
|
+
const btn = document.querySelector('#recaptcha-verify-button, .rc-button-submit, .button-submit, [id*="verify"]');
|
|
1776
|
+
if (btn)
|
|
1777
|
+
btn.click();
|
|
1778
|
+
});
|
|
1779
|
+
}
|
|
1780
|
+
catch {
|
|
1781
|
+
await humanClick(verifyBtn, p);
|
|
1782
|
+
}
|
|
2363
1783
|
await p.waitForTimeout(3000);
|
|
2364
1784
|
const screenshotPath = join(homedir(), '.aurix-captcha-verify-result.png');
|
|
2365
|
-
const
|
|
2366
|
-
|
|
1785
|
+
const errorEl2 = challengeFrame.locator('.rc-imageselect-incorrect-response, .error-message, .incorrect').first();
|
|
1786
|
+
const errorVisible2 = await errorEl2.count() > 0 && await errorEl2.isVisible().catch(() => false);
|
|
1787
|
+
if (errorVisible2) {
|
|
2367
1788
|
const errorMsg = await challengeFrame.locator('.rc-imageselect-incorrect-response, .error-message').first().textContent().catch(() => 'Incorrect answer');
|
|
2368
1789
|
await p.screenshot({ path: screenshotPath });
|
|
2369
1790
|
const results = [];
|
|
2370
1791
|
results.push(`Verification failed: "${errorMsg}". Auto-retrying...`);
|
|
2371
|
-
const maxRetries =
|
|
1792
|
+
const maxRetries = 3;
|
|
2372
1793
|
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
2373
1794
|
results.push(`\nRetry ${attempt + 1}/${maxRetries}...`);
|
|
2374
1795
|
await p.waitForTimeout(2000);
|
|
@@ -2386,7 +1807,7 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
|
|
|
2386
1807
|
const retryProvider = retryFrame.url().includes('hcaptcha') ? 'hcaptcha' : 'recaptcha';
|
|
2387
1808
|
const solveResult = await solveCaptchaGrid(p, retryFrame, retryProvider);
|
|
2388
1809
|
results.push(solveResult);
|
|
2389
|
-
if (solveResult.includes('
|
|
1810
|
+
if (solveResult.includes('CAPTCHA SOLVED')) {
|
|
2390
1811
|
return results.join('\n');
|
|
2391
1812
|
}
|
|
2392
1813
|
}
|
|
@@ -2399,7 +1820,7 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
|
|
|
2399
1820
|
await p.screenshot({ path: screenshotPath });
|
|
2400
1821
|
const results = [];
|
|
2401
1822
|
results.push(`New challenge appeared: "${instruction}". Auto-solving...`);
|
|
2402
|
-
const maxRetries =
|
|
1823
|
+
const maxRetries = 3;
|
|
2403
1824
|
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
2404
1825
|
if (attempt > 0)
|
|
2405
1826
|
results.push(`\nRetry ${attempt}/${maxRetries - 1}...`);
|
|
@@ -2416,7 +1837,7 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
|
|
|
2416
1837
|
const retryProvider = retryFrame.url().includes('hcaptcha') ? 'hcaptcha' : 'recaptcha';
|
|
2417
1838
|
const solveResult = await solveCaptchaGrid(p, retryFrame, retryProvider);
|
|
2418
1839
|
results.push(solveResult);
|
|
2419
|
-
if (solveResult.includes('
|
|
1840
|
+
if (solveResult.includes('CAPTCHA SOLVED'))
|
|
2420
1841
|
return results.join('\n');
|
|
2421
1842
|
await p.waitForTimeout(2000);
|
|
2422
1843
|
}
|