huijio commited on
Commit
71ae360
Β·
verified Β·
1 Parent(s): ae29417

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +197 -19
app.py CHANGED
@@ -136,7 +136,7 @@ def ip_swapper_handler(original_url, single_ip, multiple_ips, test_connectivity)
136
  """Main handler function for IP swapping"""
137
  try:
138
  if not original_url.strip():
139
- return "Please enter a URL", "", "", gr.update(visible=False)
140
 
141
  # Extract original IP for display
142
  original_ip = extract_ip_from_url(original_url)
@@ -146,18 +146,18 @@ def ip_swapper_handler(original_url, single_ip, multiple_ips, test_connectivity)
146
 
147
  if single_ip.strip():
148
  if not is_valid_ip(single_ip):
149
- return f"Error: Invalid IP address format: {single_ip}", "", "", gr.update(visible=False)
150
  ips_to_process.append(single_ip)
151
 
152
  if multiple_ips.strip():
153
  ip_list = [ip.strip() for ip in multiple_ips.split('\n') if ip.strip()]
154
  for ip in ip_list:
155
  if not is_valid_ip(ip):
156
- return f"Error: Invalid IP address format: {ip}", "", "", gr.update(visible=False)
157
  ips_to_process.extend(ip_list)
158
 
159
  if not ips_to_process:
160
- return "Please enter at least one valid IP address", "", "", gr.update(visible=False)
161
 
162
  # Process URLs
163
  results = []
@@ -169,6 +169,8 @@ def ip_swapper_handler(original_url, single_ip, multiple_ips, test_connectivity)
169
  'original_url': original_url
170
  })
171
  result_text = new_url
 
 
172
  else:
173
  result_lines = []
174
  for i, ip in enumerate(ips_to_process, 1):
@@ -182,6 +184,9 @@ def ip_swapper_handler(original_url, single_ip, multiple_ips, test_connectivity)
182
  result_lines.append(new_url)
183
  result_lines.append("")
184
  result_text = "\n".join(result_lines)
 
 
 
185
 
186
  # Get decoded r parameter
187
  decoded_r = decode_r_parameter(original_url)
@@ -243,10 +248,10 @@ def ip_swapper_handler(original_url, single_ip, multiple_ips, test_connectivity)
243
  # Show history button if we have test results
244
  history_visible = len(test_results) > 0
245
 
246
- return original_url, result_text, decoded_r, gr.update(visible=history_visible)
247
 
248
  except Exception as e:
249
- return f"Error: {str(e)}", "", "", gr.update(visible=False)
250
 
251
  def get_history_df():
252
  """Convert history data to DataFrame for display"""
@@ -268,7 +273,7 @@ def get_history_df():
268
 
269
  def clear_all():
270
  """Clear all inputs and outputs"""
271
- return "", "", "", "", "", gr.update(visible=False)
272
 
273
  def show_history():
274
  """Display history in a DataFrame"""
@@ -298,6 +303,21 @@ def export_history():
298
  df.to_csv(filename, index=False)
299
  return filename
300
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
301
  # Custom CSS for better styling
302
  custom_css = """
303
  .gradio-container {
@@ -349,6 +369,39 @@ custom_css = """
349
  .test-btn {
350
  background: linear-gradient(90deg, #10b981, #059669) !important;
351
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
352
  """
353
 
354
  # Create Gradio interface
@@ -360,7 +413,7 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
360
  πŸ”„ IP Swapper Wizard
361
  </h1>
362
  <p style="color: #6B7280; font-size: 1.1rem;">
363
- Swap IP addresses in URLs while maintaining all parameters β€’ Test Connectivity β€’ Track History
364
  </p>
365
  </div>
366
  """)
@@ -432,6 +485,38 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
432
  variant="secondary"
433
  )
434
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
435
  # History Section
436
  with gr.Accordion("πŸ“Š Test History & Analytics", open=False):
437
  with gr.Row():
@@ -450,14 +535,14 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
450
  3. **Check 'Test connectivity'** to automatically test URLs
451
  4. **Click 'Swap IP(s)'** to process and test
452
  5. **View results** with status indicators (βœ… Working / ❌ Not Working)
453
- 6. **Check history** for past test results
 
454
 
455
- **Testing Features:**
456
- - Automatic HTTP connectivity testing
457
- - Response time measurement
458
- - Status code reporting
459
- - Historical tracking with success rates
460
- - Export results to CSV
461
 
462
  **Status Indicators:**
463
  - βœ… Working: URL responded with HTTP 200
