@fanboynz/network-scanner 2.0.25 → 2.0.27

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/README.md CHANGED
@@ -223,7 +223,7 @@ When a page redirects to a new domain, first-party/third-party detection is base
223
223
  | `whois_timeout_multiplier` | Number | `1.5` | Timeout increase multiplier per retry |
224
224
  | `whois_use_fallback` | Boolean | `true` | Add TLD-specific fallback servers |
225
225
  | `whois_retry_on_timeout` | Boolean | `true` | Retry on timeout errors |
226
- | `whois_retry_on_error` | Boolean | `false` | Retry on connection/other errors |
226
+ | `whois_retry_on_error` | Boolean | `true` | Retry on connection/other errors |
227
227
  | `dig` | Array | - | Check dig output for ALL specified terms (AND logic) |
228
228
  | `dig-or` | Array | - | Check dig output for ANY specified term (OR logic) |
229
229
  | `dig_subdomain` | Boolean | `false` | Use subdomain for dig lookup instead of root domain |
@@ -59,7 +59,7 @@ const PRECOMPILED_MOCKS = Object.freeze({
59
59
  postMessage: () => {},
60
60
  disconnect: () => {}
61
61
  }),
62
- getManifest: () => Object.freeze({ name: "Chrome", version: "140.0.0.0" }),
62
+ getManifest: () => Object.freeze({ name: "Chrome", version: "141.0.0.0" }),
63
63
  getURL: (path) => `chrome-extension://invalid/${path}`,
64
64
  id: undefined
65
65
  }),
