@fanboynz/network-scanner 1.0.44 → 1.0.45

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
@@ -52,6 +52,47 @@ function getModuleInfo() {
52
52
  };
53
53
  }
54
54
 
55
+ /**
56
+ * Validates if a URL should be processed by Cloudflare protection
57
+ * Only allows HTTP/HTTPS URLs, skips browser-internal and special protocols
58
+ * @param {string} url - URL to validate
59
+ * @param {boolean} forceDebug - Debug logging flag
60
+ * @returns {boolean} True if URL should be processed
61
+ */
62
+ function shouldProcessUrl(url, forceDebug = false) {
63
+ if (!url || typeof url !== 'string') {
64
+ if (forceDebug) console.log(`[cloudflare][url-validation] Skipping invalid URL: ${url}`);
65
+ return false;
66
+ }
67
+
68
+ // Skip browser-internal and special protocol URLs
69
+ const skipPatterns = [
70
+ 'about:', 'chrome:', 'chrome-extension:', 'chrome-error:', 'chrome-search:',
71
+ 'devtools:', 'edge:', 'moz-extension:', 'safari-extension:', 'webkit:',
72
+ 'data:', 'blob:', 'javascript:', 'vbscript:', 'file:', 'ftp:', 'ftps:'
73
+ ];
74
+
75
+ const urlLower = url.toLowerCase();
76
+ for (const pattern of skipPatterns) {
77
+ if (urlLower.startsWith(pattern)) {
78
+ if (forceDebug) {
79
+ console.log(`[cloudflare][url-validation] Skipping ${pattern} URL: ${url.substring(0, 100)}${url.length > 100 ? '...' : ''}`);
80
+ }
81
+ return false;
82
+ }
83
+ }
84
+
85
+ // Only process HTTP/HTTPS URLs
86
+ if (!urlLower.startsWith('http://') && !urlLower.startsWith('https://')) {
87
+ if (forceDebug) {
88
+ console.log(`[cloudflare][url-validation] Skipping non-HTTP(S) URL: ${url.substring(0, 100)}${url.length > 100 ? '...' : ''}`);
89
+ }
90
+ return false;
91
+ }
92
+
93
+ return true;
94
+ }
95
+
55
96
  /**
56
97
  * Cross-version compatible timeout function for Puppeteer with timeout protection
57
98
  */
