brave-real-browser-mcp-server 2.43.22 → 2.43.24
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/lib/cjs/module/pageController.js +23 -23
- package/lib/esm/module/pageController.mjs +23 -23
- package/package.json +2 -2
- package/packages/brave-real-blocker/package.json +2 -2
- package/packages/brave-real-launcher/package.json +2 -2
- package/packages/brave-real-playwright-core/package.json +1 -1
- package/packages/brave-real-puppeteer-core/package.json +2 -2
- package/src/mcp/handlers.js +98 -76
|
@@ -58,7 +58,7 @@ async function pageController({ browser, page, proxy, turnstile, xvfbsession, pi
|
|
|
58
58
|
url.includes('track');
|
|
59
59
|
if (isAdPopup) {
|
|
60
60
|
await newPage.close().catch(() => { });
|
|
61
|
-
console.
|
|
61
|
+
console.error('[popup-blocker] Blocked popup ad:', url.substring(0, 50));
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
}
|
|
@@ -333,7 +333,7 @@ async function pageController({ browser, page, proxy, turnstile, xvfbsession, pi
|
|
|
333
333
|
get: () => 8,
|
|
334
334
|
configurable: true
|
|
335
335
|
});
|
|
336
|
-
|
|
336
|
+
|
|
337
337
|
// Device memory should be 4, 8, or 16 GB
|
|
338
338
|
if ('deviceMemory' in navigator) {
|
|
339
339
|
Object.defineProperty(navigator, 'deviceMemory', {
|
|
@@ -341,7 +341,7 @@ async function pageController({ browser, page, proxy, turnstile, xvfbsession, pi
|
|
|
341
341
|
configurable: true
|
|
342
342
|
});
|
|
343
343
|
}
|
|
344
|
-
|
|
344
|
+
|
|
345
345
|
// ========== NOTIFICATION PERMISSION FIX ==========
|
|
346
346
|
if (typeof Notification !== 'undefined') {
|
|
347
347
|
Object.defineProperty(Notification, 'permission', {
|
|
@@ -349,11 +349,11 @@ async function pageController({ browser, page, proxy, turnstile, xvfbsession, pi
|
|
|
349
349
|
configurable: true
|
|
350
350
|
});
|
|
351
351
|
}
|
|
352
|
-
|
|
352
|
+
|
|
353
353
|
// ========== DOCUMENT FOCUS FIX ==========
|
|
354
354
|
const originalHasFocus = document.hasFocus.bind(document);
|
|
355
|
-
document.hasFocus = function() { return true; };
|
|
356
|
-
|
|
355
|
+
document.hasFocus = function () { return true; };
|
|
356
|
+
|
|
357
357
|
// ========== CONNECTION API FIX ==========
|
|
358
358
|
if (!navigator.connection) {
|
|
359
359
|
Object.defineProperty(navigator, 'connection', {
|
|
@@ -363,14 +363,14 @@ async function pageController({ browser, page, proxy, turnstile, xvfbsession, pi
|
|
|
363
363
|
effectiveType: '4g',
|
|
364
364
|
saveData: false,
|
|
365
365
|
type: 'wifi',
|
|
366
|
-
addEventListener: function() {},
|
|
367
|
-
removeEventListener: function() {},
|
|
368
|
-
dispatchEvent: function() { return true; }
|
|
366
|
+
addEventListener: function () { },
|
|
367
|
+
removeEventListener: function () { },
|
|
368
|
+
dispatchEvent: function () { return true; }
|
|
369
369
|
}),
|
|
370
370
|
configurable: true
|
|
371
371
|
});
|
|
372
372
|
}
|
|
373
|
-
|
|
373
|
+
|
|
374
374
|
// ========== PERFORMANCE MEMORY FIX ==========
|
|
375
375
|
if (window.performance && !performance.memory) {
|
|
376
376
|
Object.defineProperty(performance, 'memory', {
|
|
@@ -382,17 +382,17 @@ async function pageController({ browser, page, proxy, turnstile, xvfbsession, pi
|
|
|
382
382
|
configurable: true
|
|
383
383
|
});
|
|
384
384
|
}
|
|
385
|
-
|
|
385
|
+
|
|
386
386
|
// ========== CHROME RUNTIME FIX (Critical for CreepJS) ==========
|
|
387
|
-
(function() {
|
|
387
|
+
(function () {
|
|
388
388
|
const chromeObj = {
|
|
389
389
|
app: {
|
|
390
390
|
isInstalled: false,
|
|
391
391
|
InstallState: { DISABLED: 'disabled', INSTALLED: 'installed', NOT_INSTALLED: 'not_installed' },
|
|
392
392
|
RunningState: { CANNOT_RUN: 'cannot_run', READY_TO_RUN: 'ready_to_run', RUNNING: 'running' },
|
|
393
|
-
getDetails: function() { return null; },
|
|
394
|
-
getIsInstalled: function() { return false; },
|
|
395
|
-
runningState: function() { return 'cannot_run'; }
|
|
393
|
+
getDetails: function () { return null; },
|
|
394
|
+
getIsInstalled: function () { return false; },
|
|
395
|
+
runningState: function () { return 'cannot_run'; }
|
|
396
396
|
},
|
|
397
397
|
runtime: {
|
|
398
398
|
OnInstalledReason: { CHROME_UPDATE: 'chrome_update', INSTALL: 'install', SHARED_MODULE_UPDATE: 'shared_module_update', UPDATE: 'update' },
|
|
@@ -401,14 +401,14 @@ async function pageController({ browser, page, proxy, turnstile, xvfbsession, pi
|
|
|
401
401
|
PlatformNaclArch: { ARM: 'arm', MIPS: 'mips', MIPS64: 'mips64', X86_32: 'x86-32', X86_64: 'x86-64' },
|
|
402
402
|
PlatformOs: { ANDROID: 'android', CROS: 'cros', FUCHSIA: 'fuchsia', LINUX: 'linux', MAC: 'mac', OPENBSD: 'openbsd', WIN: 'win' },
|
|
403
403
|
RequestUpdateCheckStatus: { NO_UPDATE: 'no_update', THROTTLED: 'throttled', UPDATE_AVAILABLE: 'update_available' },
|
|
404
|
-
connect: function() { return { name: '', sender: undefined, onDisconnect: { addListener: function() {} }, onMessage: { addListener: function() {} }, postMessage: function() {}, disconnect: function() {} }; },
|
|
405
|
-
sendMessage: function() {},
|
|
404
|
+
connect: function () { return { name: '', sender: undefined, onDisconnect: { addListener: function () { } }, onMessage: { addListener: function () { } }, postMessage: function () { }, disconnect: function () { } }; },
|
|
405
|
+
sendMessage: function () { },
|
|
406
406
|
id: undefined
|
|
407
407
|
},
|
|
408
|
-
csi: function() {
|
|
408
|
+
csi: function () {
|
|
409
409
|
return { startE: Date.now(), onloadT: Date.now(), pageT: Math.floor(Math.random() * 1000) + 500, tran: 15 };
|
|
410
410
|
},
|
|
411
|
-
loadTimes: function() {
|
|
411
|
+
loadTimes: function () {
|
|
412
412
|
return {
|
|
413
413
|
requestTime: Date.now() / 1000 - Math.random() * 2,
|
|
414
414
|
startLoadTime: Date.now() / 1000 - Math.random(),
|
|
@@ -426,21 +426,21 @@ async function pageController({ browser, page, proxy, turnstile, xvfbsession, pi
|
|
|
426
426
|
};
|
|
427
427
|
}
|
|
428
428
|
};
|
|
429
|
-
|
|
429
|
+
|
|
430
430
|
const makeNative = (fn, name) => {
|
|
431
|
-
Object.defineProperty(fn, 'toString', { value: function() { return 'function ' + name + '() { [native code] }'; } });
|
|
431
|
+
Object.defineProperty(fn, 'toString', { value: function () { return 'function ' + name + '() { [native code] }'; } });
|
|
432
432
|
return fn;
|
|
433
433
|
};
|
|
434
434
|
chromeObj.csi = makeNative(chromeObj.csi, 'csi');
|
|
435
435
|
chromeObj.loadTimes = makeNative(chromeObj.loadTimes, 'loadTimes');
|
|
436
|
-
|
|
436
|
+
|
|
437
437
|
if (!window.chrome) {
|
|
438
438
|
Object.defineProperty(window, 'chrome', { value: chromeObj, writable: true, enumerable: true, configurable: true });
|
|
439
439
|
} else {
|
|
440
440
|
Object.keys(chromeObj).forEach(key => { if (!window.chrome[key]) window.chrome[key] = chromeObj[key]; });
|
|
441
441
|
}
|
|
442
442
|
})();
|
|
443
|
-
|
|
443
|
+
|
|
444
444
|
// ========== NATIVE DIALOGS FIX (MUST BE FIRST) ==========
|
|
445
445
|
// Fix alert, confirm, prompt to pass SannySoft detection
|
|
446
446
|
(function () {
|
|
@@ -58,7 +58,7 @@ export async function pageController({ browser, page, proxy, turnstile, xvfbsess
|
|
|
58
58
|
url.includes('track');
|
|
59
59
|
if (isAdPopup) {
|
|
60
60
|
await newPage.close().catch(() => { });
|
|
61
|
-
console.
|
|
61
|
+
console.error('[popup-blocker] Blocked popup ad:', url.substring(0, 50));
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
}
|
|
@@ -333,7 +333,7 @@ export async function pageController({ browser, page, proxy, turnstile, xvfbsess
|
|
|
333
333
|
get: () => 8,
|
|
334
334
|
configurable: true
|
|
335
335
|
});
|
|
336
|
-
|
|
336
|
+
|
|
337
337
|
// Device memory should be 4, 8, or 16 GB
|
|
338
338
|
if ('deviceMemory' in navigator) {
|
|
339
339
|
Object.defineProperty(navigator, 'deviceMemory', {
|
|
@@ -341,7 +341,7 @@ export async function pageController({ browser, page, proxy, turnstile, xvfbsess
|
|
|
341
341
|
configurable: true
|
|
342
342
|
});
|
|
343
343
|
}
|
|
344
|
-
|
|
344
|
+
|
|
345
345
|
// ========== NOTIFICATION PERMISSION FIX ==========
|
|
346
346
|
if (typeof Notification !== 'undefined') {
|
|
347
347
|
Object.defineProperty(Notification, 'permission', {
|
|
@@ -349,11 +349,11 @@ export async function pageController({ browser, page, proxy, turnstile, xvfbsess
|
|
|
349
349
|
configurable: true
|
|
350
350
|
});
|
|
351
351
|
}
|
|
352
|
-
|
|
352
|
+
|
|
353
353
|
// ========== DOCUMENT FOCUS FIX ==========
|
|
354
354
|
const originalHasFocus = document.hasFocus.bind(document);
|
|
355
|
-
document.hasFocus = function() { return true; };
|
|
356
|
-
|
|
355
|
+
document.hasFocus = function () { return true; };
|
|
356
|
+
|
|
357
357
|
// ========== CONNECTION API FIX ==========
|
|
358
358
|
if (!navigator.connection) {
|
|
359
359
|
Object.defineProperty(navigator, 'connection', {
|
|
@@ -363,14 +363,14 @@ export async function pageController({ browser, page, proxy, turnstile, xvfbsess
|
|
|
363
363
|
effectiveType: '4g',
|
|
364
364
|
saveData: false,
|
|
365
365
|
type: 'wifi',
|
|
366
|
-
addEventListener: function() {},
|
|
367
|
-
removeEventListener: function() {},
|
|
368
|
-
dispatchEvent: function() { return true; }
|
|
366
|
+
addEventListener: function () { },
|
|
367
|
+
removeEventListener: function () { },
|
|
368
|
+
dispatchEvent: function () { return true; }
|
|
369
369
|
}),
|
|
370
370
|
configurable: true
|
|
371
371
|
});
|
|
372
372
|
}
|
|
373
|
-
|
|
373
|
+
|
|
374
374
|
// ========== PERFORMANCE MEMORY FIX ==========
|
|
375
375
|
if (window.performance && !performance.memory) {
|
|
376
376
|
Object.defineProperty(performance, 'memory', {
|
|
@@ -382,17 +382,17 @@ export async function pageController({ browser, page, proxy, turnstile, xvfbsess
|
|
|
382
382
|
configurable: true
|
|
383
383
|
});
|
|
384
384
|
}
|
|
385
|
-
|
|
385
|
+
|
|
386
386
|
// ========== CHROME RUNTIME FIX (Critical for CreepJS) ==========
|
|
387
|
-
(function() {
|
|
387
|
+
(function () {
|
|
388
388
|
const chromeObj = {
|
|
389
389
|
app: {
|
|
390
390
|
isInstalled: false,
|
|
391
391
|
InstallState: { DISABLED: 'disabled', INSTALLED: 'installed', NOT_INSTALLED: 'not_installed' },
|
|
392
392
|
RunningState: { CANNOT_RUN: 'cannot_run', READY_TO_RUN: 'ready_to_run', RUNNING: 'running' },
|
|
393
|
-
getDetails: function() { return null; },
|
|
394
|
-
getIsInstalled: function() { return false; },
|
|
395
|
-
runningState: function() { return 'cannot_run'; }
|
|
393
|
+
getDetails: function () { return null; },
|
|
394
|
+
getIsInstalled: function () { return false; },
|
|
395
|
+
runningState: function () { return 'cannot_run'; }
|
|
396
396
|
},
|
|
397
397
|
runtime: {
|
|
398
398
|
OnInstalledReason: { CHROME_UPDATE: 'chrome_update', INSTALL: 'install', SHARED_MODULE_UPDATE: 'shared_module_update', UPDATE: 'update' },
|
|
@@ -401,14 +401,14 @@ export async function pageController({ browser, page, proxy, turnstile, xvfbsess
|
|
|
401
401
|
PlatformNaclArch: { ARM: 'arm', MIPS: 'mips', MIPS64: 'mips64', X86_32: 'x86-32', X86_64: 'x86-64' },
|
|
402
402
|
PlatformOs: { ANDROID: 'android', CROS: 'cros', FUCHSIA: 'fuchsia', LINUX: 'linux', MAC: 'mac', OPENBSD: 'openbsd', WIN: 'win' },
|
|
403
403
|
RequestUpdateCheckStatus: { NO_UPDATE: 'no_update', THROTTLED: 'throttled', UPDATE_AVAILABLE: 'update_available' },
|
|
404
|
-
connect: function() { return { name: '', sender: undefined, onDisconnect: { addListener: function() {} }, onMessage: { addListener: function() {} }, postMessage: function() {}, disconnect: function() {} }; },
|
|
405
|
-
sendMessage: function() {},
|
|
404
|
+
connect: function () { return { name: '', sender: undefined, onDisconnect: { addListener: function () { } }, onMessage: { addListener: function () { } }, postMessage: function () { }, disconnect: function () { } }; },
|
|
405
|
+
sendMessage: function () { },
|
|
406
406
|
id: undefined
|
|
407
407
|
},
|
|
408
|
-
csi: function() {
|
|
408
|
+
csi: function () {
|
|
409
409
|
return { startE: Date.now(), onloadT: Date.now(), pageT: Math.floor(Math.random() * 1000) + 500, tran: 15 };
|
|
410
410
|
},
|
|
411
|
-
loadTimes: function() {
|
|
411
|
+
loadTimes: function () {
|
|
412
412
|
return {
|
|
413
413
|
requestTime: Date.now() / 1000 - Math.random() * 2,
|
|
414
414
|
startLoadTime: Date.now() / 1000 - Math.random(),
|
|
@@ -426,21 +426,21 @@ export async function pageController({ browser, page, proxy, turnstile, xvfbsess
|
|
|
426
426
|
};
|
|
427
427
|
}
|
|
428
428
|
};
|
|
429
|
-
|
|
429
|
+
|
|
430
430
|
const makeNative = (fn, name) => {
|
|
431
|
-
Object.defineProperty(fn, 'toString', { value: function() { return 'function ' + name + '() { [native code] }'; } });
|
|
431
|
+
Object.defineProperty(fn, 'toString', { value: function () { return 'function ' + name + '() { [native code] }'; } });
|
|
432
432
|
return fn;
|
|
433
433
|
};
|
|
434
434
|
chromeObj.csi = makeNative(chromeObj.csi, 'csi');
|
|
435
435
|
chromeObj.loadTimes = makeNative(chromeObj.loadTimes, 'loadTimes');
|
|
436
|
-
|
|
436
|
+
|
|
437
437
|
if (!window.chrome) {
|
|
438
438
|
Object.defineProperty(window, 'chrome', { value: chromeObj, writable: true, enumerable: true, configurable: true });
|
|
439
439
|
} else {
|
|
440
440
|
Object.keys(chromeObj).forEach(key => { if (!window.chrome[key]) window.chrome[key] = chromeObj[key]; });
|
|
441
441
|
}
|
|
442
442
|
})();
|
|
443
|
-
|
|
443
|
+
|
|
444
444
|
// ========== NATIVE DIALOGS FIX (MUST BE FIRST) ==========
|
|
445
445
|
// Fix alert, confirm, prompt to pass SannySoft detection
|
|
446
446
|
(function () {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brave-real-browser-mcp-server",
|
|
3
|
-
"version": "2.43.
|
|
3
|
+
"version": "2.43.24",
|
|
4
4
|
"description": "MCP Server for Brave Real Browser - Puppeteer with Brave Browser, Stealth Mode, Ad Blocker, and Turnstile Auto-Solver for undetectable web automation.",
|
|
5
5
|
"main": "lib/cjs/index.js",
|
|
6
6
|
"module": "lib/esm/index.mjs",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"license": "ISC",
|
|
75
75
|
"dependencies": {
|
|
76
76
|
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
77
|
-
"brave-real-puppeteer-core": "^24.37.3-brave.
|
|
77
|
+
"brave-real-puppeteer-core": "^24.37.3-brave.8",
|
|
78
78
|
"ghost-cursor": "^1.4.2",
|
|
79
79
|
"puppeteer-extra": "^3.3.6",
|
|
80
80
|
"puppeteer-extra-plugin-stealth": "^2.11.2",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brave-real-blocker",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.25",
|
|
4
4
|
"description": "Advanced uBlock Origin management and stealth features for Brave Real Browser",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"@cliqz/adblocker-puppeteer": "^1.34.0",
|
|
57
57
|
"@ghostery/adblocker-puppeteer": "^2.14.1",
|
|
58
58
|
"adm-zip": "^0.5.10",
|
|
59
|
-
"brave-real-puppeteer-core": "^24.37.3-brave.
|
|
59
|
+
"brave-real-puppeteer-core": "^24.37.3-brave.8",
|
|
60
60
|
"cross-fetch": "^4.1.0",
|
|
61
61
|
"fs-extra": "^11.3.3",
|
|
62
62
|
"got": "^13.0.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brave-real-launcher",
|
|
3
|
-
"version": "1.25.
|
|
3
|
+
"version": "1.25.24",
|
|
4
4
|
"description": "Launch Brave Browser with ease from node. Based on chrome-launcher with Brave-specific support.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"typescript": "^5.0.0"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"brave-real-blocker": "^1.19.
|
|
57
|
+
"brave-real-blocker": "^1.19.25",
|
|
58
58
|
"escape-string-regexp": "^5.0.0",
|
|
59
59
|
"is-wsl": "^3.1.1",
|
|
60
60
|
"which": "^6.0.1"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brave-real-puppeteer-core",
|
|
3
|
-
"version": "24.37.3-brave.
|
|
3
|
+
"version": "24.37.3-brave.8",
|
|
4
4
|
"description": "🦁 Brave Real-World Optimized Puppeteer & Playwright Core with 1-5ms ultra-fast timing, 50+ professional stealth features, intelligent browser auto-detection, and 100% bot detection bypass. Features cross-platform Brave browser integration, comprehensive anti-detection, and breakthrough performance improvements.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"automation",
|
|
@@ -135,7 +135,7 @@
|
|
|
135
135
|
},
|
|
136
136
|
"dependencies": {
|
|
137
137
|
"@puppeteer/browsers": "2.12.1",
|
|
138
|
-
"brave-real-launcher": "^1.25.
|
|
138
|
+
"brave-real-launcher": "^1.25.24",
|
|
139
139
|
"chromium-bidi": "14.0.0",
|
|
140
140
|
"debug": "^4.4.3",
|
|
141
141
|
"devtools-protocol": "0.0.1566079",
|
package/src/mcp/handlers.js
CHANGED
|
@@ -17,6 +17,7 @@ const ocr = require('../../lib/ocr-captcha-solver');
|
|
|
17
17
|
let browserInstance = null;
|
|
18
18
|
let pageInstance = null;
|
|
19
19
|
let blockerInstance = null;
|
|
20
|
+
let setupPageFn = null; // CDP early injection function
|
|
20
21
|
let networkRecords = [];
|
|
21
22
|
let isRecordingNetwork = false;
|
|
22
23
|
let progressTasks = {};
|
|
@@ -249,14 +250,14 @@ const handlers = {
|
|
|
249
250
|
// Selectors for common modal close buttons
|
|
250
251
|
const closeSelectors = [
|
|
251
252
|
// Bootstrap/Standard Modals
|
|
252
|
-
'.modal.show .btn-close',
|
|
253
|
-
'.modal.show .close',
|
|
253
|
+
'.modal.show .btn-close',
|
|
254
|
+
'.modal.show .close',
|
|
254
255
|
'.modal.in .close',
|
|
255
256
|
'.modal-footer .btn-primary', // "OK" button usually
|
|
256
257
|
'.modal-footer .btn-secondary', // "Close" button
|
|
257
258
|
// Custom Overlays
|
|
258
|
-
'#modal-close',
|
|
259
|
-
'.popup-close',
|
|
259
|
+
'#modal-close',
|
|
260
|
+
'.popup-close',
|
|
260
261
|
'.overlay-close',
|
|
261
262
|
// Generic "X" buttons in overlays
|
|
262
263
|
'div[role="dialog"] button[aria-label="Close"]',
|
|
@@ -563,6 +564,7 @@ const handlers = {
|
|
|
563
564
|
browserInstance = result.browser;
|
|
564
565
|
pageInstance = result.page;
|
|
565
566
|
blockerInstance = result.blocker;
|
|
567
|
+
setupPageFn = result.setupPage; // Store CDP early injection function
|
|
566
568
|
|
|
567
569
|
// ═══════════════════════════════════════════════════════════════
|
|
568
570
|
// GLOBAL DIALOG HANDLER - Auto-handle dialogs
|
|
@@ -571,19 +573,19 @@ const handlers = {
|
|
|
571
573
|
pageInstance.on('dialog', async (dialog) => {
|
|
572
574
|
const dialogType = dialog.type();
|
|
573
575
|
const msg = dialog.message().toLowerCase();
|
|
574
|
-
|
|
575
|
-
notifyProgress('browser_init', 'progress',
|
|
576
|
+
|
|
577
|
+
notifyProgress('browser_init', 'progress',
|
|
576
578
|
`🔔 Handling dialog: ${dialogType} - ${dialog.message().substring(0, 100)}...`);
|
|
577
|
-
|
|
579
|
+
|
|
578
580
|
try {
|
|
579
581
|
// Critical Fix: BLOCK redirects to external sites (e.g., eCommittee)
|
|
580
582
|
// These redirects take the user away from the search page
|
|
581
583
|
if (msg.includes('redirect') || msg.includes('external') || msg.includes('leaving')) {
|
|
582
|
-
|
|
583
|
-
|
|
584
|
+
console.error('🚫 Blocking redirect dialog (Dismiss)');
|
|
585
|
+
await dialog.dismiss(); // Simulate clicking 'Cancel'
|
|
584
586
|
} else {
|
|
585
|
-
|
|
586
|
-
|
|
587
|
+
// Auto-accept other dialogs (like alerts or simple confirmations)
|
|
588
|
+
await dialog.accept(); // Simulate clicking 'OK'
|
|
587
589
|
}
|
|
588
590
|
} catch (e) {
|
|
589
591
|
// Ignore errors (dialog might be closed by injected script)
|
|
@@ -598,7 +600,7 @@ const handlers = {
|
|
|
598
600
|
await pageInstance.evaluateOnNewDocument(() => {
|
|
599
601
|
window.originalConfirm = window.confirm;
|
|
600
602
|
window.originalAlert = window.alert;
|
|
601
|
-
|
|
603
|
+
|
|
602
604
|
// Smart Confirm Handler
|
|
603
605
|
window.confirm = (msg) => {
|
|
604
606
|
console.log('Intercepted Confirm Dialog:', msg);
|
|
@@ -608,13 +610,13 @@ const handlers = {
|
|
|
608
610
|
}
|
|
609
611
|
return true; // Return TRUE = Click OK
|
|
610
612
|
};
|
|
611
|
-
|
|
613
|
+
|
|
612
614
|
// Silently ignore alerts (always OK)
|
|
613
615
|
window.alert = (msg) => {
|
|
614
616
|
console.log('Blocked Alert Dialog:', msg);
|
|
615
617
|
return true;
|
|
616
618
|
};
|
|
617
|
-
|
|
619
|
+
|
|
618
620
|
// Silently return null for prompts
|
|
619
621
|
window.prompt = (msg) => {
|
|
620
622
|
console.log('Blocked Prompt Dialog:', msg);
|
|
@@ -646,6 +648,24 @@ const handlers = {
|
|
|
646
648
|
|
|
647
649
|
notifyProgress('navigate', 'started', `Navigating to: ${url}`);
|
|
648
650
|
|
|
651
|
+
// ═══════════════════════════════════════════════════════════════
|
|
652
|
+
// CDP EARLY INJECTION - Setup BEFORE navigation for better ad blocking
|
|
653
|
+
// This ensures CSS and scripts are injected before page scripts run
|
|
654
|
+
// ═══════════════════════════════════════════════════════════════
|
|
655
|
+
console.error('[Navigate] setupPageFn available:', !!setupPageFn);
|
|
656
|
+
if (setupPageFn) {
|
|
657
|
+
try {
|
|
658
|
+
await setupPageFn(page);
|
|
659
|
+
notifyProgress('navigate', 'progress', 'CDP early injection setup complete');
|
|
660
|
+
console.error('[Navigate] CDP early injection SUCCESS');
|
|
661
|
+
} catch (e) {
|
|
662
|
+
// Non-critical error, continue navigation
|
|
663
|
+
console.error('[Navigate] CDP early injection failed:', e.message);
|
|
664
|
+
}
|
|
665
|
+
} else {
|
|
666
|
+
console.error('[Navigate] No setupPageFn available - CDP early injection skipped');
|
|
667
|
+
}
|
|
668
|
+
|
|
649
669
|
let lastError = null;
|
|
650
670
|
|
|
651
671
|
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
@@ -796,11 +816,11 @@ const handlers = {
|
|
|
796
816
|
// 5. Click (ENHANCED: iframe + hover + auto video player detection)
|
|
797
817
|
async click(params) {
|
|
798
818
|
const { page } = requireBrowser();
|
|
799
|
-
const {
|
|
800
|
-
selector,
|
|
801
|
-
humanLike = true,
|
|
802
|
-
clickCount = 1,
|
|
803
|
-
delay = 0,
|
|
819
|
+
const {
|
|
820
|
+
selector,
|
|
821
|
+
humanLike = true,
|
|
822
|
+
clickCount = 1,
|
|
823
|
+
delay = 0,
|
|
804
824
|
autoAcceptDialogs = true,
|
|
805
825
|
retries = 3,
|
|
806
826
|
timeout = 60000,
|
|
@@ -834,17 +854,17 @@ const handlers = {
|
|
|
834
854
|
// ═══════════════════════════════════════════════════════════════
|
|
835
855
|
if (autoDetectPlayer) {
|
|
836
856
|
notifyProgress('click', 'progress', '🔍 Scanning all iframes for video players...');
|
|
837
|
-
|
|
857
|
+
|
|
838
858
|
const frames = page.frames();
|
|
839
|
-
|
|
859
|
+
|
|
840
860
|
for (let i = 0; i < frames.length; i++) {
|
|
841
861
|
try {
|
|
842
862
|
const frame = frames[i];
|
|
843
863
|
const frameUrl = frame.url();
|
|
844
|
-
|
|
864
|
+
|
|
845
865
|
// Skip blank frames
|
|
846
866
|
if (frameUrl === 'about:blank' || !frameUrl) continue;
|
|
847
|
-
|
|
867
|
+
|
|
848
868
|
// Detect player in this frame
|
|
849
869
|
const playerInfo = await frame.evaluate(() => {
|
|
850
870
|
const result = {
|
|
@@ -855,7 +875,7 @@ const handlers = {
|
|
|
855
875
|
controls: [],
|
|
856
876
|
downloadButton: null
|
|
857
877
|
};
|
|
858
|
-
|
|
878
|
+
|
|
859
879
|
// Check for video element
|
|
860
880
|
const video = document.querySelector('video');
|
|
861
881
|
if (video) {
|
|
@@ -867,7 +887,7 @@ const handlers = {
|
|
|
867
887
|
readyState: video.readyState
|
|
868
888
|
};
|
|
869
889
|
}
|
|
870
|
-
|
|
890
|
+
|
|
871
891
|
// 1. JWPlayer Detection
|
|
872
892
|
if (window.jwplayer && typeof window.jwplayer === 'function') {
|
|
873
893
|
try {
|
|
@@ -877,49 +897,49 @@ const handlers = {
|
|
|
877
897
|
result.playerType = 'jwplayer';
|
|
878
898
|
result.playerState = jw.getState();
|
|
879
899
|
result.controls.push('.jw-icon-display', '.jw-icon-playback', '[aria-label="Play"]');
|
|
880
|
-
|
|
900
|
+
|
|
881
901
|
// Find download button in JWPlayer
|
|
882
902
|
const dlBtn = document.querySelector('[aria-label="Download"], .jw-icon-download, [class*="download"]');
|
|
883
903
|
if (dlBtn) result.downloadButton = '[aria-label="Download"]';
|
|
884
904
|
}
|
|
885
|
-
} catch (e) {}
|
|
905
|
+
} catch (e) { }
|
|
886
906
|
}
|
|
887
|
-
|
|
907
|
+
|
|
888
908
|
// 2. VideoJS Detection
|
|
889
909
|
if (window.videojs || document.querySelector('.video-js')) {
|
|
890
910
|
result.hasPlayer = true;
|
|
891
911
|
result.playerType = result.playerType || 'videojs';
|
|
892
912
|
result.controls.push('.vjs-big-play-button', '.vjs-play-control');
|
|
893
913
|
}
|
|
894
|
-
|
|
914
|
+
|
|
895
915
|
// 3. Plyr Detection
|
|
896
916
|
if (window.Plyr || document.querySelector('.plyr')) {
|
|
897
917
|
result.hasPlayer = true;
|
|
898
918
|
result.playerType = result.playerType || 'plyr';
|
|
899
919
|
result.controls.push('.plyr__control--play', '[data-plyr="play"]');
|
|
900
920
|
}
|
|
901
|
-
|
|
921
|
+
|
|
902
922
|
// 4. VidStack Detection
|
|
903
923
|
if (window.VidStack || document.querySelector('media-player')) {
|
|
904
924
|
result.hasPlayer = true;
|
|
905
925
|
result.playerType = result.playerType || 'vidstack';
|
|
906
926
|
result.controls.push('media-play-button', '[data-media-play]');
|
|
907
927
|
}
|
|
908
|
-
|
|
928
|
+
|
|
909
929
|
// 5. DooPlayer Detection
|
|
910
930
|
if (window.DooPlay || document.querySelector('#dooplay') || document.querySelector('.dooplay')) {
|
|
911
931
|
result.hasPlayer = true;
|
|
912
932
|
result.playerType = result.playerType || 'dooplayer';
|
|
913
933
|
result.controls.push('.play-btn', '.dooplay-play');
|
|
914
934
|
}
|
|
915
|
-
|
|
935
|
+
|
|
916
936
|
// 6. Generic HTML5 Video
|
|
917
937
|
if (result.hasVideo && !result.hasPlayer) {
|
|
918
938
|
result.hasPlayer = true;
|
|
919
939
|
result.playerType = 'html5';
|
|
920
940
|
result.controls.push('video');
|
|
921
941
|
}
|
|
922
|
-
|
|
942
|
+
|
|
923
943
|
// Find any download button
|
|
924
944
|
if (!result.downloadButton) {
|
|
925
945
|
const dlSelectors = [
|
|
@@ -934,14 +954,14 @@ const handlers = {
|
|
|
934
954
|
}
|
|
935
955
|
}
|
|
936
956
|
}
|
|
937
|
-
|
|
957
|
+
|
|
938
958
|
return result;
|
|
939
959
|
}).catch(() => ({ hasPlayer: false }));
|
|
940
|
-
|
|
960
|
+
|
|
941
961
|
if (playerInfo.hasPlayer) {
|
|
942
962
|
context = frame;
|
|
943
|
-
frameInfo = {
|
|
944
|
-
index: i,
|
|
963
|
+
frameInfo = {
|
|
964
|
+
index: i,
|
|
945
965
|
url: frameUrl,
|
|
946
966
|
autoDetected: true
|
|
947
967
|
};
|
|
@@ -951,8 +971,8 @@ const handlers = {
|
|
|
951
971
|
controls: playerInfo.controls,
|
|
952
972
|
downloadButton: playerInfo.downloadButton
|
|
953
973
|
};
|
|
954
|
-
|
|
955
|
-
notifyProgress('click', 'progress',
|
|
974
|
+
|
|
975
|
+
notifyProgress('click', 'progress',
|
|
956
976
|
`✅ Found ${playerInfo.playerType.toUpperCase()} in iframe ${i}: ${frameUrl.substring(0, 50)}...`);
|
|
957
977
|
break;
|
|
958
978
|
}
|
|
@@ -961,7 +981,7 @@ const handlers = {
|
|
|
961
981
|
continue;
|
|
962
982
|
}
|
|
963
983
|
}
|
|
964
|
-
|
|
984
|
+
|
|
965
985
|
if (!detectedPlayer) {
|
|
966
986
|
notifyProgress('click', 'progress', '⚠️ No video player found in any iframe, using main page');
|
|
967
987
|
}
|
|
@@ -971,7 +991,7 @@ const handlers = {
|
|
|
971
991
|
if (!autoDetectPlayer && (iframe !== undefined || iframeSelector)) {
|
|
972
992
|
try {
|
|
973
993
|
const frames = page.frames();
|
|
974
|
-
|
|
994
|
+
|
|
975
995
|
if (iframe !== undefined && frames[iframe]) {
|
|
976
996
|
context = frames[iframe];
|
|
977
997
|
frameInfo = { index: iframe, url: frames[iframe].url() };
|
|
@@ -1020,10 +1040,10 @@ const handlers = {
|
|
|
1020
1040
|
// ═══════════════════════════════════════════════════════════════
|
|
1021
1041
|
if (usePlayerAPI && detectedPlayer && (selector === 'video' || selector.includes('play') || selector.includes('Play'))) {
|
|
1022
1042
|
notifyProgress('click', 'progress', `🎬 Using ${detectedPlayer.type} API for playback...`);
|
|
1023
|
-
|
|
1043
|
+
|
|
1024
1044
|
playerResult = await context.evaluate((playerType) => {
|
|
1025
1045
|
const result = { success: false, method: null, state: null };
|
|
1026
|
-
|
|
1046
|
+
|
|
1027
1047
|
try {
|
|
1028
1048
|
if (playerType === 'jwplayer' && window.jwplayer) {
|
|
1029
1049
|
const jw = window.jwplayer();
|
|
@@ -1059,20 +1079,20 @@ const handlers = {
|
|
|
1059
1079
|
} catch (e) {
|
|
1060
1080
|
result.error = e.message;
|
|
1061
1081
|
}
|
|
1062
|
-
|
|
1082
|
+
|
|
1063
1083
|
return result;
|
|
1064
1084
|
}, detectedPlayer.type).catch(e => ({ success: false, error: e.message }));
|
|
1065
|
-
|
|
1085
|
+
|
|
1066
1086
|
if (playerResult.success) {
|
|
1067
1087
|
notifyProgress('click', 'progress', `✅ ${playerResult.method} executed`);
|
|
1068
|
-
|
|
1088
|
+
|
|
1069
1089
|
// Wait for play if requested
|
|
1070
1090
|
if (waitForPlay) {
|
|
1071
1091
|
notifyProgress('click', 'progress', '⏳ Waiting for video to start playing...');
|
|
1072
|
-
|
|
1092
|
+
|
|
1073
1093
|
const startTime = Date.now();
|
|
1074
1094
|
let isPlaying = false;
|
|
1075
|
-
|
|
1095
|
+
|
|
1076
1096
|
while (Date.now() - startTime < playerTimeout) {
|
|
1077
1097
|
const state = await context.evaluate(() => {
|
|
1078
1098
|
const video = document.querySelector('video');
|
|
@@ -1089,21 +1109,21 @@ const handlers = {
|
|
|
1089
1109
|
}
|
|
1090
1110
|
return { playing: false };
|
|
1091
1111
|
}).catch(() => ({ playing: false }));
|
|
1092
|
-
|
|
1112
|
+
|
|
1093
1113
|
if (state.playing || state.currentTime > 0) {
|
|
1094
1114
|
isPlaying = true;
|
|
1095
1115
|
notifyProgress('click', 'progress', `▶️ Video is now playing (${state.currentTime?.toFixed(1) || 0}s)`);
|
|
1096
1116
|
break;
|
|
1097
1117
|
}
|
|
1098
|
-
|
|
1118
|
+
|
|
1099
1119
|
await new Promise(r => setTimeout(r, 500));
|
|
1100
1120
|
}
|
|
1101
|
-
|
|
1121
|
+
|
|
1102
1122
|
if (!isPlaying) {
|
|
1103
1123
|
notifyProgress('click', 'progress', '⚠️ Video may still be buffering');
|
|
1104
1124
|
}
|
|
1105
1125
|
}
|
|
1106
|
-
|
|
1126
|
+
|
|
1107
1127
|
notifyProgress('click', 'completed', `Video playback started via ${playerResult.method}`, {
|
|
1108
1128
|
selector,
|
|
1109
1129
|
clicked: true,
|
|
@@ -1112,7 +1132,7 @@ const handlers = {
|
|
|
1112
1132
|
iframe: frameInfo,
|
|
1113
1133
|
playerResult
|
|
1114
1134
|
});
|
|
1115
|
-
|
|
1135
|
+
|
|
1116
1136
|
return {
|
|
1117
1137
|
success: true,
|
|
1118
1138
|
selector,
|
|
@@ -1153,7 +1173,7 @@ const handlers = {
|
|
|
1153
1173
|
// HOVER functionality (for video player dynamic controls)
|
|
1154
1174
|
if (hoverFirst || hoverOnly) {
|
|
1155
1175
|
notifyProgress('click', 'progress', `Hovering over ${selector}...`);
|
|
1156
|
-
|
|
1176
|
+
|
|
1157
1177
|
try {
|
|
1158
1178
|
await context.hover(selector);
|
|
1159
1179
|
notifyProgress('click', 'progress', `Hover successful, waiting ${hoverDuration}ms for controls...`);
|
|
@@ -1169,7 +1189,7 @@ const handlers = {
|
|
|
1169
1189
|
}
|
|
1170
1190
|
}
|
|
1171
1191
|
}
|
|
1172
|
-
|
|
1192
|
+
|
|
1173
1193
|
if (hoverOnly) {
|
|
1174
1194
|
notifyProgress('click', 'completed', `Hover completed: ${selector}`, { selector, hovered: true, iframe: frameInfo });
|
|
1175
1195
|
return { success: true, selector, hovered: true, clicked: false, iframe: frameInfo, detectedPlayer };
|
|
@@ -1187,7 +1207,7 @@ const handlers = {
|
|
|
1187
1207
|
try {
|
|
1188
1208
|
const { createCursor } = require('ghost-cursor');
|
|
1189
1209
|
const cursor = createCursor(page);
|
|
1190
|
-
|
|
1210
|
+
|
|
1191
1211
|
if (context !== page) {
|
|
1192
1212
|
const element = await context.$(selector);
|
|
1193
1213
|
if (element) {
|
|
@@ -1210,19 +1230,19 @@ const handlers = {
|
|
|
1210
1230
|
|
|
1211
1231
|
await new Promise(r => setTimeout(r, 300));
|
|
1212
1232
|
|
|
1213
|
-
notifyProgress('click', 'completed',
|
|
1214
|
-
`${hoverFirst ? 'Hovered+' : ''}Clicked: ${selector}${dialogHandled ? ' (dialog auto-accepted)' : ''}`,
|
|
1233
|
+
notifyProgress('click', 'completed',
|
|
1234
|
+
`${hoverFirst ? 'Hovered+' : ''}Clicked: ${selector}${dialogHandled ? ' (dialog auto-accepted)' : ''}`,
|
|
1215
1235
|
{ selector, humanLike, dialogHandled, iframe: frameInfo, detectedPlayer, attempts: attempt }
|
|
1216
1236
|
);
|
|
1217
1237
|
|
|
1218
|
-
return {
|
|
1219
|
-
success: true,
|
|
1220
|
-
selector,
|
|
1221
|
-
clicked: true,
|
|
1222
|
-
dialogHandled,
|
|
1223
|
-
iframe: frameInfo,
|
|
1238
|
+
return {
|
|
1239
|
+
success: true,
|
|
1240
|
+
selector,
|
|
1241
|
+
clicked: true,
|
|
1242
|
+
dialogHandled,
|
|
1243
|
+
iframe: frameInfo,
|
|
1224
1244
|
detectedPlayer,
|
|
1225
|
-
attempts: attempt
|
|
1245
|
+
attempts: attempt
|
|
1226
1246
|
};
|
|
1227
1247
|
|
|
1228
1248
|
} catch (attemptError) {
|
|
@@ -1246,10 +1266,10 @@ const handlers = {
|
|
|
1246
1266
|
// 6. Type (ENHANCED: iframe support)
|
|
1247
1267
|
async type(params) {
|
|
1248
1268
|
const { page } = requireBrowser();
|
|
1249
|
-
const {
|
|
1250
|
-
selector,
|
|
1251
|
-
text,
|
|
1252
|
-
delay = 50,
|
|
1269
|
+
const {
|
|
1270
|
+
selector,
|
|
1271
|
+
text,
|
|
1272
|
+
delay = 50,
|
|
1253
1273
|
clear = false,
|
|
1254
1274
|
// NEW: iframe support
|
|
1255
1275
|
iframe,
|
|
@@ -1268,7 +1288,7 @@ const handlers = {
|
|
|
1268
1288
|
if (iframe !== undefined || iframeSelector) {
|
|
1269
1289
|
try {
|
|
1270
1290
|
const frames = page.frames();
|
|
1271
|
-
|
|
1291
|
+
|
|
1272
1292
|
if (iframe !== undefined && frames[iframe]) {
|
|
1273
1293
|
context = frames[iframe];
|
|
1274
1294
|
frameInfo = { index: iframe, url: frames[iframe].url() };
|
|
@@ -1345,6 +1365,7 @@ const handlers = {
|
|
|
1345
1365
|
browserInstance = null;
|
|
1346
1366
|
pageInstance = null;
|
|
1347
1367
|
blockerInstance = null;
|
|
1368
|
+
setupPageFn = null;
|
|
1348
1369
|
}
|
|
1349
1370
|
|
|
1350
1371
|
notifyProgress('browser_close', 'completed', 'Browser closed');
|
|
@@ -2752,8 +2773,8 @@ const handlers = {
|
|
|
2752
2773
|
// 26. Execute JS (ENHANCED: iframe context support - FIXED)
|
|
2753
2774
|
async execute_js(params) {
|
|
2754
2775
|
const { page } = requireBrowser();
|
|
2755
|
-
const {
|
|
2756
|
-
code,
|
|
2776
|
+
const {
|
|
2777
|
+
code,
|
|
2757
2778
|
returnValue = true,
|
|
2758
2779
|
// NEW: iframe support (FIXED)
|
|
2759
2780
|
iframe,
|
|
@@ -2771,7 +2792,7 @@ const handlers = {
|
|
|
2771
2792
|
if (iframe !== undefined || iframeSelector) {
|
|
2772
2793
|
try {
|
|
2773
2794
|
const frames = page.frames();
|
|
2774
|
-
|
|
2795
|
+
|
|
2775
2796
|
if (iframe !== undefined) {
|
|
2776
2797
|
// iframe index provided
|
|
2777
2798
|
if (iframe === 0) {
|
|
@@ -2820,9 +2841,9 @@ const handlers = {
|
|
|
2820
2841
|
// Execute the code in the correct context
|
|
2821
2842
|
const result = await context.evaluate(code);
|
|
2822
2843
|
|
|
2823
|
-
notifyProgress('execute_js', 'completed', 'JavaScript executed', {
|
|
2824
|
-
hasResult: result !== undefined,
|
|
2825
|
-
iframe: frameInfo
|
|
2844
|
+
notifyProgress('execute_js', 'completed', 'JavaScript executed', {
|
|
2845
|
+
hasResult: result !== undefined,
|
|
2846
|
+
iframe: frameInfo
|
|
2826
2847
|
});
|
|
2827
2848
|
|
|
2828
2849
|
return { success: true, result: returnValue ? result : undefined, iframe: frameInfo };
|
|
@@ -4227,6 +4248,7 @@ async function cleanup() {
|
|
|
4227
4248
|
browserInstance = null;
|
|
4228
4249
|
pageInstance = null;
|
|
4229
4250
|
blockerInstance = null;
|
|
4251
|
+
setupPageFn = null;
|
|
4230
4252
|
}
|
|
4231
4253
|
}
|
|
4232
4254
|
|