@@ -91,9 +91,9 @@ const BUILT_IN_PROPERTIES = new Set([
91
91
  // User agent collections with latest versions
92
92
  const USER_AGENT_COLLECTIONS = {
93
93
  chrome: [
94
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36",
95
- "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36",
96
- "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36"
94
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
95
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
96
+ "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"
97
97
  ],
98
98
  firefox: [
99
99
  "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:143.0) Gecko/20100101 Firefox/143.0",
@@ -535,7 +535,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
535
535
  onMessage: { addListener: () => {}, removeListener: () => {} },
536
536
  sendMessage: () => {},
537
537
  connect: () => ({ onMessage: { addListener: () => {}, removeListener: () => {} }, postMessage: () => {}, disconnect: () => {} }),
538
- getManifest: () => ({ name: "Chrome", version: "140.0.0.0" }),
538
+ getManifest: () => ({ name: "Chrome", version: "141.0.0.0" }),
539
539
  getURL: (path) => `chrome-extension://invalid/${path}`,
540
540
  id: undefined
541
541
  },
package/lib/nettools.js CHANGED
@@ -357,7 +357,7 @@ async function whoisLookup(domain, timeout = 10000, whoisServer = null, debugMod
357
357
  * @param {number} whoisDelay - Delay in milliseconds before whois requests (default: 2000)
358
358
  * @returns {Promise<Object>} Object with success status and output/error
359
359
  */
360
- async function whoisLookupWithRetry(domain, timeout = 10000, whoisServer = null, debugMode = false, retryOptions = {}, whoisDelay = 4000, logFunc = null) {
360
+ async function whoisLookupWithRetry(domain, timeout = 10000, whoisServer = null, debugMode = false, retryOptions = {}, whoisDelay = 8000, logFunc = null) {
361
361
  const {
362
362
  maxRetries = 3,
363
363
  timeoutMultiplier = 1.5,
@@ -367,7 +367,6 @@ async function whoisLookupWithRetry(domain, timeout = 10000, whoisServer = null,
367
367
  } = retryOptions;
368
368
 
369
369
  let serversToTry = [];
370
- let currentTimeout = timeout;
371
370
 
372
371
  // Build list of servers to try
373
372
  if (whoisServer) {
@@ -390,88 +389,124 @@ async function whoisLookupWithRetry(domain, timeout = 10000, whoisServer = null,
390
389
  }
391
390
 
392
391
  let lastError = null;
393
- let attemptCount = 0;
392
+ let totalAttempts = 0;
393
+ let serversAttempted = [];
394
394
 
395
395
  if (debugMode) {
396
396
  if (logFunc) {
397
397
  logFunc(`${messageColors.highlight('[whois-retry]')} Starting whois lookup for ${domain} with ${serversToTry.length} server(s) to try`);
398
398
  logFunc(`${messageColors.highlight('[whois-retry]')} Servers: [${serversToTry.map(s => s || 'default').join(', ')}]`);
399
- logFunc(`${messageColors.highlight('[whois-retry]')} Retry settings: maxRetries=${maxRetries}, timeoutMultiplier=${timeoutMultiplier}, retryOnTimeout=${retryOnTimeout}, retryOnError=${retryOnError}`);
399
+ logFunc(`${messageColors.highlight('[whois-retry]')} Retry settings: maxRetries=${maxRetries} per server, timeoutMultiplier=${timeoutMultiplier}, retryOnTimeout=${retryOnTimeout}, retryOnError=${retryOnError}`);
400
400
  } else {
401
401
  console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Starting whois lookup for ${domain} with ${serversToTry.length} server(s) to try`));
402
402
  console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Servers: [${serversToTry.map(s => s || 'default').join(', ')}]`));
403
- console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Retry settings: maxRetries=${maxRetries}, timeoutMultiplier=${timeoutMultiplier}, retryOnTimeout=${retryOnTimeout}, retryOnError=${retryOnError}`));
403
+ console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Retry settings: maxRetries=${maxRetries} per server, timeoutMultiplier=${timeoutMultiplier}, retryOnTimeout=${retryOnTimeout}, retryOnError=${retryOnError}`));
404
404
  }
405
405
  }
406
406
 
407
- for (const server of serversToTry) {
408
- attemptCount++;
407
+ // Try each server with retry logic
408
+ for (let serverIndex = 0; serverIndex < serversToTry.length; serverIndex++) {
409
+ const server = serversToTry[serverIndex];
410
+ let currentTimeout = timeout;
411
+ let retryCount = 0;
412
+ serversAttempted.push(server);
409
413
 
410
414
  if (debugMode) {
411
415
  const serverName = server || 'default';
412
416
  if (logFunc) {
413
- logFunc(`${messageColors.highlight('[whois-retry]')} Attempt ${attemptCount}/${serversToTry.length}: trying server ${serverName} (timeout: ${currentTimeout}ms)`);
417
+ logFunc(`${messageColors.highlight('[whois-retry]')} Server ${serverIndex + 1}/${serversToTry.length}: ${serverName} (max ${maxRetries} attempts)`);
414
418
  } else {
415
- console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Attempt ${attemptCount}/${serversToTry.length}: trying server ${serverName} (timeout: ${currentTimeout}ms)`));
419
+ console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Server ${serverIndex + 1}/${serversToTry.length}: ${serverName} (max ${maxRetries} attempts)`));
416
420
  }
417
421
  }
418
422
 
419
- // Add delay between retry attempts to prevent rate limiting
420
- if (attemptCount > 1) {
421
- if (whoisDelay > 0) {
422
- if (debugMode) {
423
- if (logFunc) {
424
- logFunc(`${messageColors.highlight('[whois-retry]')} Adding ${whoisDelay}ms delay before retry attempt...`);
425
- } else {
426
- console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Adding ${whoisDelay}ms delay before retry attempt...`));
427
- }
428
- }
429
- await new Promise(resolve => setTimeout(resolve, whoisDelay));
430
- }
423
+ // Retry this server up to maxRetries times
424
+ while (retryCount < maxRetries) {
425
+ totalAttempts++;
426
+ const attemptNum = retryCount + 1;
431
427
 
432
- } else if (whoisDelay > 0) {
433
- // Add initial delay on first attempt if configured
434
428
  if (debugMode) {
429
+ const serverName = server || 'default';
435
430
  if (logFunc) {
436
- logFunc(`${messageColors.highlight('[whois-retry]')} Adding ${whoisDelay}ms delay to prevent rate limiting...`);
431
+ logFunc(`${messageColors.highlight('[whois-retry]')} Attempt ${attemptNum}/${maxRetries} on server ${serverName} (timeout: ${currentTimeout}ms)`);
437
432
  } else {
438
- console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Adding ${whoisDelay}ms delay to prevent rate limiting...`));
433
+ console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Attempt ${attemptNum}/${maxRetries} on server ${serverName} (timeout: ${currentTimeout}ms)`));
439
434
  }
440
435
  }
441
- await new Promise(resolve => setTimeout(resolve, whoisDelay));
442
- } else if (debugMode) {
443
- // Log when delay is skipped due to whoisDelay being 0
444
- if (logFunc) {
445
- logFunc(`${messageColors.highlight('[whois-retry]')} Skipping delay (whoisDelay: ${whoisDelay}ms)`);
446
- } else {
447
- console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Skipping delay (whoisDelay: ${whoisDelay}ms)`));
448
- }
449
- }
450
-
451
- try {
452
- const result = await whoisLookup(domain, currentTimeout, server, debugMode, logFunc);
453
436
 
454
- if (result.success) {
437
+ // Add progressive delay between retries (but not before first attempt on any server)
438
+ if (retryCount > 0 && whoisDelay > 0) {
439
+ // Progressive delay: base delay * retry attempt number + extra delay
440
+ // Attempt 2: base delay * 1 + 4000ms = 8000ms + 4000ms = 12000ms
441
+ // Attempt 3: base delay * 2 + 6000ms = 16000ms + 6000ms = 22000ms
442
+ // Attempt 4+: base delay * 3 + 6000ms = 24000ms + 6000ms = 30000ms (if maxRetries > 3)
443
+ const delayMultiplier = Math.min(retryCount, 3);
444
+ const baseDelay = whoisDelay * delayMultiplier;
445
+
446
+ // Add extra delay based on retry attempt
447
+ let extraDelay = 0;
448
+ if (retryCount === 1) {
449
+ extraDelay = 4000; // Extra 4 seconds for 2nd attempt
450
+ } else if (retryCount >= 2) {
451
+ extraDelay = 6000; // Extra 6 seconds for 3rd+ attempts
452
+ }
453
+
454
+ const actualDelay = baseDelay + extraDelay;
455
+
456
+ if (debugMode) {
457
+ if (logFunc) {
458
+ logFunc(`${messageColors.highlight('[whois-retry]')} Adding ${actualDelay}ms progressive delay before retry ${retryCount + 1} (base: ${baseDelay}ms + extra: ${extraDelay}ms)...`);
459
+ } else {
460
+ console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Adding ${actualDelay}ms progressive delay before retry ${retryCount + 1} (base: ${baseDelay}ms + extra: ${extraDelay}ms)...`));
461
+ }
462
+ }
463
+ await new Promise(resolve => setTimeout(resolve, actualDelay));
464
+ } else if (serverIndex > 0 && retryCount === 0 && whoisDelay > 0) {
465
+ // Add delay before trying a new server (but not the very first server)
455
466
  if (debugMode) {
456
467
  if (logFunc) {
457
- logFunc(`${messageColors.highlight('[whois-retry]')} SUCCESS on attempt ${attemptCount}/${serversToTry.length} using server ${result.whoisServer || 'default'}`);
468
+ logFunc(`${messageColors.highlight('[whois-retry]')} Adding ${whoisDelay}ms delay before trying new server...`);
458
469
  } else {
459
- console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} SUCCESS on attempt ${attemptCount}/${serversToTry.length} using server ${result.whoisServer || 'default'}`));
470
+ console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Adding ${whoisDelay}ms delay before trying new server...`));
460
471
  }
461
472
  }
473
+ await new Promise(resolve => setTimeout(resolve, whoisDelay));
474
+ } else if (debugMode && whoisDelay === 0) {
475
+ // Log when delay is skipped due to whoisDelay being 0
476
+ if (logFunc) {
477
+ logFunc(`${messageColors.highlight('[whois-retry]')} Skipping delay (whoisDelay: ${whoisDelay}ms)`);
478
+ } else {
479
+ console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Skipping delay (whoisDelay: ${whoisDelay}ms)`));
480
+ }
481
+ }
482
+
483
+ try {
484
+ const result = await whoisLookup(domain, currentTimeout, server, debugMode, logFunc);
462
485
 
463
- // Add retry info to result
464
- return {
465
- ...result,
466
- retryInfo: {
467
- totalAttempts: attemptCount,
468
- maxAttempts: serversToTry.length,
469
- serversAttempted: serversToTry.slice(0, attemptCount),
470
- finalServer: result.whoisServer,
471
- retriedAfterFailure: attemptCount > 1
486
+ if (result.success) {
487
+ if (debugMode) {
488
+ if (logFunc) {
489
+ logFunc(`${messageColors.highlight('[whois-retry]')} SUCCESS on attempt ${attemptNum}/${maxRetries} for server ${result.whoisServer || 'default'} (total attempts: ${totalAttempts})`);
490
+ } else {
491
+ console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} SUCCESS on attempt ${attemptNum}/${maxRetries} for server ${result.whoisServer || 'default'} (total attempts: ${totalAttempts})`));
492
+ }
472
493
  }
473
- };
474
- } else {
494
+
495
+ // Add retry info to result
496
+ return {
497
+ ...result,
498
+ retryInfo: {
499
+ totalAttempts: totalAttempts,
500
+ maxAttempts: serversToTry.length * maxRetries,
501
+ serversAttempted: serversAttempted,
502
+ finalServer: result.whoisServer,
503
+ retriedAfterFailure: totalAttempts > 1,
504
+ serverRetries: retryCount,
505
+ serverIndex: serverIndex
506
+ }
507
+ };
508
+ }
509
+
475
510
  // Determine if we should retry based on error type
476
511
  const shouldRetry = (result.isTimeout && retryOnTimeout) || (!result.isTimeout && retryOnError);
477
512
 
@@ -479,72 +514,85 @@ async function whoisLookupWithRetry(domain, timeout = 10000, whoisServer = null,
479
514
  const serverName = result.whoisServer || 'default';
480
515
  const errorType = result.isTimeout ? 'TIMEOUT' : 'ERROR';
481
516
  if (logFunc) {
482
- logFunc(`${messageColors.highlight('[whois-retry]')} ${errorType} on attempt ${attemptCount}/${serversToTry.length} with server ${serverName}: ${result.error}`);
517
+ logFunc(`${messageColors.highlight('[whois-retry]')} ${errorType} on attempt ${attemptNum}/${maxRetries} with server ${serverName}: ${result.error}`);
483
518
  } else {
484
- console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} ${errorType} on attempt ${attemptCount}/${serversToTry.length} with server ${serverName}: ${result.error}`));
519
+ console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} ${errorType} on attempt ${attemptNum}/${maxRetries} with server ${serverName}: ${result.error}`));
485
520
  }
486
521
 
487
- if (attemptCount < serversToTry.length) {
522
+ if (retryCount < maxRetries - 1) {
488
523
  if (shouldRetry) {
489
524
  if (logFunc) {
490
- logFunc(`${messageColors.highlight('[whois-retry]')} Will retry with next server...`);
525
+ logFunc(`${messageColors.highlight('[whois-retry]')} Will retry attempt ${attemptNum + 1}/${maxRetries} on same server...`);
491
526
  } else {
492
- console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Will retry with next server...`));
527
+ console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Will retry attempt ${attemptNum + 1}/${maxRetries} on same server...`));
493
528
  }
494
529
  } else {
495
530
  if (logFunc) {
496
- logFunc(`${messageColors.highlight('[whois-retry]')} Skipping retry (retryOn${result.isTimeout ? 'Timeout' : 'Error'}=${shouldRetry})`);
531
+ logFunc(`${messageColors.highlight('[whois-retry]')} Skipping retry on same server (retryOn${result.isTimeout ? 'Timeout' : 'Error'}=${shouldRetry})`);
497
532
  } else {
498
- console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Skipping retry (retryOn${result.isTimeout ? 'Timeout' : 'Error'}=${shouldRetry})`));
533
+ console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Skipping retry on same server (retryOn${result.isTimeout ? 'Timeout' : 'Error'}=${shouldRetry})`));
499
534
  }
500
535
  }
536
+ } else if (serverIndex < serversToTry.length - 1) {
537
+ if (logFunc) {
538
+ logFunc(`${messageColors.highlight('[whois-retry]')} Max retries reached for server, will try next server...`);
539
+ } else {
540
+ console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Max retries reached for server, will try next server...`));
541
+ }
501
542
  }