@@ -468,19 +553,35 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
468
  process_btn.click(
469
  fn=ip_swapper_handler,
470
  inputs=[url_input, single_ip_input, multiple_ips_input, test_connectivity],
471
- outputs=[original_url_output, modified_url_output, decoded_r_output, history_btn]
 
 
 
 
472
  )
473
 
474
  decode_btn.click(
475
- fn=lambda url: (url, "", decode_r_parameter(url), gr.update(visible=False)) if url else ("", "", "Please enter a URL", gr.update(visible=False)),
476
  inputs=[url_input],
477
- outputs=[original_url_output, modified_url_output, decoded_r_output, history_btn]
 
 
 
 
478
  )
479
 
480
  clear_btn.click(
481
  fn=clear_all,
482
  inputs=[],
483
- outputs=[url_input, single_ip_input, multiple_ips_input, original_url_output, modified_url_output, decoded_r_output, history_btn]
 
 
 
 
 
 
 
 
484
  )
485
 
486
  # History handlers
@@ -508,6 +609,83 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
508
  outputs=[history_output]
509
  )
510
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
511
  # Launch configuration
512
  if __name__ == "__main__":
513
  # Disable SSL warnings for testing
 
136
  """Main handler function for IP swapping"""
137
  try:
138
  if not original_url.strip():
139
+ return "Please enter a URL", "", "", gr.update(visible=False), "about:blank", "No URL to display"
140
 
141
  # Extract original IP for display
142
  original_ip = extract_ip_from_url(original_url)
 
146
 
147
  if single_ip.strip():
148
  if not is_valid_ip(single_ip):
149
+ return f"Error: Invalid IP address format: {single_ip}", "", "", gr.update(visible=False), "about:blank", "Invalid IP format"
150
  ips_to_process.append(single_ip)
151
 
152
  if multiple_ips.strip():
153
  ip_list = [ip.strip() for ip in multiple_ips.split('\n') if ip.strip()]
154
  for ip in ip_list:
155
  if not is_valid_ip(ip):
156
+ return f"Error: Invalid IP address format: {ip}", "", "", gr.update(visible=False), "about:blank", f"Invalid IP: {ip}"
157
  ips_to_process.extend(ip_list)
158
 
159
  if not ips_to_process:
160
+ return "Please enter at least one valid IP address", "", "", gr.update(visible=False), "about:blank", "No IPs provided"
161
 
162
  # Process URLs
163
  results = []
 
169
  'original_url': original_url
170
  })
171
  result_text = new_url
172
+ iframe_url = new_url
173
+ iframe_title = f"Testing: {ips_to_process[0]}"
174
  else:
175
  result_lines = []
176
  for i, ip in enumerate(ips_to_process, 1):
 
184
  result_lines.append(new_url)
185
  result_lines.append("")
186
  result_text = "\n".join(result_lines)
187
+ # For multiple IPs, show the first one in iframe
188
+ iframe_url = results[0]['url'] if results else "about:blank"
189
+ iframe_title = f"Testing: {results[0]['ip']}" if results else "Multiple IPs"
190
 
191
  # Get decoded r parameter
192
  decoded_r = decode_r_parameter(original_url)
 
248
  # Show history button if we have test results
249
  history_visible = len(test_results) > 0
250
 
251
+ return original_url, result_text, decoded_r, gr.update(visible=history_visible), iframe_url, iframe_title
252
 
253
  except Exception as e:
254
+ return f"Error: {str(e)}", "", "", gr.update(visible=False), "about:blank", f"Error: {str(e)}"
255
 
256
  def get_history_df():
257
  """Convert history data to DataFrame for display"""
 
273
 
274
  def clear_all():
275
  """Clear all inputs and outputs"""
276
+ return "", "", "", "", "", gr.update(visible=False), "about:blank", "Ready for testing..."
277
 
278
  def show_history():
279
  """Display history in a DataFrame"""
 
303
  df.to_csv(filename, index=False)
304
  return filename
305
 
306
+ def load_url_in_iframe(url, ip_address):
307
+ """Load a specific URL in the iframe"""
308
+ if not url or url.startswith("Error:") or url.startswith("Please enter"):
309
+ return "about:blank", "No valid URL to display"
310
+
311
+ # Validate URL format
312
+ try:
313
+ parsed = urlparse(url)
314
+ if parsed.scheme and parsed.netloc:
315
+ return url, f"Testing: {ip_address}"
316
+ else:
317
+ return "about:blank", "Invalid URL format"
318
+ except:
319
+ return "about:blank", "Invalid URL"
320
+
321
  # Custom CSS for better styling
