@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 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
- * Cross-version compatible timeout function for Puppeteer with timeout protection
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
- try {
101
- // Try newer Puppeteer method first
102
- if (typeof page.waitForTimeout === 'function') {
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
- }, TIMEOUTS.QUICK_DETECTION);
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, TIMEOUTS.PHISHING_WAIT);
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, TIMEOUTS.CHALLENGE_WAIT);
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')), TIMEOUTS.CHALLENGE_SOLVING)
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: TIMEOUTS.JS_CHALLENGE }
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
- // Reduced timeout for Turnstile operations
620
- const turnstileTimeout = TIMEOUTS.TURNSTILE_OPERATION;
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: TIMEOUTS.SELECTOR_WAIT }),
633
- new Promise((_, reject) => setTimeout(() => reject(new Error('Selector timeout')), TIMEOUTS.SELECTOR_WAIT_BUFFER))
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: TIMEOUTS.SELECTOR_WAIT }),
667
- new Promise((_, reject) => setTimeout(() => reject(new Error('Checkbox timeout')), TIMEOUTS.SELECTOR_WAIT_BUFFER))
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, TIMEOUTS.ELEMENT_INTERACTION_DELAY);
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: TIMEOUTS.SELECTOR_WAIT }),
709
- new Promise((_, reject) => setTimeout(() => reject(new Error('Container timeout')), TIMEOUTS.SELECTOR_WAIT_BUFFER))
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, TIMEOUTS.ELEMENT_INTERACTION_DELAY);
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: TIMEOUTS.SELECTOR_WAIT }),
765
- new Promise((_, reject) => setTimeout(() => reject(new Error('Legacy selector timeout')), TIMEOUTS.SELECTOR_WAIT_BUFFER))
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
- }, TIMEOUTS.CHALLENGE_COMPLETION);
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
- FALLBACK_TIMEOUT: 5000 // Fallback timeout for failed operations
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
- * Cross-version compatible timeout function for Puppeteer with timeout protection
97
- * Handles different Puppeteer versions that may have different timeout methods
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
- // Try newer Puppeteer method first (v1.4.0+)
110
- if (typeof page.waitForTimeout === 'function') {
111
- await page.waitForTimeout(timeout);
112
- } else if (typeof page.waitFor === 'function') {
113
- // Fallback for older Puppeteer versions
114
- await page.waitFor(timeout);
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
- // If all else fails, use setTimeout
121
- await new Promise(resolve => setTimeout(resolve, timeout));
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.evaluate(() => {
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, TIMEOUTS.PAGE_LOAD_WAIT);
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 page.waitForFunction(
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 || TIMEOUTS.ADDITIONAL_DELAY_DEFAULT;
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
 
@@ -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 new Promise(resolve => setTimeout(resolve, delay));
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 new Promise(resolve => setTimeout(resolve, pauseBetween));
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 new Promise(resolve => setTimeout(resolve, TIMING.CLICK_PAUSE_MIN + Math.random() * TIMING.CLICK_PAUSE_MAX));
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 new Promise(resolve => setTimeout(resolve, TIMING.POST_CLICK_MIN + Math.random() * TIMING.POST_CLICK_MAX));
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 new Promise(resolve => setTimeout(resolve, TIMING.MISTAKE_PAUSE_MIN + Math.random() * TIMING.MISTAKE_PAUSE_MAX));
599
+ await fastTimeout(TIMING.MISTAKE_PAUSE_MIN + Math.random() * TIMING.MISTAKE_PAUSE_MAX);
594
600
  await page.keyboard.press('Backspace');
595
- await new Promise(resolve => setTimeout(resolve, TIMING.BACKSPACE_DELAY_MIN + Math.random() * TIMING.BACKSPACE_DELAY_MAX));
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 new Promise(resolve => setTimeout(resolve, delay));
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 new Promise(resolve => setTimeout(resolve, TIMING.CLICK_PAUSE_MIN + Math.random() * TIMING.POST_CLICK_MIN));
724
+ await fastTimeout(TIMING.CLICK_PAUSE_MIN + Math.random() * TIMING.POST_CLICK_MIN);
719
725
  }
720
726
 
721
727
  // Time-based spacing
722
- await new Promise(resolve => setTimeout(resolve, actionInterval));
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 new Promise(resolve => setTimeout(resolve, actionInterval));
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.60 ===
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.60'; // Script version
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: 6 Maximum concurrent site processing (1-50, default: 6)
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
- '--disable-background-timer-throttling',
1074
- '--disable-backgrounding-occluded-windows',
1075
- '--disable-renderer-backgrounding',
1076
- '--disable-features=TranslateUI',
1077
- '--disable-features=VizDisplayCompositor',
1078
- '--run-all-compositor-stages-before-draw',
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, 20000)); // Use site timeout or 20s max
1255
- page.setDefaultNavigationTimeout(Math.min(timeout, 25000)); // Use site timeout or 25s max
1256
- // Note: timeout variable from siteConfig.timeout || 30000 is overridden for stability
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
- // load Wait for all resources (default)
2081
- // domcontentloaded Wait for DOM only
2082
- // networkidle0 Wait until 0 network requests for 500ms
2083
- // networkidle2 Wait until ≤2 network requests for 500ms
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 = isFastSite ? 'load' : 'domcontentloaded';
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
- await new Promise(resolve => setTimeout(resolve, 2000)); // Give iframes time to load
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
- // Optimize network idle and delay times for better responsiveness
2238
+ // Aggressive optimization for Puppeteer 22.x responsiveness
2218
2239
  const isFastSite = timeout <= 15000;
2219
- const networkIdleTime = isFastSite ? 4000 : 2000; // Faster idle for slow sites
2220
- const networkIdleTimeout = isFastSite ? timeout : Math.min(timeout / 2, 12000);
2221
- const actualDelay = isFastSite ? delayMs : Math.min(delayMs, 2000); // Cap delay for slow sites
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
- await new Promise(resolve => setTimeout(resolve, actualDelay));
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 || 5000;
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 new Promise(resolve => setTimeout(resolve, additionalDelay));
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 new Promise(resolve => setTimeout(resolve, delayMs));
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 new Promise(resolve => setTimeout(resolve, delayMs));
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
- await new Promise(resolve => setTimeout(resolve, 3000)); // Increased for nettools operations
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 > 5;
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 new Promise(resolve => setTimeout(resolve, 1000));
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 new Promise(resolve => setTimeout(resolve, 2000)); // Give browser time to stabilize
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 new Promise(resolve => setTimeout(resolve, 1000)); // Give filesystem time to sync
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.59",
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": "^23.11.1"
16
+ "puppeteer": ">=20.0.0 <23.0.0"
17
17
  },
18
18
  "keywords": [
19
19
  "puppeteer",