502
543
  }
503
544
 
504
545
  lastError = result;
505
546
 
506
- // If this is the last server or we shouldn't retry this error type, break
507
- if (attemptCount >= serversToTry.length || !shouldRetry) {
547
+ // If this is the last retry for this server or we shouldn't retry this error type, break to next server
548
+ if (retryCount >= maxRetries - 1 || !shouldRetry) {
508
549
  break;
509
550
  }
510
551
 
511
- // Increase timeout for next attempt
552
+ // Increase timeout for next retry attempt on same server
553
+ retryCount++;
512
554
  currentTimeout = Math.round(currentTimeout * timeoutMultiplier);
513
- }
514
- } catch (error) {
515
- if (debugMode) {
516
- const serverName = server || 'default';
517
- if (logFunc) {
518
- logFunc(`${messageColors.highlight('[whois-retry]')} EXCEPTION on attempt ${attemptCount}/${serversToTry.length} with server ${serverName}: ${error.message}`);
519
- } else {
520
- console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} EXCEPTION on attempt ${attemptCount}/${serversToTry.length} with server ${serverName}: ${error.message}`));
555
+
556
+ } catch (error) {
557
+ if (debugMode) {
558
+ const serverName = server || 'default';
559
+ if (logFunc) {
560
+ logFunc(`${messageColors.highlight('[whois-retry]')} EXCEPTION on attempt ${attemptNum}/${maxRetries} with server ${serverName}: ${error.message}`);
561
+ } else {
562
+ console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} EXCEPTION on attempt ${attemptNum}/${maxRetries} with server ${serverName}: ${error.message}`));
563
+ }
521
564
  }