322
  custom_css = """
323
  .gradio-container {
 
369
  .test-btn {
370
  background: linear-gradient(90deg, #10b981, #059669) !important;
371
  }
372
+ .iframe-container {
373
+ border: 2px solid #e5e7eb;
374
+ border-radius: 10px;
375
+ overflow: hidden;
376
+ margin-top: 10px;
377
+ }
378
+ .iframe-header {
379
+ background: #4f46e5;
380
+ color: white;
381
+ padding: 8px 12px;
382
+ font-weight: bold;
383
+ display: flex;
384
+ justify-content: between;
385
+ align-items: center;
386
+ }
387
+ .iframe-content {
388
+ height: 500px;
389
+ width: 100%;
390
+ }
391
+ .url-test-buttons {
392
+ margin: 10px 0;
393
+ display: flex;
394
+ gap: 10px;
395
+ flex-wrap: wrap;
396
+ }
397
+ .url-test-btn {
398
+ background: #4f46e5 !important;
399
+ color: white !important;
400
+ border: none !important;
401
+ }
402
+ .url-test-btn:hover {
403
+ background: #4338ca !important;
404
+ }
405
  """
406
 
407
  # Create Gradio interface
 
413
  πŸ”„ IP Swapper Wizard
414
  </h1>
415
  <p style="color: #6B7280; font-size: 1.1rem;">
416
+ Swap IP addresses in URLs while maintaining all parameters β€’ Test Connectivity β€’ Track History β€’ Live Preview
417
  </p>
418
  </div>