@@ -139,6 +180,18 @@ async function safeWaitForNavigation(page, timeout = TIMEOUTS.NAVIGATION_TIMEOUT
139
180
  */
140
181
  async function quickCloudflareDetection(page, forceDebug = false) {
141
182
  try {
183
+ // Get current page URL and validate it
184
+ const currentPageUrl = await page.url();
185
+
186
+ if (!shouldProcessUrl(currentPageUrl, forceDebug)) {
187
+ if (forceDebug) {
188
+ console.log(`[debug][cloudflare] Quick detection skipping non-HTTP(S) page: ${currentPageUrl}`);
189
+ }
190
+ return { hasIndicators: false, skippedInvalidUrl: true };
191
+ }
192
+
193
+ // Continue with existing detection logic only for valid HTTP(S) URLs
194
+
142
195
  const quickCheck = await safePageEvaluate(page, () => {
143
196
  const title = document.title || '';
144
197
  const bodyText = document.body ? document.body.textContent.substring(0, 500) : '';
@@ -813,6 +866,21 @@ async function handleCloudflareProtection(page, currentUrl, siteConfig, forceDeb
813
866
  if (forceDebug) {
814
867
  console.log(`[debug][cloudflare] Using Cloudflare module v${CLOUDFLARE_MODULE_VERSION} for ${currentUrl}`);
815
868
  }
869
+
870
+ // VALIDATE URL FIRST - Skip protection handling for non-HTTP(S) URLs
871
+ if (!shouldProcessUrl(currentUrl, forceDebug)) {
872
+ if (forceDebug) {
873
+ console.log(`[debug][cloudflare] Skipping protection handling for non-HTTP(S) URL: ${currentUrl}`);
874
+ }
875
+ return {
876
+ phishingWarning: { attempted: false, success: true },
877
+ verificationChallenge: { attempted: false, success: true },
878
+ overallSuccess: true,
879
+ errors: [],
880
+ skippedInvalidUrl: true
881
+ };
882
+ }
883
+
816
884
  // Quick detection first - exit early if no Cloudflare detected and no explicit config
817
885
  const quickDetection = await quickCloudflareDetection(page, forceDebug);
818
886
 
package/lib/flowproxy.js CHANGED
@@ -1,46 +1,176 @@
1
1
  /**
2
2
  * FlowProxy protection detection and handling module
3
+ * Version: 1.0.0 - Enhanced with comprehensive documentation and smart detection
3
4
  * Detects flowProxy DDoS protection and handles it appropriately for security scanning
5
+ *
6
+ * FlowProxy (by Aurologic) is a DDoS protection service similar to Cloudflare that:
7
+ * - Implements rate limiting and browser verification
8
+ * - Uses JavaScript challenges to verify legitimate browsers
9
+ * - Can block automated tools and scrapers
10
+ * - Requires specific handling for security scanning tools
4
11
  */
5
12
 
6
13
  /**
7
- * Cross-version compatible timeout function for Puppeteer
14
+ * Module version information
15
+ */
16
+ const FLOWPROXY_MODULE_VERSION = '1.0.0';
17
+
18
+ /**
19
+ * Timeout constants for FlowProxy operations (in milliseconds)
20
+ */
21
+ const TIMEOUTS = {
22
+ PAGE_LOAD_WAIT: 2000, // Initial wait for page to load
23
+ JS_CHALLENGE_DEFAULT: 15000, // Default JavaScript challenge timeout
24
+ RATE_LIMIT_DEFAULT: 30000, // Default rate limit delay
25
+ ADDITIONAL_DELAY_DEFAULT: 5000, // Default additional processing delay
26
+ PAGE_TIMEOUT_DEFAULT: 45000, // Default page timeout
27
+ NAVIGATION_TIMEOUT_DEFAULT: 45000, // Default navigation timeout
28
+ FALLBACK_TIMEOUT: 5000 // Fallback timeout for failed operations
29
+ };
30
+
31
+ /**
32
+ * Gets module version information
33
+ * @returns {object} Version information object
34
+ */
35
+ function getModuleInfo() {
36
+ return {
37
+ version: FLOWPROXY_MODULE_VERSION,
38
+ name: 'FlowProxy Protection Handler'
39
+ };
40
+ }
41
+
42
+ /**
43
+ * Validates if a URL should be processed by FlowProxy protection
44
+ * Only allows HTTP/HTTPS URLs, skips browser-internal and special protocols
45
+ *
46
+ * @param {string} url - URL to validate
47
+ * @param {boolean} forceDebug - Debug logging flag
48
+ * @returns {boolean} True if URL should be processed
49
+ *
50
+ * @example
51
+ * // Valid URLs that will be processed
52
+ * shouldProcessUrl('https://example.com') // => true
53
+ * shouldProcessUrl('http://test.com') // => true
54
+ *
55
+ * // Invalid URLs that will be skipped
56
+ * shouldProcessUrl('chrome://settings') // => false
57
+ * shouldProcessUrl('about:blank') // => false
58
+ * shouldProcessUrl('file:///local/file.html') // => false
59
+ */
60
+ function shouldProcessUrl(url, forceDebug = false) {
61
+ if (!url || typeof url !== 'string') {
62
+ if (forceDebug) console.log(`[flowproxy][url-validation] Skipping invalid URL: ${url}`);
63
+ return false;
64
+ }
65
+
66
+ // Skip browser-internal and special protocol URLs
67
+ // These protocols are not relevant for FlowProxy protection
68
+ const skipPatterns = [
69
+ 'about:', 'chrome:', 'chrome-extension:', 'chrome-error:', 'chrome-search:',
70
+ 'devtools:', 'edge:', 'moz-extension:', 'safari-extension:', 'webkit:',
71
+ 'data:', 'blob:', 'javascript:', 'vbscript:', 'file:', 'ftp:', 'ftps:'
72
+ ];
73
+
74
+ const urlLower = url.toLowerCase();
75
+ for (const pattern of skipPatterns) {
76
+ if (urlLower.startsWith(pattern)) {
77
+ if (forceDebug) {
78
+ console.log(`[flowproxy][url-validation] Skipping ${pattern} URL: ${url.substring(0, 100)}${url.length > 100 ? '...' : ''}`);
79
+ }
80
+ return false;
81
+ }
82
+ }
83
+
84
+ // Only process HTTP/HTTPS URLs - FlowProxy only protects web traffic
85
+ if (!urlLower.startsWith('http://') && !urlLower.startsWith('https://')) {
86
+ if (forceDebug) {
87
+ console.log(`[flowproxy][url-validation] Skipping non-HTTP(S) URL: ${url.substring(0, 100)}${url.length > 100 ? '...' : ''}`);
88
+ }
89
+ return false;
90
+ }
91
+
92
+ return true;
93
+ }
94
+
95
+ /**
96
+ * Cross-version compatible timeout function for Puppeteer with timeout protection
97
+ * Handles different Puppeteer versions that may have different timeout methods
98
+ *
8
99
  * @param {import('puppeteer').Page} page - Puppeteer page instance
9
100
  * @param {number} timeout - Timeout in milliseconds
10
101
  * @returns {Promise<void>}
102
+ *
103
+ * @example
104
+ * // Wait for 5 seconds
105
+ * await waitForTimeout(page, 5000);
11
106
  */
12
107
  async function waitForTimeout(page, timeout) {
13
108
  try {
109
+ // Try newer Puppeteer method first (v1.4.0+)
14
110
  if (typeof page.waitForTimeout === 'function') {
15
111
  await page.waitForTimeout(timeout);
16
112
  } else if (typeof page.waitFor === 'function') {
113
+ // Fallback for older Puppeteer versions
17
114
  await page.waitFor(timeout);
18
115
  } else {
116
+ // Final fallback - use standard setTimeout
19
117
  await new Promise(resolve => setTimeout(resolve, timeout));
20
118
  }
21
119
  } catch (error) {
120
+ // If all else fails, use setTimeout
22
121
  await new Promise(resolve => setTimeout(resolve, timeout));
23
122
  }
24
123
  }
25
124
 
26
125
  /**
27
- * Analyzes the current page to detect flowProxy protection
126
+ * Analyzes the current page to detect flowProxy protection with comprehensive detection logic
127
+ *
128
+ * FlowProxy protection typically manifests as:
129
+ * - DDoS protection pages with "Please wait" messages
130
+ * - Rate limiting responses (429 errors)
131
+ * - JavaScript challenges that must complete before access
132
+ * - Aurologic branding and flowproxy-specific elements
133
+ * - Browser verification processes
134
+ *
28
135
  * @param {import('puppeteer').Page} page - Puppeteer page instance
29
- * @returns {Promise<object>} Detection information object
136
+ * @returns {Promise<object>} Detection information object with detailed analysis
137
+ *
138
+ * @example
139
+ * const analysis = await analyzeFlowProxyProtection(page);
140
+ * if (analysis.isFlowProxyDetected) {
141
+ * console.log(`FlowProxy protection found: ${analysis.title}`);
142
+ * if (analysis.isRateLimited) {
143
+ * console.log('Rate limiting is active');
144
+ * }
145
+ * }
30
146
  */
31
147
  async function analyzeFlowProxyProtection(page) {
32
148
  try {
149
+ // Get current page URL and validate it first
150
+ const currentPageUrl = await page.url();
151
+
152
+ if (!shouldProcessUrl(currentPageUrl, false)) {
153
+ return {
154
+ isFlowProxyDetected: false,
155
+ skippedInvalidUrl: true,
156
+ url: currentPageUrl
157
+ };
158
+ }
159
+
160
+ // Continue with comprehensive FlowProxy detection for valid HTTP(S) URLs
33
161
  return await page.evaluate(() => {
34
162
  const title = document.title || '';
35
163
  const bodyText = document.body ? document.body.textContent : '';
36
164
  const url = window.location.href;
37
165
 
38
- // Check for flowProxy/aurologic specific indicators
166
+ // Check for flowProxy/aurologic specific domain indicators
167
+ // FlowProxy services often redirect to aurologic domains or use flowproxy subdomains
39
168
  const hasFlowProxyDomain = url.includes('aurologic') ||
40
169
  url.includes('flowproxy') ||
41
170
  url.includes('ddos-protection');
42
171
 
43
172
  // Check for flowProxy challenge page indicators
173
+ // These are common titles and text patterns used by FlowProxy protection pages
44
174
  const hasProtectionPage = title.includes('DDoS Protection') ||
45
175
  title.includes('Please wait') ||
46
176
  title.includes('Checking your browser') ||
@@ -48,18 +178,21 @@ async function analyzeFlowProxyProtection(page) {
48
178
  bodyText.includes('flowProxy') ||
49
179
  bodyText.includes('Verifying your browser');
50
180
 
51
- // Check for specific flowProxy elements
181
+ // Check for specific flowProxy DOM elements
182
+ // FlowProxy typically adds custom data attributes and CSS classes
52
183
  const hasFlowProxyElements = document.querySelector('[data-flowproxy]') !== null ||
53
184
  document.querySelector('.flowproxy-challenge') !== null ||
54
185
  document.querySelector('#flowproxy-container') !== null ||
55
186
  document.querySelector('.aurologic-protection') !== null;
56
187
 
57
188
  // Check for challenge indicators
189
+ // FlowProxy uses various elements to indicate active challenges
58
190
  const hasChallengeElements = document.querySelector('.challenge-running') !== null ||
59
191
  document.querySelector('.verification-container') !== null ||
60
192
  document.querySelector('input[name="flowproxy-response"]') !== null;
61
193
 
62
194
  // Check for rate limiting indicators
195
+ // Rate limiting is a common FlowProxy feature that shows specific messages
63
196
  const isRateLimited = bodyText.includes('Rate limited') ||
64
197
  bodyText.includes('Too many requests') ||
65
198
  bodyText.includes('Please try again later') ||
@@ -67,17 +200,20 @@ async function analyzeFlowProxyProtection(page) {
67
200
  title.includes('Rate Limit');
68
201
 
69
202
  // Check for JavaScript challenge indicators
203
+ // FlowProxy often requires JavaScript to be enabled and uses specific scripts
70
204
  const hasJSChallenge = document.querySelector('script[src*="flowproxy"]') !== null ||
71
205
  document.querySelector('script[src*="aurologic"]') !== null ||
72
206
  bodyText.includes('JavaScript is required') ||
73
207
  bodyText.includes('Please enable JavaScript');
74
208
 
75
209
  // Check for loading/processing indicators
210
+ // FlowProxy shows these while performing browser verification
76
211
  const isProcessing = bodyText.includes('Processing') ||
77
212
  bodyText.includes('Loading') ||
78
213
  document.querySelector('.loading-spinner') !== null ||
79
214
  document.querySelector('.processing-indicator') !== null;
80
215
 
216
+ // Main detection logic - any of these primary indicators suggest FlowProxy presence
81
217
  const isFlowProxyDetected = hasFlowProxyDomain ||
82
218
  hasProtectionPage ||
83
219
  hasFlowProxyElements ||
@@ -98,6 +234,7 @@ async function analyzeFlowProxyProtection(page) {
98
234
  };
99
235
  });
100
236
  } catch (error) {
237
+ // Return safe defaults if page evaluation fails
101
238
  return {
102
239
  isFlowProxyDetected: false,
103
240
  hasFlowProxyDomain: false,
@@ -114,13 +251,69 @@ async function analyzeFlowProxyProtection(page) {
114
251
 
115
252
  /**
116
253
  * Handles flowProxy protection by implementing appropriate delays and retry logic
254
+ *
255
+ * FlowProxy handling strategy:
256
+ * 1. Detect protection type (rate limiting, JS challenge, etc.)
257
+ * 2. Implement appropriate delays based on protection type
258
+ * 3. Wait for JavaScript challenges to complete
259
+ * 4. Verify successful bypass before continuing
260
+ *
117
261
  * @param {import('puppeteer').Page} page - Puppeteer page instance
118
262
  * @param {string} currentUrl - Current URL being processed
119
- * @param {object} siteConfig - Site configuration object
120
- * @param {boolean} forceDebug - Debug mode flag
121
- * @returns {Promise<object>} Result object with handling details
263
+ * @param {object} siteConfig - Site configuration object with FlowProxy settings
264
+ * @param {boolean} forceDebug - Debug mode flag for detailed logging
265
+ *
266
+ * @returns {Promise<object>} Result object with comprehensive handling details:
267
+ * {
268
+ * flowProxyDetection: {
269
+ * attempted: boolean, // Whether detection was attempted
270
+ * detected: boolean, // Whether FlowProxy protection was found
271
+ * details: object|null // Detailed detection information
272
+ * },
273
+ * handlingResult: {
274
+ * attempted: boolean, // Whether handling was attempted
275
+ * success: boolean // Whether handling succeeded
276
+ * },
277
+ * overallSuccess: boolean, // True if no critical failures occurred
278
+ * errors: string[], // Array of error messages
279
+ * warnings: string[], // Array of warning messages
280
+ * skippedInvalidUrl: boolean // True if URL was skipped due to invalid protocol
281
+ * }
282
+ *
283
+ * @example
284
+ * const config = {
285
+ * flowproxy_delay: 45000, // Rate limit delay (45 seconds)
286
+ * flowproxy_js_timeout: 20000, // JS challenge timeout (20 seconds)
287
+ * flowproxy_additional_delay: 8000 // Additional processing delay (8 seconds)
288
+ * };
289
+ *
290
+ * const result = await handleFlowProxyProtection(page, url, config, true);
291
+ * if (result.flowProxyDetection.detected) {
292
+ * console.log('FlowProxy protection handled');
293
+ * if (result.warnings.length > 0) {
294
+ * console.log('Warnings:', result.warnings);
295
+ * }
296
+ * }
122
297
  */
123
298
  async function handleFlowProxyProtection(page, currentUrl, siteConfig, forceDebug = false) {
299
+
300
+ // VALIDATE URL FIRST - Skip protection handling for non-HTTP(S) URLs
301
+ // FlowProxy only protects web traffic, so other protocols should be skipped
302
+ if (!shouldProcessUrl(currentUrl, forceDebug)) {
303
+ if (forceDebug) {
304
+ console.log(`[debug][flowproxy] Skipping protection handling for non-HTTP(S) URL: ${currentUrl}`);
305
+ }
306
+ return {
307
+ flowProxyDetection: { attempted: false, detected: false },
308
+ handlingResult: { attempted: false, success: true },
309
+ overallSuccess: true,
310
+ errors: [],
311
+ warnings: [],
312
+ skippedInvalidUrl: true
313
+ };
314
+ }
315
+
316
+ // Initialize result structure for tracking all handling aspects
124
317
  const result = {
125
318
  flowProxyDetection: { attempted: false, detected: false },
126
319
  handlingResult: { attempted: false, success: false },
@@ -132,9 +325,11 @@ async function handleFlowProxyProtection(page, currentUrl, siteConfig, forceDebu
132
325
  try {
133
326
  if (forceDebug) console.log(`[debug][flowproxy] Checking for flowProxy protection on ${currentUrl}`);
134
327
 
135
- // Wait a moment for the page to load
136
- await waitForTimeout(page, 2000);
328
+ // Wait for initial page load before analyzing
329
+ // FlowProxy protection pages need time to fully render their elements
330
+ await waitForTimeout(page, TIMEOUTS.PAGE_LOAD_WAIT);
137
331
 
332
+ // Perform comprehensive FlowProxy detection
138
333
  const detectionInfo = await analyzeFlowProxyProtection(page);
139
334
  result.flowProxyDetection = {
140
335
  attempted: true,
@@ -142,6 +337,7 @@ async function handleFlowProxyProtection(page, currentUrl, siteConfig, forceDebu
142
337
  details: detectionInfo
143
338
  };
144
339
 
340
+ // Only proceed with handling if FlowProxy protection is detected
145
341
  if (detectionInfo.isFlowProxyDetected) {
146
342
  result.handlingResult.attempted = true;
147
343
 
@@ -153,23 +349,28 @@ async function handleFlowProxyProtection(page, currentUrl, siteConfig, forceDebu
153
349
  console.log(`[debug][flowproxy] Has Challenge Elements: ${detectionInfo.hasChallengeElements}`);
154
350
  console.log(`[debug][flowproxy] Is Rate Limited: ${detectionInfo.isRateLimited}`);
155
351
  console.log(`[debug][flowproxy] Has JS Challenge: ${detectionInfo.hasJSChallenge}`);
352
+ console.log(`[debug][flowproxy] Is Processing: ${detectionInfo.isProcessing}`);
353
+ console.log(`[debug][flowproxy] Body Snippet: "${detectionInfo.bodySnippet}"`);
156
354
  }
157
355
 
158
- // Handle rate limiting
356
+ // HANDLE RATE LIMITING - Highest priority as it blocks all requests
357
+ // Rate limiting requires waiting before any other actions
159
358
  if (detectionInfo.isRateLimited) {
160
- const rateLimitDelay = siteConfig.flowproxy_delay || 30000; // 30 second default
359
+ const rateLimitDelay = siteConfig.flowproxy_delay || TIMEOUTS.RATE_LIMIT_DEFAULT;
161
360
  result.warnings.push(`Rate limiting detected - implementing ${rateLimitDelay}ms delay`);
162
361
  if (forceDebug) console.log(`[debug][flowproxy] Rate limiting detected, waiting ${rateLimitDelay}ms`);
163
362
  await waitForTimeout(page, rateLimitDelay);
164
363
  }
165
364
 
166
- // Handle JavaScript challenges by waiting for completion
365
+ // HANDLE JAVASCRIPT CHALLENGES - Second priority as they must complete
366
+ // FlowProxy uses JS challenges to verify browser legitimacy
167
367
  if (detectionInfo.hasJSChallenge || detectionInfo.isProcessing) {
168
- const jsWaitTime = siteConfig.flowproxy_js_timeout || 15000; // 15 second default
368
+ const jsWaitTime = siteConfig.flowproxy_js_timeout || TIMEOUTS.JS_CHALLENGE_DEFAULT;
169
369
  if (forceDebug) console.log(`[debug][flowproxy] JavaScript challenge detected, waiting up to ${jsWaitTime}ms for completion`);
170
370
 
171
371
  try {
172
- // Wait for challenge to complete or timeout
372
+ // Wait for challenge completion indicators to disappear
373
+ // These conditions indicate the JS challenge has finished
173
374
  await page.waitForFunction(
174
375
  () => {
175
376
  const bodyText = document.body ? document.body.textContent : '';
@@ -184,41 +385,48 @@ async function handleFlowProxyProtection(page, currentUrl, siteConfig, forceDebu
184
385
 
185
386
  if (forceDebug) console.log(`[debug][flowproxy] JavaScript challenge appears to have completed`);
186
387
  } catch (timeoutErr) {
388
+ // Continue even if timeout occurs - some challenges may take longer
187
389
  result.warnings.push(`JavaScript challenge timeout after ${jsWaitTime}ms`);
188
390
  if (forceDebug) console.log(`[debug][flowproxy] JavaScript challenge timeout - continuing anyway`);
189
391
  }
190
392
  }
191
393
 
192
- // Implement additional delay for flowProxy processing
193
- const additionalDelay = siteConfig.flowproxy_additional_delay || 5000; // 5 second default
394
+ // IMPLEMENT ADDITIONAL DELAY - Final step to ensure all processing completes
395
+ // FlowProxy may need extra time even after challenges complete
396
+ const additionalDelay = siteConfig.flowproxy_additional_delay || TIMEOUTS.ADDITIONAL_DELAY_DEFAULT;
194
397
  if (forceDebug) console.log(`[debug][flowproxy] Implementing additional ${additionalDelay}ms delay for flowProxy processing`);
195
398
  await waitForTimeout(page, additionalDelay);
196
399
 
197
- // Check if we're still on a protection page
400
+ // VERIFY SUCCESSFUL BYPASS - Check if we're still on a protection page
401
+ // This helps identify if our handling was successful
198
402
  const finalCheck = await analyzeFlowProxyProtection(page);
199
403
  if (finalCheck.isFlowProxyDetected && finalCheck.hasProtectionPage) {
200
404
  result.warnings.push('Still on flowProxy protection page after handling attempts');
201
405
  if (forceDebug) console.log(`[debug][flowproxy] Warning: Still appears to be on protection page`);
406
+ // Don't mark as failure - protection page may persist but still allow access
202
407
  } else {
203
408
  result.handlingResult.success = true;
204
409
  if (forceDebug) console.log(`[debug][flowproxy] Successfully handled flowProxy protection for ${currentUrl}`);
205
410
  }
206
411
 
207
412
  } else {
413
+ // No FlowProxy protection detected - mark as successful (nothing to handle)
208
414
  if (forceDebug) console.log(`[debug][flowproxy] No flowProxy protection detected on ${currentUrl}`);
209
- result.overallSuccess = true; // No protection to handle
415
+ result.overallSuccess = true;
210
416
  }
211
417
 
212
418
  } catch (error) {
419
+ // Critical error occurred during handling
213
420
  result.errors.push(`FlowProxy handling error: ${error.message}`);
214
421
  result.overallSuccess = false;
215
422
  if (forceDebug) {
216
423
  console.log(`[debug][flowproxy] FlowProxy handling failed for ${currentUrl}:`);
217
424
  console.log(`[debug][flowproxy] Error: ${error.message}`);
425
+ console.log(`[debug][flowproxy] Stack: ${error.stack}`);
218
426
  }
219
427
  }
220
428
 
221
- // Log overall result
429
+ // LOG COMPREHENSIVE RESULTS for debugging and monitoring
222
430
  if (result.errors.length > 0 && forceDebug) {
223
431
  console.log(`[debug][flowproxy] FlowProxy handling completed with errors for ${currentUrl}:`);
224
432
  result.errors.forEach(error => {
@@ -237,38 +445,61 @@ async function handleFlowProxyProtection(page, currentUrl, siteConfig, forceDebu
237
445
  }
238
446
 
239
447
  /**
240
- * Checks if the current page might be behind flowProxy protection
448
+ * Quick check to determine if the current page might be behind flowProxy protection
449
+ * This is a lightweight alternative to full analysis for simple detection needs
450
+ *
241
451
  * @param {import('puppeteer').Page} page - Puppeteer page instance
242
452
  * @returns {Promise<boolean>} True if flowProxy protection is suspected
453
+ *
454
+ * @example
455
+ * if (await isFlowProxyProtected(page)) {
456
+ * console.log('FlowProxy protection detected - implementing handling');
457
+ * await handleFlowProxyProtection(page, url, config);
458
+ * }
243
459
  */
244
460
  async function isFlowProxyProtected(page) {
245
461
  try {
246
462
  const detection = await analyzeFlowProxyProtection(page);
247
463
  return detection.isFlowProxyDetected;
248
464
  } catch (error) {
465
+ // Return false if detection fails - assume no protection
249
466
  return false;
250
467
  }
251
468
  }
252
469
 
253
470
  /**
254
471
  * Gets recommended timeout values for flowProxy protected sites
255
- * @param {object} siteConfig - Site configuration object
256
- * @returns {object} Recommended timeout values
472
+ * Provides sensible defaults while allowing site-specific customization
473
+ *
474
+ * @param {object} siteConfig - Site configuration object with optional FlowProxy settings
475
+ * @returns {object} Recommended timeout values for FlowProxy handling
476
+ *
477
+ * @example
478
+ * const timeouts = getFlowProxyTimeouts({
479
+ * flowproxy_delay: 60000, // Custom rate limit delay
480
+ * flowproxy_js_timeout: 25000 // Custom JS challenge timeout
481
+ * });
482
+ *
483
+ * // Use timeouts in page operations
484
+ * await page.goto(url, { timeout: timeouts.pageTimeout });
257
485
  */
258
486
  function getFlowProxyTimeouts(siteConfig) {
259
487
  return {
260
- pageTimeout: siteConfig.flowproxy_page_timeout || 45000, // 45 seconds
261
- navigationTimeout: siteConfig.flowproxy_nav_timeout || 45000, // 45 seconds
262
- challengeTimeout: siteConfig.flowproxy_js_timeout || 15000, // 15 seconds
263
- rateLimit: siteConfig.flowproxy_delay || 30000, // 30 seconds
264
- additionalDelay: siteConfig.flowproxy_additional_delay || 5000 // 5 seconds
488
+ pageTimeout: siteConfig.flowproxy_page_timeout || TIMEOUTS.PAGE_TIMEOUT_DEFAULT,
489
+ navigationTimeout: siteConfig.flowproxy_nav_timeout || TIMEOUTS.NAVIGATION_TIMEOUT_DEFAULT,
490
+ challengeTimeout: siteConfig.flowproxy_js_timeout || TIMEOUTS.JS_CHALLENGE_DEFAULT,
491
+ rateLimit: siteConfig.flowproxy_delay || TIMEOUTS.RATE_LIMIT_DEFAULT,
492
+ additionalDelay: siteConfig.flowproxy_additional_delay || TIMEOUTS.ADDITIONAL_DELAY_DEFAULT
265
493
  };
266
494
  }
267
495
 
496
+ // Export all public functions for use in other modules
268
497
  module.exports = {
269
498
  analyzeFlowProxyProtection,
270
499
  handleFlowProxyProtection,
271
500
  isFlowProxyProtected,
272
501
  getFlowProxyTimeouts,
273
- waitForTimeout
502
+ waitForTimeout,
503
+ getModuleInfo,
504
+ FLOWPROXY_MODULE_VERSION
274
505
  };
package/nwss.js CHANGED
@@ -1,4 +1,4 @@
1
- // === Network scanner script (nwss.js) v1.0.44 ===
1
+ // === Network scanner script (nwss.js) v1.0.45 ===
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,7 +35,7 @@ const { navigateWithRedirectHandling, handleRedirectTimeout } = require('./lib/r
35
35
  const { monitorBrowserHealth, isBrowserHealthy } = require('./lib/browserhealth');
36
36
 
37
37
  // --- Script Configuration & Constants ---
38
- const VERSION = '1.0.44'; // Script version
38
+ const VERSION = '1.0.45'; // Script version
39
39
 
40
40
  // get startTime
41
41
  const startTime = Date.now();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fanboynz/network-scanner",
3
- "version": "1.0.44",
3
+ "version": "1.0.45",
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": {