565
+
566
+ lastError = {
567
+ success: false,
568
+ error: error.message,
569
+ domain: domain,
570
+ whoisServer: server,
571
+ isTimeout: error.message.includes('timeout'),
572
+ duration: 0
573
+ };
574
+
575
+ // For exceptions, only retry if it's a retryable error type
576
+ const isRetryableException = error.message.includes('timeout') ||
577
+ error.message.includes('ECONNRESET') ||
578
+ error.message.includes('ENOTFOUND');
579
+
580
+ if (retryCount >= maxRetries - 1 || !isRetryableException) {
581
+ break;
582
+ }
583
+
584
+ retryCount++;
585
+ currentTimeout = Math.round(currentTimeout * timeoutMultiplier);
522
586
  }
523
-
524
- lastError = {
525
- success: false,
526
- error: error.message,
527
- domain: domain,
528
- whoisServer: server,
529
- isTimeout: error.message.includes('timeout'),
530
- duration: 0
531
- };
532
-
533
- // Continue to next server unless this is the last one
534
- if (attemptCount >= serversToTry.length) {
535
- break;
536
- }
537
-
538
- currentTimeout = Math.round(currentTimeout * timeoutMultiplier);
539
587
  }
540
588
  }
541
589
 
542
590
  // All attempts failed
