@fanboynz/network-scanner 1.0.59 → 1.0.61
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/cloudflare.js +39 -50
- package/lib/flowproxy.js +42 -24
- package/lib/interaction.js +16 -10
- package/nwss.js +72 -46
- package/package.json +2 -2
package/lib/cloudflare.js
CHANGED
|
@@ -11,36 +11,40 @@ const CLOUDFLARE_MODULE_VERSION = '2.1.0';
|
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Timeout constants for various operations (in milliseconds)
|
|
14
|
+
* Optimized timeout constants for Puppeteer 22.x performance (in milliseconds)
|
|
15
|
+
* All values tuned for maximum scanning speed while maintaining functionality
|
|
14
16
|
*/
|
|
15
17
|
const TIMEOUTS = {
|
|
16
|
-
QUICK_DETECTION: 3000, // Quick Cloudflare detection check
|
|
17
18
|
PAGE_EVALUATION: 8000, // Standard page evaluation timeout
|
|
18
19
|
PAGE_EVALUATION_SAFE: 10000, // Safe page evaluation with extra buffer
|
|
19
|
-
CHALLENGE_COMPLETION: 3000, // Challenge completion check
|
|
20
|
-
PHISHING_WAIT: 2000, // Wait before checking phishing warning
|
|
21
20
|
PHISHING_CLICK: 3000, // Timeout for clicking phishing continue button
|
|
22
21
|
PHISHING_NAVIGATION: 8000, // Wait for navigation after phishing bypass
|
|
23
|
-
CHALLENGE_WAIT: 1000, // Wait before checking verification challenge
|
|
24
|
-
CHALLENGE_SOLVING: 20000, // Overall challenge solving timeout
|
|
25
|
-
JS_CHALLENGE: 15000, // JS challenge completion wait
|
|
26
22
|
JS_CHALLENGE_BUFFER: 18000, // JS challenge with safety buffer
|
|
27
|
-
TURNSTILE_OPERATION: 8000, // Turnstile iframe operations
|
|
28
23
|
TURNSTILE_COMPLETION: 12000, // Turnstile completion check
|
|
29
24
|
TURNSTILE_COMPLETION_BUFFER: 15000, // Turnstile completion with buffer
|
|
30
|
-
SELECTOR_WAIT: 2000, // Wait for selector to appear
|
|
31
|
-
SELECTOR_WAIT_BUFFER: 2500, // Selector wait with safety buffer
|
|
32
|
-
ELEMENT_INTERACTION_DELAY: 500, // Delay before element interactions
|
|
33
25
|
CLICK_TIMEOUT: 5000, // Standard click operation timeout
|
|
34
26
|
CLICK_TIMEOUT_BUFFER: 1000, // Click timeout safety buffer
|
|
35
27
|
NAVIGATION_TIMEOUT: 15000, // Standard navigation timeout
|
|
36
28
|
NAVIGATION_TIMEOUT_BUFFER: 2000, // Navigation timeout safety buffer
|
|
37
|
-
FALLBACK_TIMEOUT: 5000, // Fallback timeout for failed operations
|
|
38
29
|
ADAPTIVE_TIMEOUT_WITH_INDICATORS: 25000, // Adaptive timeout when indicators found + explicit config
|
|
39
30
|
ADAPTIVE_TIMEOUT_WITHOUT_INDICATORS: 20000, // Adaptive timeout with explicit config only
|
|
40
31
|
ADAPTIVE_TIMEOUT_AUTO_WITH_INDICATORS: 15000, // Adaptive timeout for auto-detected with indicators
|
|
41
32
|
ADAPTIVE_TIMEOUT_AUTO_WITHOUT_INDICATORS: 10000 // Adaptive timeout for auto-detected without indicators
|
|
42
33
|
};
|
|
43
34
|
|
|
35
|
+
// Fast timeout constants - optimized for speed
|
|
36
|
+
const FAST_TIMEOUTS = {
|
|
37
|
+
QUICK_DETECTION: 2000, // Fast Cloudflare detection
|
|
38
|
+
PHISHING_WAIT: 1000, // Fast phishing check
|
|
39
|
+
CHALLENGE_WAIT: 500, // Fast challenge detection
|
|
40
|
+
ELEMENT_INTERACTION_DELAY: 250, // Fast element interactions
|
|
41
|
+
SELECTOR_WAIT: 1500, // Fast selector waits
|
|
42
|
+
TURNSTILE_OPERATION: 6000, // Fast Turnstile operations
|
|
43
|
+
JS_CHALLENGE: 12000, // Fast JS challenge completion
|
|
44
|
+
CHALLENGE_SOLVING: 15000, // Fast overall challenge solving
|
|
45
|
+
CHALLENGE_COMPLETION: 3000 // Fast completion check
|
|
46
|
+
};
|
|
47
|
+
|
|
44
48
|
/**
|
|
45
49
|
* Gets module version information
|
|
46
50
|
* @returns {object} Version information object
|
|
@@ -94,28 +98,13 @@ function shouldProcessUrl(url, forceDebug = false) {
|
|
|
94
98
|
}
|
|
95
99
|
|
|
96
100
|
/**
|
|
97
|
-
*
|
|
101
|
+
* Fast timeout helper for Puppeteer 22.x compatibility
|
|
102
|
+
* Replaces deprecated page.waitForTimeout() with standard Promise-based approach
|
|
98
103
|
*/
|
|
99
104
|
async function waitForTimeout(page, timeout) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
await Promise.race([
|
|
104
|
-
page.waitForTimeout(timeout),
|
|
105
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error('waitForTimeout exceeded')), timeout + TIMEOUTS.FALLBACK_TIMEOUT))
|
|
106
|
-
]);
|
|
107
|
-
} else if (typeof page.waitFor === 'function') {
|
|
108
|
-
await Promise.race([
|
|
109
|
-
page.waitFor(timeout),
|
|
110
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error('waitFor exceeded')), timeout + TIMEOUTS.FALLBACK_TIMEOUT))
|
|
111
|
-
]);
|
|
112
|
-
} else {
|
|
113
|
-
await new Promise(resolve => setTimeout(resolve, timeout));
|
|
114
|
-
}
|
|
115
|
-
} catch (error) {
|
|
116
|
-
// If all else fails, use setTimeout
|
|
117
|
-
await new Promise(resolve => setTimeout(resolve, Math.min(timeout, TIMEOUTS.FALLBACK_TIMEOUT)));
|
|
118
|
-
}
|
|
105
|
+
// Use fast Promise-based timeout for Puppeteer 22.x compatibility
|
|
106
|
+
// This eliminates the deprecated API dependency and improves performance
|
|
107
|
+
return new Promise(resolve => setTimeout(resolve, timeout));
|
|
119
108
|
}
|
|
120
109
|
|
|
121
110
|
/**
|
|
@@ -226,7 +215,7 @@ async function quickCloudflareDetection(page, forceDebug = false) {
|
|
|
226
215
|
url,
|
|
227
216
|
bodySnippet: bodyText.substring(0, 200)
|
|
228
217
|
};
|
|
229
|
-
},
|
|
218
|
+
}, FAST_TIMEOUTS.QUICK_DETECTION);
|
|
230
219
|
|
|
231
220
|
if (forceDebug && quickCheck.hasIndicators) {
|
|
232
221
|
console.log(`[debug][cloudflare] Quick detection found Cloudflare indicators on ${quickCheck.url}`);
|
|
@@ -356,7 +345,7 @@ async function handlePhishingWarning(page, currentUrl, forceDebug = false) {
|
|
|
356
345
|
if (forceDebug) console.log(`[debug][cloudflare] Checking for phishing warning on ${currentUrl}`);
|
|
357
346
|
|
|
358
347
|
// Shorter wait with timeout protection
|
|
359
|
-
await waitForTimeout(page,
|
|
348
|
+
await waitForTimeout(page, FAST_TIMEOUTS.PHISHING_WAIT);
|
|
360
349
|
|
|
361
350
|
const challengeInfo = await analyzeCloudflareChallenge(page);
|
|
362
351
|
|
|
@@ -424,7 +413,7 @@ async function handleVerificationChallenge(page, currentUrl, forceDebug = false)
|
|
|
424
413
|
if (forceDebug) console.log(`[debug][cloudflare] Checking for verification challenge on ${currentUrl}`);
|
|
425
414
|
|
|
426
415
|
// Reduced wait time
|
|
427
|
-
await waitForTimeout(page,
|
|
416
|
+
await waitForTimeout(page, FAST_TIMEOUTS.CHALLENGE_WAIT);
|
|
428
417
|
|
|
429
418
|
const challengeInfo = await analyzeCloudflareChallenge(page);
|
|
430
419
|
result.details = challengeInfo;
|
|
@@ -489,8 +478,8 @@ async function attemptChallengeSolveWithTimeout(page, currentUrl, challengeInfo,
|
|
|
489
478
|
// Reduced timeout for challenge solving
|
|
490
479
|
return await Promise.race([
|
|
491
480
|
attemptChallengeSolve(page, currentUrl, challengeInfo, forceDebug),
|
|
492
|
-
new Promise((_, reject) =>
|
|
493
|
-
setTimeout(() => reject(new Error('Challenge solving timeout')),
|
|
481
|
+
new Promise((_, reject) =>
|
|
482
|
+
setTimeout(() => reject(new Error('Challenge solving timeout')), FAST_TIMEOUTS.CHALLENGE_SOLVING)
|
|
494
483
|
)
|
|
495
484
|
]);
|
|
496
485
|
} catch (error) {
|
|
@@ -589,7 +578,7 @@ async function waitForJSChallengeCompletion(page, forceDebug = false) {
|
|
|
589
578
|
!document.querySelector('.cf-challenge-running') &&
|
|
590
579
|
!document.querySelector('[data-cf-challenge]');
|
|
591
580
|
},
|
|
592
|
-
{ timeout:
|
|
581
|
+
{ timeout: FAST_TIMEOUTS.JS_CHALLENGE }
|
|
593
582
|
),
|
|
594
583
|
new Promise((_, reject) =>
|
|
595
584
|
setTimeout(() => reject(new Error('JS challenge timeout')), TIMEOUTS.JS_CHALLENGE_BUFFER)
|
|
@@ -616,8 +605,8 @@ async function handleTurnstileChallenge(page, forceDebug = false) {
|
|
|
616
605
|
};
|
|
617
606
|
|
|
618
607
|
try {
|
|
619
|
-
//
|
|
620
|
-
const turnstileTimeout =
|
|
608
|
+
// Use fast timeout for Turnstile operations
|
|
609
|
+
const turnstileTimeout = FAST_TIMEOUTS.TURNSTILE_OPERATION;
|
|
621
610
|
|
|
622
611
|
const turnstileSelectors = [
|
|
623
612
|
'iframe[src*="challenges.cloudflare.com"]',
|
|
@@ -629,8 +618,8 @@ async function handleTurnstileChallenge(page, forceDebug = false) {
|
|
|
629
618
|
for (const selector of turnstileSelectors) {
|
|
630
619
|
try {
|
|
631
620
|
await Promise.race([
|
|
632
|
-
page.waitForSelector(selector, { timeout:
|
|
633
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error('Selector timeout')),
|
|
621
|
+
page.waitForSelector(selector, { timeout: FAST_TIMEOUTS.SELECTOR_WAIT }),
|
|
622
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('Selector timeout')), FAST_TIMEOUTS.SELECTOR_WAIT + 500))
|
|
634
623
|
]);
|
|
635
624
|
|
|
636
625
|
const frames = await page.frames();
|
|
@@ -663,11 +652,11 @@ async function handleTurnstileChallenge(page, forceDebug = false) {
|
|
|
663
652
|
for (const selector of checkboxSelectors) {
|
|
664
653
|
try {
|
|
665
654
|
await Promise.race([
|
|
666
|
-
turnstileFrame.waitForSelector(selector, { timeout:
|
|
667
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error('Checkbox timeout')),
|
|
655
|
+
turnstileFrame.waitForSelector(selector, { timeout: FAST_TIMEOUTS.SELECTOR_WAIT }),
|
|
656
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('Checkbox timeout')), FAST_TIMEOUTS.SELECTOR_WAIT + 500))
|
|
668
657
|
]);
|
|
669
658
|
|
|
670
|
-
await waitForTimeout(page,
|
|
659
|
+
await waitForTimeout(page, FAST_TIMEOUTS.ELEMENT_INTERACTION_DELAY);
|
|
671
660
|
await turnstileFrame.click(selector);
|
|
672
661
|
|
|
673
662
|
if (forceDebug) console.log(`[debug][cloudflare] Clicked Turnstile checkbox: ${selector}`);
|
|
@@ -705,11 +694,11 @@ async function handleTurnstileChallenge(page, forceDebug = false) {
|
|
|
705
694
|
for (const selector of containerSelectors) {
|
|
706
695
|
try {
|
|
707
696
|
await Promise.race([
|
|
708
|
-
page.waitForSelector(selector, { timeout:
|
|
709
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error('Container timeout')),
|
|
697
|
+
page.waitForSelector(selector, { timeout: FAST_TIMEOUTS.SELECTOR_WAIT }),
|
|
698
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('Container timeout')), FAST_TIMEOUTS.SELECTOR_WAIT + 500))
|
|
710
699
|
]);
|
|
711
700
|
|
|
712
|
-
await waitForTimeout(page,
|
|
701
|
+
await waitForTimeout(page, FAST_TIMEOUTS.ELEMENT_INTERACTION_DELAY);
|
|
713
702
|
await page.click(selector);
|
|
714
703
|
|
|
715
704
|
if (forceDebug) console.log(`[debug][cloudflare] Clicked Turnstile container: ${selector}`);
|
|
@@ -761,8 +750,8 @@ async function handleLegacyCheckbox(page, forceDebug = false) {
|
|
|
761
750
|
for (const selector of legacySelectors) {
|
|
762
751
|
try {
|
|
763
752
|
await Promise.race([
|
|
764
|
-
page.waitForSelector(selector, { timeout:
|
|
765
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error('Legacy selector timeout')),
|
|
753
|
+
page.waitForSelector(selector, { timeout: FAST_TIMEOUTS.SELECTOR_WAIT }),
|
|
754
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('Legacy selector timeout')), FAST_TIMEOUTS.SELECTOR_WAIT + 500))
|
|
766
755
|
]);
|
|
767
756
|
|
|
768
757
|
const checkbox = await page.$(selector);
|
|
@@ -814,7 +803,7 @@ async function checkChallengeCompletion(page) {
|
|
|
814
803
|
return (noChallengeRunning && noChallengeContainer && noChallengePage) ||
|
|
815
804
|
hasClearanceCookie ||
|
|
816
805
|
hasTurnstileResponse;
|
|
817
|
-
},
|
|
806
|
+
}, FAST_TIMEOUTS.CHALLENGE_COMPLETION);
|
|
818
807
|
|
|
819
808
|
return { isCompleted };
|
|
820
809
|
} catch (error) {
|
package/lib/flowproxy.js
CHANGED
|
@@ -17,15 +17,24 @@ const FLOWPROXY_MODULE_VERSION = '1.0.0';
|
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Timeout constants for FlowProxy operations (in milliseconds)
|
|
20
|
+
* Optimized for Puppeteer 22.x performance while maintaining FlowProxy compatibility
|
|
20
21
|
*/
|
|
21
22
|
const TIMEOUTS = {
|
|
23
|
+
PAGE_EVALUATION_SAFE: 10000, // Safe page evaluation timeout
|
|
24
|
+
// FlowProxy-specific timeouts
|
|
22
25
|
PAGE_LOAD_WAIT: 2000, // Initial wait for page to load
|
|
23
26
|
JS_CHALLENGE_DEFAULT: 15000, // Default JavaScript challenge timeout
|
|
24
27
|
RATE_LIMIT_DEFAULT: 30000, // Default rate limit delay
|
|
25
28
|
ADDITIONAL_DELAY_DEFAULT: 5000, // Default additional processing delay
|
|
26
29
|
PAGE_TIMEOUT_DEFAULT: 45000, // Default page timeout
|
|
27
30
|
NAVIGATION_TIMEOUT_DEFAULT: 45000, // Default navigation timeout
|
|
28
|
-
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// Fast timeout constants - optimized for speed while respecting FlowProxy delays
|
|
34
|
+
const FAST_TIMEOUTS = {
|
|
35
|
+
PAGE_LOAD_WAIT: 1500, // Reduced from 2000ms
|
|
36
|
+
ADDITIONAL_DELAY_DEFAULT: 3000, // Reduced from 5000ms
|
|
37
|
+
FALLBACK_TIMEOUT: 3000 // Reduced from 5000ms
|
|
29
38
|
};
|
|
30
39
|
|
|
31
40
|
/**
|
|
@@ -93,35 +102,39 @@ function shouldProcessUrl(url, forceDebug = false) {
|
|
|
93
102
|
}
|
|
94
103
|
|
|
95
104
|
/**
|
|
96
|
-
*
|
|
97
|
-
*
|
|
105
|
+
* Fast timeout helper for Puppeteer 22.x compatibility
|
|
106
|
+
* Replaces deprecated page.waitForTimeout() with standard Promise-based approach
|
|
98
107
|
*
|
|
99
108
|
* @param {import('puppeteer').Page} page - Puppeteer page instance
|
|
100
109
|
* @param {number} timeout - Timeout in milliseconds
|
|
101
110
|
* @returns {Promise<void>}
|
|
102
|
-
*
|
|
103
|
-
* @example
|
|
104
|
-
* // Wait for 5 seconds
|
|
105
|
-
* await waitForTimeout(page, 5000);
|
|
106
111
|
*/
|
|
107
112
|
async function waitForTimeout(page, timeout) {
|
|
113
|
+
// Use fast Promise-based timeout for Puppeteer 22.x compatibility
|
|
114
|
+
return new Promise(resolve => setTimeout(resolve, timeout));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Safe page evaluation with timeout protection for FlowProxy analysis
|
|
119
|
+
*/
|
|
120
|
+
async function safePageEvaluate(page, func, timeout = TIMEOUTS.PAGE_EVALUATION_SAFE) {
|
|
108
121
|
try {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
} else {
|
|
116
|
-
// Final fallback - use standard setTimeout
|
|
117
|
-
await new Promise(resolve => setTimeout(resolve, timeout));
|
|
118
|
-
}
|
|
122
|
+
return await Promise.race([
|
|
123
|
+
page.evaluate(func),
|
|
124
|
+
new Promise((_, reject) =>
|
|
125
|
+
setTimeout(() => reject(new Error('FlowProxy page evaluation timeout')), timeout)
|
|
126
|
+
)
|
|
127
|
+
]);
|
|
119
128
|
} catch (error) {
|
|
120
|
-
//
|
|
121
|
-
|
|
129
|
+
// Return safe defaults if evaluation fails
|
|
130
|
+
return {
|
|
131
|
+
isFlowProxyDetected: false,
|
|
132
|
+
error: error.message
|
|
133
|
+
};
|
|
122
134
|
}
|
|
123
135
|
}
|
|
124
136
|
|
|
137
|
+
|
|
125
138
|
/**
|
|
126
139
|
* Analyzes the current page to detect flowProxy protection with comprehensive detection logic
|
|
127
140
|
*
|
|
@@ -158,7 +171,7 @@ async function analyzeFlowProxyProtection(page) {
|
|
|
158
171
|
}
|
|
159
172
|
|
|
160
173
|
// Continue with comprehensive FlowProxy detection for valid HTTP(S) URLs
|
|
161
|
-
return await page
|
|
174
|
+
return await safePageEvaluate(page, () => {
|
|
162
175
|
const title = document.title || '';
|
|
163
176
|
const bodyText = document.body ? document.body.textContent : '';
|
|
164
177
|
const url = window.location.href;
|
|
@@ -327,7 +340,7 @@ async function handleFlowProxyProtection(page, currentUrl, siteConfig, forceDebu
|
|
|
327
340
|
|
|
328
341
|
// Wait for initial page load before analyzing
|
|
329
342
|
// FlowProxy protection pages need time to fully render their elements
|
|
330
|
-
await waitForTimeout(page,
|
|
343
|
+
await waitForTimeout(page, FAST_TIMEOUTS.PAGE_LOAD_WAIT);
|
|
331
344
|
|
|
332
345
|
// Perform comprehensive FlowProxy detection
|
|
333
346
|
const detectionInfo = await analyzeFlowProxyProtection(page);
|
|
@@ -371,7 +384,8 @@ async function handleFlowProxyProtection(page, currentUrl, siteConfig, forceDebu
|
|
|
371
384
|
try {
|
|
372
385
|
// Wait for challenge completion indicators to disappear
|
|
373
386
|
// These conditions indicate the JS challenge has finished
|
|
374
|
-
await
|
|
387
|
+
await Promise.race([
|
|
388
|
+
page.waitForFunction(
|
|
375
389
|
() => {
|
|
376
390
|
const bodyText = document.body ? document.body.textContent : '';
|
|
377
391
|
return !bodyText.includes('Processing') &&
|
|
@@ -381,7 +395,11 @@ async function handleFlowProxyProtection(page, currentUrl, siteConfig, forceDebu
|
|
|
381
395
|
!document.querySelector('.processing-indicator');
|
|
382
396
|
},
|
|
383
397
|
{ timeout: jsWaitTime }
|
|
384
|
-
|
|
398
|
+
),
|
|
399
|
+
new Promise((_, reject) =>
|
|
400
|
+
setTimeout(() => reject(new Error('JS challenge timeout')), jsWaitTime + 5000)
|
|
401
|
+
)
|
|
402
|
+
]);
|
|
385
403
|
|
|
386
404
|
if (forceDebug) console.log(`[debug][flowproxy] JavaScript challenge appears to have completed`);
|
|
387
405
|
} catch (timeoutErr) {
|
|
@@ -393,7 +411,7 @@ async function handleFlowProxyProtection(page, currentUrl, siteConfig, forceDebu
|
|
|
393
411
|
|
|
394
412
|
// IMPLEMENT ADDITIONAL DELAY - Final step to ensure all processing completes
|
|
395
413
|
// FlowProxy may need extra time even after challenges complete
|
|
396
|
-
const additionalDelay = siteConfig.flowproxy_additional_delay ||
|
|
414
|
+
const additionalDelay = siteConfig.flowproxy_additional_delay || FAST_TIMEOUTS.ADDITIONAL_DELAY_DEFAULT;
|
|
397
415
|
if (forceDebug) console.log(`[debug][flowproxy] Implementing additional ${additionalDelay}ms delay for flowProxy processing`);
|
|
398
416
|
await waitForTimeout(page, additionalDelay);
|
|
399
417
|
|
package/lib/interaction.js
CHANGED
|
@@ -53,6 +53,12 @@
|
|
|
53
53
|
* @version 1.0
|
|
54
54
|
* @requires puppeteer
|
|
55
55
|
*/
|
|
56
|
+
|
|
57
|
+
// Fast setTimeout helper for Puppeteer 22.x compatibility
|
|
58
|
+
// Uses standard Promise constructor for better performance than node:timers/promises
|
|
59
|
+
function fastTimeout(ms) {
|
|
60
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
61
|
+
}
|
|
56
62
|
|
|
57
63
|
// === VIEWPORT AND COORDINATE CONSTANTS ===
|
|
58
64
|
// These control the default viewport assumptions and coordinate generation
|
|
@@ -336,7 +342,7 @@ async function humanLikeMouseMove(page, fromX, fromY, toX, toY, options = {}) {
|
|
|
336
342
|
// Variable delay between movements
|
|
337
343
|
if (i < actualSteps) {
|
|
338
344
|
const delay = Math.floor(Math.random() * (maxDelay - minDelay + 1)) + minDelay;
|
|
339
|
-
await
|
|
345
|
+
await fastTimeout(delay);
|
|
340
346
|
}
|
|
341
347
|
}
|
|
342
348
|
}
|
|
@@ -396,7 +402,7 @@ async function simulateScrolling(page, options = {}) {
|
|
|
396
402
|
}
|
|
397
403
|
|
|
398
404
|
if (i < amount - 1) {
|
|
399
|
-
await
|
|
405
|
+
await fastTimeout(pauseBetween);
|
|
400
406
|
}
|
|
401
407
|
}
|
|
402
408
|
} catch (scrollErr) {
|
|
@@ -514,12 +520,12 @@ async function interactWithElements(page, options = {}) {
|
|
|
514
520
|
await humanLikeMouseMove(page, currentPos.x, currentPos.y, element.x, element.y);
|
|
515
521
|
|
|
516
522
|
// Brief pause before clicking
|
|
517
|
-
await
|
|
523
|
+
await fastTimeout(TIMING.CLICK_PAUSE_MIN + Math.random() * TIMING.CLICK_PAUSE_MAX);
|
|
518
524
|
|
|
519
525
|
await page.mouse.click(element.x, element.y);
|
|
520
526
|
|
|
521
527
|
// Brief pause after clicking
|
|
522
|
-
await
|
|
528
|
+
await fastTimeout(TIMING.POST_CLICK_MIN + Math.random() * TIMING.POST_CLICK_MAX);
|
|
523
529
|
}
|
|
524
530
|
} catch (elementErr) {
|
|
525
531
|
// Continue to next attempt if this one fails
|
|
@@ -590,16 +596,16 @@ async function simulateTyping(page, text, options = {}) {
|
|
|
590
596
|
if (mistakes && Math.random() < mistakeRate) {
|
|
591
597
|
const wrongChar = String.fromCharCode(97 + Math.floor(Math.random() * 26));
|
|
592
598
|
await page.keyboard.type(wrongChar);
|
|
593
|
-
await
|
|
599
|
+
await fastTimeout(TIMING.MISTAKE_PAUSE_MIN + Math.random() * TIMING.MISTAKE_PAUSE_MAX);
|
|
594
600
|
await page.keyboard.press('Backspace');
|
|
595
|
-
await
|
|
601
|
+
await fastTimeout(TIMING.BACKSPACE_DELAY_MIN + Math.random() * TIMING.BACKSPACE_DELAY_MAX);
|
|
596
602
|
}
|
|
597
603
|
|
|
598
604
|
await page.keyboard.type(char);
|
|
599
605
|
|
|
600
606
|
// Variable delay between keystrokes
|
|
601
607
|
const delay = Math.floor(Math.random() * (maxDelay - minDelay + 1)) + minDelay;
|
|
602
|
-
await
|
|
608
|
+
await fastTimeout(delay);
|
|
603
609
|
}
|
|
604
610
|
} catch (typingErr) {
|
|
605
611
|
// Silently handle typing errors
|
|
@@ -715,11 +721,11 @@ async function performPageInteraction(page, currentUrl, options = {}, forceDebug
|
|
|
715
721
|
|
|
716
722
|
// Occasional pause
|
|
717
723
|
if (Math.random() < PROBABILITIES.PAUSE_CHANCE) {
|
|
718
|
-
await
|
|
724
|
+
await fastTimeout(TIMING.CLICK_PAUSE_MIN + Math.random() * TIMING.POST_CLICK_MIN);
|
|
719
725
|
}
|
|
720
726
|
|
|
721
727
|
// Time-based spacing
|
|
722
|
-
await
|
|
728
|
+
await fastTimeout(actionInterval);
|
|
723
729
|
}
|
|
724
730
|
|
|
725
731
|
// Scrolling simulation
|
|
@@ -732,7 +738,7 @@ async function performPageInteraction(page, currentUrl, options = {}, forceDebug
|
|
|
732
738
|
smoothness: 3 + Math.floor(Math.random() * 4)
|
|
733
739
|
});
|
|
734
740
|
|
|
735
|
-
await
|
|
741
|
+
await fastTimeout(actionInterval);
|
|
736
742
|
}
|
|
737
743
|
}
|
|
738
744
|
|
package/nwss.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// === Network scanner script (nwss.js) v1.0.
|
|
1
|
+
// === Network scanner script (nwss.js) v1.0.61 ===
|
|
2
2
|
|
|
3
3
|
// puppeteer for browser automation, fs for file system operations, psl for domain parsing.
|
|
4
4
|
// const pLimit = require('p-limit'); // Will be dynamically imported
|
|
@@ -35,13 +35,20 @@ const { performPageInteraction, createInteractionConfig } = require('./lib/inter
|
|
|
35
35
|
const { createGlobalHelpers, getTotalDomainsSkipped, getDetectedDomainsCount } = require('./lib/domain-cache');
|
|
36
36
|
const { createSmartCache } = require('./lib/smart-cache'); // Smart cache system
|
|
37
37
|
const { clearPersistentCache } = require('./lib/smart-cache');
|
|
38
|
+
|
|
39
|
+
// Fast setTimeout helper for Puppeteer 22.x compatibility
|
|
40
|
+
// Uses standard Promise constructor for better performance than node:timers/promises
|
|
41
|
+
function fastTimeout(ms) {
|
|
42
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
43
|
+
}
|
|
44
|
+
|
|
38
45
|
// Enhanced redirect handling
|
|
39
46
|
const { navigateWithRedirectHandling, handleRedirectTimeout } = require('./lib/redirect');
|
|
40
47
|
// Ensure web browser is working correctly
|
|
41
48
|
const { monitorBrowserHealth, isBrowserHealthy } = require('./lib/browserhealth');
|
|
42
49
|
|
|
43
|
-
// --- Script Configuration & Constants ---
|
|
44
|
-
const VERSION = '1.0.
|
|
50
|
+
// --- Script Configuration & Constants ---
|
|
51
|
+
const VERSION = '1.0.61'; // Script version
|
|
45
52
|
|
|
46
53
|
// get startTime
|
|
47
54
|
const startTime = Date.now();
|
|
@@ -382,7 +389,7 @@ Global config.json options:
|
|
|
382
389
|
ignore_similar: true/false Ignore domains similar to already found domains (default: true)
|
|
383
390
|
ignore_similar_threshold: 80 Similarity threshold percentage for ignore_similar (default: 80)
|
|
384
391
|
ignore_similar_ignored_domains: true/false Ignore domains similar to ignoreDomains list (default: true)
|
|
385
|
-
max_concurrent_sites:
|
|
392
|
+
max_concurrent_sites: 8 Maximum concurrent site processing (1-50, default: 8)
|
|
386
393
|
resource_cleanup_interval: 180 Browser restart interval in URLs processed (1-1000, default: 180)
|
|
387
394
|
|
|
388
395
|
Per-site config.json options:
|
|
@@ -1040,6 +1047,11 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
1040
1047
|
executablePath: executablePath,
|
|
1041
1048
|
// Force temporary user data directory for complete cleanup control
|
|
1042
1049
|
userDataDir: tempUserDataDir,
|
|
1050
|
+
// Puppeteer 22.x headless mode optimization
|
|
1051
|
+
// 'shell' = chrome-headless-shell (performance optimized)
|
|
1052
|
+
// true = new unified headless mode (full Chrome features)
|
|
1053
|
+
// false = headful mode (GUI visible)
|
|
1054
|
+
headless: launchHeadless ? 'shell' : false, // Use shell for maximum performance
|
|
1043
1055
|
args: [
|
|
1044
1056
|
// Disk space controls - 50MB cache limits
|
|
1045
1057
|
'--disk-cache-size=52428800', // 50MB disk cache (50 * 1024 * 1024)
|
|
@@ -1047,6 +1059,17 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
1047
1059
|
'--disable-application-cache',
|
|
1048
1060
|
'--disable-offline-load-stale-cache',
|
|
1049
1061
|
'--disable-background-downloads',
|
|
1062
|
+
// PERFORMANCE: Additional Puppeteer 22.x optimizations
|
|
1063
|
+
'--disable-features=VizDisplayCompositor,AudioServiceOutOfProcess',
|
|
1064
|
+
'--disable-ipc-flooding-protection',
|
|
1065
|
+
'--disable-renderer-backgrounding',
|
|
1066
|
+
'--disable-backgrounding-occluded-windows',
|
|
1067
|
+
'--disable-features=TranslateUI,BlinkGenPropertyTrees',
|
|
1068
|
+
'--disable-features=Translate,BackForwardCache,AcceptCHFrame',
|
|
1069
|
+
'--aggressive-cache-discard',
|
|
1070
|
+
'--memory-pressure-off',
|
|
1071
|
+
'--max_old_space_size=2048',
|
|
1072
|
+
'--disable-features=VizDisplayCompositor',
|
|
1050
1073
|
'--no-first-run',
|
|
1051
1074
|
'--disable-default-apps',
|
|
1052
1075
|
'--disable-component-extensions-with-background-pages',
|
|
@@ -1070,18 +1093,13 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
1070
1093
|
'--ignore-certificate-errors-ca-list',
|
|
1071
1094
|
'--disable-web-security',
|
|
1072
1095
|
'--allow-running-insecure-content',
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
'--disable-threaded-animation',
|
|
1080
|
-
'--disable-threaded-scrolling',
|
|
1081
|
-
'--disable-checker-imaging',
|
|
1082
|
-
'--disable-image-animation-resync'
|
|
1096
|
+
'--disable-features=HttpsFirstBalancedModeAutoEnable',
|
|
1097
|
+
'--run-all-compositor-stages-before-draw',
|
|
1098
|
+
'--disable-threaded-animation',
|
|
1099
|
+
'--disable-threaded-scrolling',
|
|
1100
|
+
'--disable-checker-imaging',
|
|
1101
|
+
'--disable-image-animation-resync'
|
|
1083
1102
|
],
|
|
1084
|
-
headless: launchHeadless ? 'shell' : false,
|
|
1085
1103
|
protocolTimeout: 60000 // 60 seconds
|
|
1086
1104
|
});
|
|
1087
1105
|
|
|
@@ -1251,9 +1269,9 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
1251
1269
|
page = await browserInstance.newPage();
|
|
1252
1270
|
|
|
1253
1271
|
// Set aggressive timeouts for problematic operations
|
|
1254
|
-
page.setDefaultTimeout(Math.min(timeout,
|
|
1255
|
-
page.setDefaultNavigationTimeout(Math.min(timeout,
|
|
1256
|
-
//
|
|
1272
|
+
page.setDefaultTimeout(Math.min(timeout, 15000)); // Reduced for Puppeteer 22.x
|
|
1273
|
+
page.setDefaultNavigationTimeout(Math.min(timeout, 18000)); // Reduced for faster fails
|
|
1274
|
+
// Aggressive timeouts prevent hanging in Puppeteer 22.x
|
|
1257
1275
|
|
|
1258
1276
|
page.on('console', (msg) => {
|
|
1259
1277
|
if (forceDebug && msg.type() === 'error') console.log(`[debug] Console error: ${msg.text()}`);
|
|
@@ -1268,8 +1286,8 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
1268
1286
|
// Apply flowProxy timeouts if detection is enabled
|
|
1269
1287
|
if (flowproxyDetection) {
|
|
1270
1288
|
const flowproxyTimeouts = getFlowProxyTimeouts(siteConfig);
|
|
1271
|
-
page.setDefaultTimeout(flowproxyTimeouts.pageTimeout);
|
|
1272
|
-
page.setDefaultNavigationTimeout(flowproxyTimeouts.navigationTimeout);
|
|
1289
|
+
page.setDefaultTimeout(Math.min(flowproxyTimeouts.pageTimeout, 25000));
|
|
1290
|
+
page.setDefaultNavigationTimeout(Math.min(flowproxyTimeouts.navigationTimeout, 30000));
|
|
1273
1291
|
if (forceDebug) {
|
|
1274
1292
|
console.log(formatLogMessage('debug', `Applied flowProxy timeouts - page: ${flowproxyTimeouts.pageTimeout}ms, nav: ${flowproxyTimeouts.navigationTimeout}ms`));
|
|
1275
1293
|
}
|
|
@@ -2077,21 +2095,23 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
2077
2095
|
|
|
2078
2096
|
try {
|
|
2079
2097
|
// Use custom goto options if provided, otherwise default to 'load'
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2098
|
+
// load Wait for all resources (default)
|
|
2099
|
+
// domcontentloaded Wait for DOM only
|
|
2100
|
+
// networkidle0 Wait until 0 network requests for 500ms
|
|
2101
|
+
// networkidle2 Wait until ≤2 network requests for 500ms
|
|
2102
|
+
|
|
2103
|
+
// Note: For Puppeteer 22.x compatibility, avoid deprecated timeout patterns
|
|
2104
|
+
// Use explicit Promise-based timeouts instead of page.waitForTimeout()
|
|
2084
2105
|
|
|
2085
2106
|
// Use faster defaults for sites with long timeouts to improve responsiveness
|
|
2086
2107
|
const isFastSite = timeout <= 15000;
|
|
2087
|
-
const defaultWaitUntil =
|
|
2108
|
+
const defaultWaitUntil = 'domcontentloaded'; // Always use faster option in Puppeteer 22.x
|
|
2088
2109
|
const defaultGotoOptions = {
|
|
2089
2110
|
waitUntil: defaultWaitUntil,
|
|
2090
|
-
timeout: timeout
|
|
2111
|
+
timeout: Math.min(timeout, 20000) // Cap timeout for faster failures
|
|
2091
2112
|
};
|
|
2092
2113
|
const gotoOptions = siteConfig.goto_options
|
|
2093
|
-
? { ...defaultGotoOptions, ...siteConfig.goto_options }
|
|
2094
|
-
: defaultGotoOptions;
|
|
2114
|
+
? { ...defaultGotoOptions, ...siteConfig.goto_options } : defaultGotoOptions;
|
|
2095
2115
|
|
|
2096
2116
|
// Enhanced navigation with redirect handling - passes existing gotoOptions
|
|
2097
2117
|
const navigationResult = await navigateWithRedirectHandling(page, currentUrl, siteConfig, gotoOptions, forceDebug, formatLogMessage);
|
|
@@ -2171,7 +2191,8 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
2171
2191
|
// Wait for iframes to load and log them
|
|
2172
2192
|
if (forceDebug) {
|
|
2173
2193
|
try {
|
|
2174
|
-
|
|
2194
|
+
// Use fast timeout helper for compatibility
|
|
2195
|
+
await fastTimeout(2000); // Give iframes time to load
|
|
2175
2196
|
const frames = page.frames();
|
|
2176
2197
|
console.log(formatLogMessage('debug', `Total frames found: ${frames.length}`));
|
|
2177
2198
|
frames.forEach((frame, index) => {
|
|
@@ -2214,25 +2235,29 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
2214
2235
|
|
|
2215
2236
|
const delayMs = siteConfig.delay || 4000;
|
|
2216
2237
|
|
|
2217
|
-
//
|
|
2238
|
+
// Aggressive optimization for Puppeteer 22.x responsiveness
|
|
2218
2239
|
const isFastSite = timeout <= 15000;
|
|
2219
|
-
const networkIdleTime =
|
|
2220
|
-
const networkIdleTimeout =
|
|
2221
|
-
const actualDelay =
|
|
2240
|
+
const networkIdleTime = 2000; // Reduced for all sites
|
|
2241
|
+
const networkIdleTimeout = Math.min(timeout / 2, 8000); // Much shorter timeout
|
|
2242
|
+
const actualDelay = Math.min(delayMs, 1500); // Reduced delay for all sites
|
|
2222
2243
|
|
|
2223
2244
|
await page.waitForNetworkIdle({
|
|
2224
2245
|
idleTime: networkIdleTime,
|
|
2225
2246
|
timeout: networkIdleTimeout
|
|
2226
2247
|
});
|
|
2227
|
-
|
|
2248
|
+
// Use fast timeout helper for Puppeteer 22.x compatibility with better performance
|
|
2249
|
+
await fastTimeout(actualDelay);
|
|
2228
2250
|
|
|
2229
2251
|
// Apply additional delay for flowProxy if detected
|
|
2230
2252
|
if (flowproxyDetection) {
|
|
2231
|
-
const additionalDelay = siteConfig.flowproxy_additional_delay ||
|
|
2253
|
+
const additionalDelay = Math.min(siteConfig.flowproxy_additional_delay || 3000, 3000);
|
|
2232
2254
|
if (forceDebug) console.log(formatLogMessage('debug', `Applying flowProxy additional delay: ${additionalDelay}ms`));
|
|
2233
|
-
await
|
|
2255
|
+
await fastTimeout(additionalDelay);
|
|
2234
2256
|
}
|
|
2235
2257
|
|
|
2258
|
+
// Replace deprecated page.waitForTimeout patterns with fast timeout helper
|
|
2259
|
+
// This ensures compatibility with Puppeteer 22.x where waitForTimeout was removed
|
|
2260
|
+
|
|
2236
2261
|
for (let i = 1; i < (siteConfig.reload || 1); i++) {
|
|
2237
2262
|
if (siteConfig.clear_sitedata === true) {
|
|
2238
2263
|
try {
|
|
@@ -2256,16 +2281,16 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
2256
2281
|
console.warn(messageColors.warn(`[clear_sitedata before reload failed] ${currentUrl}: ${reloadClearErr.message}`));
|
|
2257
2282
|
}
|
|
2258
2283
|
}
|
|
2259
|
-
await page.reload({ waitUntil: 'domcontentloaded', timeout: timeout });
|
|
2260
|
-
await
|
|
2284
|
+
await page.reload({ waitUntil: 'domcontentloaded', timeout: Math.min(timeout, 15000) });
|
|
2285
|
+
await fastTimeout(delayMs);
|
|
2261
2286
|
}
|
|
2262
2287
|
|
|
2263
2288
|
if (siteConfig.forcereload === true) {
|
|
2264
2289
|
if (forceDebug) console.log(formatLogMessage('debug', `Forcing extra reload (cache disabled) for ${currentUrl}`));
|
|
2265
2290
|
try {
|
|
2266
2291
|
await page.setCacheEnabled(false);
|
|
2267
|
-
await page.reload({ waitUntil: 'domcontentloaded', timeout: timeout });
|
|
2268
|
-
await
|
|
2292
|
+
await page.reload({ waitUntil: 'domcontentloaded', timeout: Math.min(timeout, 12000) });
|
|
2293
|
+
await fastTimeout(delayMs);
|
|
2269
2294
|
await page.setCacheEnabled(true);
|
|
2270
2295
|
} catch (forceReloadErr) {
|
|
2271
2296
|
console.warn(messageColors.warn(`[forcereload failed] ${currentUrl}: ${forceReloadErr.message}`));
|
|
@@ -2299,7 +2324,8 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
2299
2324
|
});
|
|
2300
2325
|
|
|
2301
2326
|
// Wait a moment for async nettools/searchstring operations to complete
|
|
2302
|
-
|
|
2327
|
+
// Use fast timeout helper for Puppeteer 22.x compatibility
|
|
2328
|
+
await fastTimeout(3000); // Increased for nettools operations
|
|
2303
2329
|
|
|
2304
2330
|
outputDryRunResults(currentUrl, enhancedMatches, dryRunNetTools, pageTitle);
|
|
2305
2331
|
|
|
@@ -2451,12 +2477,12 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
2451
2477
|
// Also check if browser was unhealthy during recent processing
|
|
2452
2478
|
const recentResults = results.slice(-3);
|
|
2453
2479
|
const hasRecentFailures = recentResults.filter(r => !r.success).length >= 2;
|
|
2454
|
-
const shouldRestartFromFailures = hasRecentFailures && urlsSinceLastCleanup >
|
|
2480
|
+
const shouldRestartFromFailures = hasRecentFailures && urlsSinceLastCleanup > 3; // More aggressive restart
|
|
2455
2481
|
|
|
2456
2482
|
const siteUrlCount = siteGroup.urls.length;
|
|
2457
2483
|
|
|
2458
2484
|
// Check if processing this entire site would exceed cleanup interval OR health check suggests restart
|
|
2459
|
-
const wouldExceedLimit = urlsSinceLastCleanup + siteUrlCount >= RESOURCE_CLEANUP_INTERVAL;
|
|
2485
|
+
const wouldExceedLimit = urlsSinceLastCleanup + siteUrlCount >= Math.min(RESOURCE_CLEANUP_INTERVAL, 100); // More frequent restarts
|
|
2460
2486
|
const isNotLastSite = siteIndex < siteGroups.length - 1;
|
|
2461
2487
|
|
|
2462
2488
|
// Restart browser if we've processed enough URLs, health check suggests it, and this isn't the last site
|
|
@@ -2509,7 +2535,7 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
2509
2535
|
|
|
2510
2536
|
// Reset cleanup counter and add delay
|
|
2511
2537
|
urlsSinceLastCleanup = 0;
|
|
2512
|
-
await
|
|
2538
|
+
await fastTimeout(1000);
|
|
2513
2539
|
}
|
|
2514
2540
|
|
|
2515
2541
|
if (forceDebug) {
|
|
@@ -2547,7 +2573,7 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
2547
2573
|
}
|
|
2548
2574
|
browser = await createBrowser();
|
|
2549
2575
|
urlsSinceLastCleanup = 0; // Reset counter
|
|
2550
|
-
await
|
|
2576
|
+
await fastTimeout(2000); // Give browser time to stabilize
|
|
2551
2577
|
} catch (emergencyRestartErr) {
|
|
2552
2578
|
if (forceDebug) console.log(formatLogMessage('debug', `Emergency restart failed: ${emergencyRestartErr.message}`));
|
|
2553
2579
|
}
|
|
@@ -2704,7 +2730,7 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
2704
2730
|
forceDebug,
|
|
2705
2731
|
comprehensive: true
|
|
2706
2732
|
});
|
|
2707
|
-
await
|
|
2733
|
+
await fastTimeout(1000); // Give filesystem time to sync
|
|
2708
2734
|
|
|
2709
2735
|
// Calculate timing, success rates, and provide summary information
|
|
2710
2736
|
if (forceDebug) console.log(formatLogMessage('debug', `Calculating timing statistics...`));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fanboynz/network-scanner",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.61",
|
|
4
4
|
"description": "A Puppeteer-based network scanner for analyzing web traffic, generating adblock filter rules, and identifying third-party requests. Features include fingerprint spoofing, Cloudflare bypass, content analysis with curl/grep, and multiple output formats.",
|
|
5
5
|
"main": "nwss.js",
|
|
6
6
|
"scripts": {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"lru-cache": "^10.4.3",
|
|
14
14
|
"p-limit": "^4.0.0",
|
|
15
15
|
"psl": "^1.15.0",
|
|
16
|
-
"puppeteer": "
|
|
16
|
+
"puppeteer": ">=20.0.0 <23.0.0"
|
|
17
17
|
},
|
|
18
18
|
"keywords": [
|
|
19
19
|
"puppeteer",
|