419
  """)
 
485
  variant="secondary"
486
  )
487
 
488
+ # Live Preview Section
489
+ with gr.Accordion("🌐 Live URL Preview & Testing", open=True):
490
+ gr.Markdown("**Test your generated URLs directly in the browser below:**")
491
+
492
+ with gr.Row():
493
+ with gr.Column(scale=3):
494
+ iframe_title = gr.Textbox(
495
+ label="Current Preview:",
496
+ interactive=False,
497
+ max_lines=1,
498
+ value="Ready for testing..."
499
+ )
500
+
501
+ # URL testing buttons will be dynamically generated
502
+ url_test_buttons = gr.HTML(
503
+ value="<div style='padding: 10px; background: #f3f4f6; border-radius: 5px; text-align: center;'>Generated URLs will appear here after processing</div>"
504
+ )
505
+
506
+ with gr.Column(scale=7):
507
+ iframe_component = gr.HTML(
508
+ value="""
509
+ <div class="iframe-container">
510
+ <div class="iframe-header">
511
+ <span>πŸ” Live Browser Preview</span>
512
+ </div>
513
+ <iframe src="about:blank" class="iframe-content" id="preview-iframe"
514
+ sandbox="allow-scripts allow-same-origin allow-forms allow-popups"
515
+ loading="lazy"></iframe>
516
+ </div>
517
+ """
518
+ )
519
+
520
  # History Section
521
  with gr.Accordion("πŸ“Š Test History & Analytics", open=False):
522
  with gr.Row():
 
535
  3. **Check 'Test connectivity'** to automatically test URLs
536
  4. **Click 'Swap IP(s)'** to process and test
537
  5. **View results** with status indicators (βœ… Working / ❌ Not Working)
538
+ 6. **Test URLs live** in the built-in browser
539
+ 7. **Check history** for past test results
540
 
541
+ **Live Preview Features:**
542
+ - Test URLs directly in the app
543
+ - Built-in browser with iframe
544
+ - Quick navigation between multiple IPs
545
+ - Safe sandboxed environment
 
546
 
547
  **Status Indicators:**
548
  - βœ… Working: URL responded with HTTP 200
 
553
  process_btn.click(
554
  fn=ip_swapper_handler,
555
  inputs=[url_input, single_ip_input, multiple_ips_input, test_connectivity],
556
+ outputs=[original_url_output, modified_url_output, decoded_r_output, history_btn, iframe_component, iframe_title]
557
+ ).then(
558
+ fn=lambda modified_url, single_ip, multiple_ips: generate_url_buttons(modified_url, single_ip, multiple_ips),
559
+ inputs=[modified_url_output, single_ip_input, multiple_ips_input],
560
+ outputs=[url_test_buttons]
561
  )
562
 
563
  decode_btn.click(
564
+ fn=lambda url: (url, "", decode_r_parameter(url), gr.update(visible=False), "about:blank", "Decode Only Mode") if url else ("", "", "Please enter a URL", gr.update(visible=False), "about:blank", "No URL"),
565
  inputs=[url_input],
566
+ outputs=[original_url_output, modified_url_output, decoded_r_output, history_btn, iframe_component, iframe_title]
567
+ ).then(
568
+ fn=lambda modified_url, single_ip, multiple_ips: "<div style='padding: 10px; background: #f3f4f6; border-radius: 5px; text-align: center;'>Use 'Swap IP(s)' to generate testable URLs</div>",
569
+ inputs=[modified_url_output, single_ip_input, multiple_ips_input],
570
+ outputs=[url_test_buttons]
571
  )
572
 
573
  clear_btn.click(
574
  fn=clear_all,
575
  inputs=[],
576
+ outputs=[url_input, single_ip_input, multiple_ips_input, original_url_output, modified_url_output, decoded_r_output, history_btn, iframe_title]
577
+ ).then(
578
+ fn=lambda: "about:blank",
579
+ inputs=[],
580
+ outputs=[iframe_component]
581
+ ).then(
582
+ fn=lambda: "<div style='padding: 10px; background: #f3f4f6; border-radius: 5px; text-align: center;'>Generated URLs will appear here after processing</div>",
583
+ inputs=[],
584
+ outputs=[url_test_buttons]
585
  )
586
 
587
  # History handlers
 
609
  outputs=[history_output]
610
  )
611
 
612
+ def generate_url_buttons(modified_url, single_ip, multiple_ips):
613
+ """Generate clickable buttons for testing URLs in iframe"""
614
+ if not modified_url or modified_url.startswith("Error:") or modified_url.startswith("Please enter"):
615
+ return "<div style='padding: 10px; background: #f3f4f6; border-radius: 5px; text-align: center;'>No valid URLs to test</div>"
616
+
617
+ # Extract URLs from the modified_url text
618
+ urls = []
619
+ ips = []
620
+
621
+ if single_ip and is_valid_ip(single_ip):
622
+ # Single IP case - extract the URL directly
623
+ urls.append(modified_url.split('\n')[0]) # Take first line as URL
624
+ ips.append(single_ip)
625
+
626
+ if multiple_ips:
627
+ # Multiple IPs case - parse the formatted output
628
+ ip_list = [ip.strip() for ip in multiple_ips.split('\n') if ip.strip() and is_valid_ip(ip)]
629
+ lines = modified_url.split('\n')
630
+
631
+ for i, line in enumerate(lines):
632
+ if line.startswith('http'):
633
+ # Find the corresponding IP
634
+ for ip in ip_list:
635
+ if ip in lines[i-1] if i > 0 else False:
636
+ urls.append(line)
637
+ ips.append(ip)
638
+ break
639
+
640
+ # If we couldn't parse structured output, try to extract URLs directly
641
+ if not urls:
642
+ import re
643
+ url_pattern = r'https?://[^\s]+'
644
+ found_urls = re.findall(url_pattern, modified_url)
645
+ urls = found_urls
646
+ # Use the provided IPs or generate placeholders
647
+ if single_ip:
648
+ ips = [single_ip] * len(urls)
649
+ elif multiple_ips:
650
+ ip_list = [ip.strip() for ip in multiple_ips.split('\n') if ip.strip()]
651
+ ips = ip_list[:len(urls)]
652
+ else:
653
+ ips = [f"IP_{i+1}" for i in range(len(urls))]
654
+
655
+ if not urls:
656
+ return "<div style='padding: 10px; background: #f3f4f6; border-radius: 5px; text-align: center;'>No valid URLs found in output</div>"
657
+
658
+ # Generate buttons HTML
659
+ buttons_html = '<div class="url-test-buttons">'
660
+ buttons_html += '<strong>Test URLs:</strong><br>'
661
+
662
+ for i, (url, ip) in enumerate(zip(urls, ips)):
663
+ button_id = f"url-btn-{i}"
664
+ buttons_html += f'''
665
+ <button class="url-test-btn" onclick="loadIframe('{url}', '{ip}')" style="margin: 2px; padding: 5px 10px; border-radius: 4px;">
666
+ 🌐 Test {ip}
667
+ </button>
668
+ '''
669
+
670
+ buttons_html += '</div>'
671
+ buttons_html += '''
672
+ <script>
673
+ function loadIframe(url, ip) {
674
+ const iframe = document.getElementById('preview-iframe');
675
+ const title = document.querySelector('[data-testid="iframe_title"] input');
676
+ iframe.src = url;
677
+ if (title) title.value = 'Testing: ' + ip;
678
+
679
+ // Update Gradio state (optional)
680
+ if (window.gradio_app) {
681
+ // You can add Gradio state updates here if needed
682
+ }
683
+ }
684
+ </script>
685
+ '''
686
+
687
+ return buttons_html
688
+
689
  # Launch configuration
690
  if __name__ == "__main__":
691
  # Disable SSL warnings for testing