543
591
  if (debugMode) {
544
592
  if (logFunc) {
545
- logFunc(`${messageColors.highlight('[whois-retry]')} FINAL FAILURE: All ${attemptCount} attempts failed for ${domain}`);
593
+ logFunc(`${messageColors.highlight('[whois-retry]')} FINAL FAILURE: All ${totalAttempts} attempts failed for ${domain} across ${serversAttempted.length} server(s)`);
546
594
  } else {
547
- console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} FINAL FAILURE: All ${attemptCount} attempts failed for ${domain}`));
595
+ console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} FINAL FAILURE: All ${totalAttempts} attempts failed for ${domain} across ${serversAttempted.length} server(s)`));
548
596
  }
549
597
  if (lastError) {
550
598
  if (logFunc) {
@@ -559,11 +607,11 @@ async function whoisLookupWithRetry(domain, timeout = 10000, whoisServer = null,
559
607
  return {
560
608
  ...lastError,
561
609
  retryInfo: {
562
- totalAttempts: attemptCount,
563
- maxAttempts: serversToTry.length,
564
- serversAttempted: serversToTry.slice(0, attemptCount),
610
+ totalAttempts: totalAttempts,
611
+ maxAttempts: serversToTry.length * maxRetries,
612
+ serversAttempted: serversAttempted,
565
613
  finalServer: lastError?.whoisServer || null,
566
- retriedAfterFailure: attemptCount > 1,
614
+ retriedAfterFailure: totalAttempts > 1,
567
615
  allAttemptsFailed: true
568
616
  }
569
617
  };
@@ -1357,4 +1405,4 @@ module.exports = {
1357
1405
  getCommonWhoisServers,
1358
1406
  suggestWhoisServers,
1359
1407
  execWithTimeout // Export for testing
1360
- };
1408
+ };
package/nwss.js CHANGED
@@ -1,4 +1,4 @@
1
- // === Network scanner script (nwss.js) v2.0.25 ===
1
+ // === Network scanner script (nwss.js) v2.0.27 ===
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
@@ -56,7 +56,7 @@ function fastTimeout(ms) {
56
56
  }
57
57
 
58
58
  // --- Configuration Constants ---
59
- const TIMEOUTS = {
59
+ const TIMEOUTS = Object.freeze({
60
60
  DEFAULT_PAGE: 35000, // Standard page load timeout (35s)
61
61
  DEFAULT_NAVIGATION: 25000, // Navigation operation timeout
62
62
  DEFAULT_NAVIGATION_REDUCED: 20000, // Reduced timeout for faster failures
@@ -71,21 +71,32 @@ const TIMEOUTS = {
71
71
  CURL_HANDLER_DELAY: 3000, // Wait for async curl operations
72
72
  PROTOCOL_TIMEOUT: 180000, // Chrome DevTools Protocol timeout
73
73
  REDIRECT_JS_TIMEOUT: 5000 // JavaScript redirect detection timeout
74
- };
74
+ });
75
75
 
76
- const CACHE_LIMITS = {
76
+ const CACHE_LIMITS = Object.freeze({
77
77
  DISK_CACHE_SIZE: 52428800, // 50MB
78
78
  MEDIA_CACHE_SIZE: 52428800, // 50MB
79
79
  DEFAULT_CACHE_PATH: '.cache',
80
80
  DEFAULT_MAX_SIZE: 5000
81
- };
81
+ });
82
82
 
83
- const CONCURRENCY_LIMITS = {
83
+ const CONCURRENCY_LIMITS = Object.freeze({
84
84
  MIN: 1,
85
85
  MAX: 50,
86
86
  DEFAULT: 6,
87
87
  HIGH_CONCURRENCY_THRESHOLD: 12 // Auto-enable aggressive caching above this
88
- };
88
+ });
89
+
90
+ // V8 Optimization: Use Map for user agent lookups instead of object
91
+ const USER_AGENTS = Object.freeze(new Map([
92
+ ['chrome', "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"],
93
+ ['chrome_mac', "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"],
94
+ ['chrome_linux', "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"],
95
+ ['firefox', "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0) Gecko/20100101 Firefox/143.0"],
96
+ ['firefox_mac', "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:142.0) Gecko/20100101 Firefox/143.0"],
97
+ ['firefox_linux', "Mozilla/5.0 (X11; Linux x86_64; rv:142.0) Gecko/20100101 Firefox/143.0"],
98
+ ['safari', "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15"]
99
+ ]));
89
100
 
90
101
  const REALTIME_CLEANUP_THRESHOLD = 8; // Default pages to keep for realtime cleanup
91
102
 
@@ -132,7 +143,7 @@ const { navigateWithRedirectHandling, handleRedirectTimeout } = require('./lib/r
132
143
  const { monitorBrowserHealth, isBrowserHealthy, isQuicklyResponsive, performGroupWindowCleanup, performRealtimeWindowCleanup, trackPageForRealtime, updatePageUsage, cleanupPageBeforeReload } = require('./lib/browserhealth');
133
144
 
134
145
  // --- Script Configuration & Constants ---
135
- const VERSION = '2.0.25'; // Script version
146
+ const VERSION = '2.0.27'; // Script version
136
147
 
137
148
  // get startTime
138
149
  const startTime = Date.now();
@@ -1211,6 +1222,9 @@ function setupFrameHandling(page, forceDebug) {
1211
1222
  '/usr/bin/chromium',
1212
1223
  '/snap/bin/chromium'
1213
1224
  ];
1225
+ // V8 Optimization: Freeze the Chrome paths array since it's constant
1226
+ Object.freeze(systemChromePaths);
1227
+
1214
1228
 
1215
1229
  let executablePath = null;
1216
1230
  for (const chromePath of systemChromePaths) {
@@ -1387,12 +1401,28 @@ function setupFrameHandling(page, forceDebug) {
1387
1401
  * @returns {Promise<object>} A promise that resolves to an object containing scan results.
1388
1402
  */
1389
1403
  async function processUrl(currentUrl, siteConfig, browserInstance) {
1390
- const allowFirstParty = siteConfig.firstParty === true || siteConfig.firstParty === 1;
1391
- const allowThirdParty = siteConfig.thirdParty === undefined || siteConfig.thirdParty === true || siteConfig.thirdParty === 1;
1392
- const perSiteSubDomains = siteConfig.subDomains === 1 ? true : subDomainsMode;
1393
- const siteLocalhostIP = siteConfig.localhost || null;
1394
- const cloudflarePhishBypass = siteConfig.cloudflare_phish === true;
1395
- const cloudflareBypass = siteConfig.cloudflare_bypass === true;
1404
+ // V8 Optimization: Single destructuring to avoid multiple property lookups
1405
+ const {
1406
+ firstParty,
1407
+ thirdParty,
1408
+ subDomains,
1409
+ localhost,
1410
+ cloudflare_phish,
1411
+ cloudflare_bypass,
1412
+ flowproxy_detection,
1413
+ privoxy,
1414
+ pihole,
1415
+ even_blocked,
1416
+ comments,
1417
+ bypass_cache
1418
+ } = siteConfig;
1419
+
1420
+ const allowFirstParty = firstParty === true || firstParty === 1;
1421
+ const allowThirdParty = thirdParty === undefined || thirdParty === true || thirdParty === 1;
1422
+ const perSiteSubDomains = subDomains === 1 ? true : subDomainsMode;
1423
+ const siteLocalhostIP = localhost || null;
1424
+ const cloudflarePhishBypass = cloudflare_phish === true;
1425
+ const cloudflareBypass = cloudflare_bypass === true;
1396
1426
  // Add redirect and same-page loop protection
1397
1427
  const MAX_REDIRECT_DEPTH = siteConfig.max_redirects || 10;
1398
1428
  const redirectHistory = new Set();
@@ -1401,14 +1431,14 @@ function setupFrameHandling(page, forceDebug) {
1401
1431
  const MAX_SAME_PAGE_LOADS = 3;
1402
1432
  let currentPageUrl = currentUrl;
1403
1433
 
1404
- const sitePrivoxy = siteConfig.privoxy === true;
1405
- const sitePihole = siteConfig.pihole === true;
1406
- const flowproxyDetection = siteConfig.flowproxy_detection === true;
1434
+ const sitePrivoxy = privoxy === true;
1435
+ const sitePihole = pihole === true;
1436
+ const flowproxyDetection = flowproxy_detection === true;
1407
1437
 
1408
- const evenBlocked = siteConfig.even_blocked === true;
1438
+ const evenBlocked = even_blocked === true;
1409
1439
  // Log site-level comments if debug mode is enabled
1410
- if (forceDebug && siteConfig.comments) {
1411
- const siteComments = Array.isArray(siteConfig.comments) ? siteConfig.comments : [siteConfig.comments];
1440
+ if (forceDebug && comments) {
1441
+ const siteComments = Array.isArray(comments) ? comments : [comments];
1412
1442
  console.log(formatLogMessage('debug', `Site comments for ${currentUrl}: ${siteComments.length} item(s)`));
1413
1443
  siteComments.forEach((comment, idx) =>
1414
1444
  console.log(formatLogMessage('debug', ` Site comment ${idx + 1}: ${comment}`))
@@ -1416,11 +1446,11 @@ function setupFrameHandling(page, forceDebug) {
1416
1446
  }
1417
1447
 
1418
1448
  // Log bypass_cache setting if enabled
1419
- if (forceDebug && siteConfig.bypass_cache === true) {
1449
+ if (forceDebug && bypass_cache === true) {
1420
1450
  console.log(formatLogMessage('debug', `Cache bypass enabled for all URLs in site: ${currentUrl}`));
1421
1451
  }
1422
1452
 
1423
- if (siteConfig.firstParty === 0 && siteConfig.thirdParty === 0) {
1453
+ if (firstParty === 0 && thirdParty === 0) {
1424
1454
  console.warn(`⚠ Skipping ${currentUrl} because both firstParty and thirdParty are disabled.`);
1425
1455
  return { url: currentUrl, rules: [], success: false, skipped: true };
1426
1456
  }
@@ -1475,14 +1505,14 @@ function setupFrameHandling(page, forceDebug) {
1475
1505
  let finalUrlAfterRedirect = null;
1476
1506
 
1477
1507
  // Enhanced error types for Puppeteer 23.x compatibility
1478
- const CRITICAL_BROWSER_ERRORS = [
1508
+ const CRITICAL_BROWSER_ERRORS = Object.freeze([
1479
1509
  'Protocol error',
1480
1510
  'Target closed',
1481
1511
  'Browser has been closed',
1482
1512
  'Browser protocol broken',
1483
1513
  'Browser process exited',
1484
1514
  'Browser disconnected'
1485
- ];
1515
+ ]);
1486
1516
 
1487
1517
  try {
1488
1518
 
@@ -1907,29 +1937,30 @@ function setupFrameHandling(page, forceDebug) {
1907
1937
 
1908
1938
  // Client Hints protection for Chrome user agents
1909
1939
  if (siteConfig.userAgent && siteConfig.userAgent.toLowerCase().includes('chrome')) {
1940
+ const userAgentKey = siteConfig.userAgent.toLowerCase();
1910
1941
  let platform = 'Windows';
1911
1942
  let platformVersion = '15.0.0';
1912
1943
  let arch = 'x86';
1913
1944
 
1914
- if (siteConfig.userAgent.toLowerCase() === 'chrome_mac') {
1945
+ if (userAgentKey === 'chrome_mac') {
1915
1946
  platform = 'macOS';
1916
- platformVersion = '13.5.0';
1947
+ platformVersion = '13.5.0';
1917
1948
  arch = 'arm';
1918
- } else if (siteConfig.userAgent.toLowerCase() === 'chrome_linux') {
1949
+ } else if (userAgentKey === 'chrome_linux') {
1919
1950
  platform = 'Linux';
1920
1951
  platformVersion = '6.5.0';
1921
1952
  arch = 'x86';
1922
1953
  }
1923
-
1954
+
1924
1955
  await page.setExtraHTTPHeaders({
1925
- 'Sec-CH-UA': '"Chromium";v="140", "Not=A?Brand";v="24", "Google Chrome";v="140"',
1956
+ 'Sec-CH-UA': '"Chromium";v="141", "Not=A?Brand";v="24", "Google Chrome";v="141"',
1926
1957
  'Sec-CH-UA-Platform': `"${platform}"`,
1927
1958
  'Sec-CH-UA-Platform-Version': `"${platformVersion}"`,
1928
1959
  'Sec-CH-UA-Mobile': '?0',
1929
1960
  'Sec-CH-UA-Arch': `"${arch}"`,
1930
1961
  'Sec-CH-UA-Bitness': '"64"',
1931
- 'Sec-CH-UA-Full-Version': '"140.0.7339.208"',
1932
- 'Sec-CH-UA-Full-Version-List': '"Chromium";v="140.0.7339.208", "Not=A?Brand";v="24.0.0.0", "Google Chrome";v="140.0.7339.208"'
1962
+ 'Sec-CH-UA-Full-Version': '"141.0.7390.55"',
1963
+ 'Sec-CH-UA-Full-Version-List': '"Chromium";v="141.0.7390.55", "Not=A?Brand";v="24.0.0.0", "Google Chrome";v="141.0.7390.55"'
1933
1964
  });
1934
1965
  }
1935
1966
  } catch (fingerprintErr) {
@@ -1959,16 +1990,7 @@ function setupFrameHandling(page, forceDebug) {
1959
1990
  // Get user agent for curl if needed
1960
1991
  let curlUserAgent = '';
1961
1992
  if (useCurl && siteConfig.userAgent) {
1962
- const userAgents = {
1963
- chrome: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36",
1964
- chrome_mac: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36",
1965
- chrome_linux: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36",
1966
- firefox: "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0) Gecko/20100101 Firefox/143.0",
1967
- firefox_mac: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:142.0) Gecko/20100101 Firefox/143.0",
1968
- firefox_linux: "Mozilla/5.0 (X11; Linux x86_64; rv:142.0) Gecko/20100101 Firefox/143.0",
1969
- safari: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15"
1970
- };
1971
- curlUserAgent = userAgents[siteConfig.userAgent.toLowerCase()] || '';
1993
+ curlUserAgent = USER_AGENTS.get(siteConfig.userAgent.toLowerCase()) || '';
1972
1994
  }
1973
1995
 
1974
1996
  if (useCurl && forceDebug) {
@@ -3487,20 +3509,29 @@ function setupFrameHandling(page, forceDebug) {
3487
3509
  // Temporarily store the pLimit function
3488
3510
  const originalLimit = limit;
3489
3511
 
3490
- // Create a flat list of all URL tasks with their site configs for true concurrency
3491
- const allTasks = [];
3512
+ // V8 Optimization: Calculate total URLs first to pre-allocate array
3513
+ let totalUrls = 0;
3492
3514
  for (const site of sites) {
3493
3515
  const urlsToProcess = Array.isArray(site.url) ? site.url : [site.url];
3494
- urlsToProcess.forEach(url => {
3495
- allTasks.push({
3516
+ totalUrls += urlsToProcess.length;
3517
+ }
3518
+
3519
+ // Pre-allocate array with exact size to prevent multiple reallocations
3520
+ const allTasks = new Array(totalUrls);
3521
+ let taskIndex = 0;
3522
+
3523
+ // Populate the pre-allocated array
3524
+ for (const site of sites) {
3525
+ const urlsToProcess = Array.isArray(site.url) ? site.url : [site.url];
3526
+ for (const url of urlsToProcess) {
3527
+ allTasks[taskIndex++] = {
3496
3528
  url,
3497
3529
  config: { ...site, _originalUrl: url }, // Preserve original URL for CDP domain checking
3498
- taskId: allTasks.length // For tracking
3499
- });
3500
- });
3530
+ taskId: taskIndex - 1 // For tracking
3531
+ };
3532
+ }
3501
3533
  }
3502
-
3503
- const totalUrls = allTasks.length;
3534
+
3504
3535
 
3505
3536
  let results = [];
3506
3537
  let processedUrlCount = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fanboynz/network-scanner",
3
- "version": "2.0.25",
3
+ "version": "2.0.27",
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": {