webtools-cli 1.0.4__tar.gz → 1.0.6__tar.gz

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.
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: webtools-cli
3
- Version: 1.0.4
3
+ Version: 1.0.6
4
4
  Summary: Advanced Web Intelligence & Scraping Toolkit with CLI and Web UI
5
5
  Author: Abhinav Adarsh
6
6
  License-Expression: MIT
7
- Project-URL: Homepage, https://github.com/abhinavgautam08/webtools-cli
7
+ Project-URL: Homepage, https://webtoolscli.pages.dev
8
8
  Keywords: web-scraping,osint,seo,intelligence,cli
9
9
  Classifier: Development Status :: 4 - Beta
10
10
  Classifier: Environment :: Console
@@ -41,7 +41,9 @@ Dynamic: license-file
41
41
 
42
42
  ![WebTools CLI Interface](https://i.postimg.cc/7LXjQqBm/CLI.png)
43
43
 
44
- WebTools CLI is an advanced web intelligence suite for researchers, OSINT enthusiasts, and developers. It brings the power of deep web analysis and automated scraping directly into your terminal, bridging the gap between a high-speed **Terminal UI** and a feature-rich **Cyber-themed Dashboard**.
44
+ try : [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1l4-ZChKGYhOFrPwp2_JPLJ1X0ZYSVrZk?usp=sharing)
45
+
46
+ An advanced web intelligence suite for researchers, OSINT enthusiasts, and developers. It brings the power of deep web analysis and automated scraping directly into your terminal.
45
47
 
46
48
  ---
47
49
 
@@ -79,6 +81,7 @@ pip install webtools-cli --upgrade
79
81
  For Single Page Application (SPA) support:
80
82
 
81
83
  ```bash
84
+ pip install "webtools-cli[playwright]"
82
85
  playwright install chromium
83
86
  ```
84
87
 
@@ -99,9 +102,9 @@ playwright install chromium
99
102
  - **Honeypot Detector**: Identifies hidden traps and anti-bot measures (Cloudflare/CAPTCHAs).
100
103
 
101
104
  ### Modern Experience
102
- - **Matrix Background**: "Flickering Grid" animated dashboard (Canvas-based).
103
- - **Responsive Preview**: Live rendering scaling for desktop and mobile viewpoints.
104
- - **History & Stats**: Phase-by-phase performance tracking and historical session management.
105
+ - **Premium Visual Engine**: Sleek glassmorphism, fluid gradients, and premium Motion One animations.
106
+ - **Edge-to-Edge Responsiveness**: Rock-solid layout stability on every device, from iPhone SE to 4K monitors.
107
+ - **Dynamic Interactions**: Flickering grid backgrounds, hover-glow effects, and high-performance transitions.
105
108
 
106
109
  ---
107
110
 
@@ -158,5 +161,11 @@ This tool is for **educational and testing purposes only**. Always respect `robo
158
161
  ---
159
162
 
160
163
  <p align="center">
161
- Built with ❤️ by <strong>Abhinav Adarsh</strong> and the open source community
164
+ Built with ❤️ by
165
+ <strong>
166
+ <a href="https://abhinavgautam08.pages.dev/" target="_blank" rel="noopener noreferrer">
167
+ Abhinav Adarsh
168
+ </a>
169
+ </strong>
170
+ and the open source community
162
171
  </p>
@@ -6,7 +6,9 @@
6
6
 
7
7
  ![WebTools CLI Interface](https://i.postimg.cc/7LXjQqBm/CLI.png)
8
8
 
9
- WebTools CLI is an advanced web intelligence suite for researchers, OSINT enthusiasts, and developers. It brings the power of deep web analysis and automated scraping directly into your terminal, bridging the gap between a high-speed **Terminal UI** and a feature-rich **Cyber-themed Dashboard**.
9
+ try : [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1l4-ZChKGYhOFrPwp2_JPLJ1X0ZYSVrZk?usp=sharing)
10
+
11
+ An advanced web intelligence suite for researchers, OSINT enthusiasts, and developers. It brings the power of deep web analysis and automated scraping directly into your terminal.
10
12
 
11
13
  ---
12
14
 
@@ -44,6 +46,7 @@ pip install webtools-cli --upgrade
44
46
  For Single Page Application (SPA) support:
45
47
 
46
48
  ```bash
49
+ pip install "webtools-cli[playwright]"
47
50
  playwright install chromium
48
51
  ```
49
52
 
@@ -64,9 +67,9 @@ playwright install chromium
64
67
  - **Honeypot Detector**: Identifies hidden traps and anti-bot measures (Cloudflare/CAPTCHAs).
65
68
 
66
69
  ### Modern Experience
67
- - **Matrix Background**: "Flickering Grid" animated dashboard (Canvas-based).
68
- - **Responsive Preview**: Live rendering scaling for desktop and mobile viewpoints.
69
- - **History & Stats**: Phase-by-phase performance tracking and historical session management.
70
+ - **Premium Visual Engine**: Sleek glassmorphism, fluid gradients, and premium Motion One animations.
71
+ - **Edge-to-Edge Responsiveness**: Rock-solid layout stability on every device, from iPhone SE to 4K monitors.
72
+ - **Dynamic Interactions**: Flickering grid backgrounds, hover-glow effects, and high-performance transitions.
70
73
 
71
74
  ---
72
75
 
@@ -123,5 +126,11 @@ This tool is for **educational and testing purposes only**. Always respect `robo
123
126
  ---
124
127
 
125
128
  <p align="center">
126
- Built with ❤️ by <strong>Abhinav Adarsh</strong> and the open source community
127
- </p>
129
+ Built with ❤️ by
130
+ <strong>
131
+ <a href="https://abhinavgautam08.pages.dev/" target="_blank" rel="noopener noreferrer">
132
+ Abhinav Adarsh
133
+ </a>
134
+ </strong>
135
+ and the open source community
136
+ </p>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "webtools-cli"
7
- version = "1.0.4"
7
+ version = "1.0.6"
8
8
  description = "Advanced Web Intelligence & Scraping Toolkit with CLI and Web UI"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -45,7 +45,7 @@ playwright = ["playwright"]
45
45
  webtools = "webtools.cli:main"
46
46
 
47
47
  [project.urls]
48
- Homepage = "https://github.com/abhinavgautam08/webtools-cli"
48
+ Homepage = "https://webtoolscli.pages.dev"
49
49
 
50
50
  [tool.setuptools.packages.find]
51
51
  include = ["webtools*"]
@@ -4,8 +4,19 @@ sys.dont_write_bytecode = True
4
4
  # --- PACKAGE PATHS ---
5
5
  PACKAGE_DIR = os.path.dirname(os.path.abspath(__file__))
6
6
  DATA_DIR = os.path.join(os.path.expanduser('~'), '.webtools')
7
- SCRAPED_DIR = os.path.join(DATA_DIR, 'scraped')
7
+
8
+ # Output paths in Current Working Directory (CWD)
9
+ BASE_DIR = os.getcwd()
10
+ WEBFILES_DIR = os.path.join(BASE_DIR, 'webfiles')
11
+ SCRAPED_DIR = os.path.join(WEBFILES_DIR, 'scraped')
12
+ BULK_DIR = os.path.join(WEBFILES_DIR, 'bulk')
13
+
14
+ # Ensure directories exist
8
15
  os.makedirs(SCRAPED_DIR, exist_ok=True)
16
+ os.makedirs(BULK_DIR, exist_ok=True)
17
+ os.makedirs(os.path.join(SCRAPED_DIR, 'images'), exist_ok=True)
18
+ os.makedirs(os.path.join(SCRAPED_DIR, 'videos'), exist_ok=True)
19
+ os.makedirs(DATA_DIR, exist_ok=True) # Global meta data stays persistent
9
20
  try:
10
21
  from colorama import init, Fore, Style
11
22
  init(autoreset=True)
@@ -97,9 +108,8 @@ log.setLevel(logging.ERROR)
97
108
  # SSL warnings ko globally band karo
98
109
  urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
99
110
 
100
- # Directories setup kar rahe hain
101
- os.makedirs(os.path.join(SCRAPED_DIR, 'images'), exist_ok=True)
102
- os.makedirs(os.path.join(SCRAPED_DIR, 'videos'), exist_ok=True)
111
+ # SSL warnings ko globally band karo
112
+ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
103
113
 
104
114
  # --- PERFORMANCE AUDITOR ---
105
115
  class PerformanceTracker:
@@ -561,18 +571,70 @@ def detect_tech_stack(soup, response):
561
571
 
562
572
  return list(stack)
563
573
 
574
+ def ensure_playwright():
575
+ """Ensure playwright and its browser are installed"""
576
+ global PLAYWRIGHT_AVAILABLE
577
+ if PLAYWRIGHT_AVAILABLE:
578
+ return True
579
+ try:
580
+ import playwright
581
+ PLAYWRIGHT_AVAILABLE = True
582
+ return True
583
+ except ImportError:
584
+ print(f"\n{Fore.CYAN}🚀 Installing Playwright dependencies...{Style.RESET_ALL}")
585
+ try:
586
+ # First try installing the extra (recommended for pip users)
587
+ try:
588
+ subprocess.run([sys.executable, "-m", "pip", "install", "webtools-cli[playwright]"], check=True)
589
+ except:
590
+ # Fallback to direct install
591
+ subprocess.run([sys.executable, "-m", "pip", "install", "playwright"], check=True)
592
+
593
+ # After pip install, we need to install the browser
594
+ print(f"{Fore.CYAN}📥 Downloading Chromium browser...{Style.RESET_ALL}")
595
+ subprocess.run([sys.executable, "-m", "playwright", "install", "chromium"], check=True)
596
+
597
+ # Reset state for current session
598
+ PLAYWRIGHT_AVAILABLE = True
599
+ return True
600
+ except Exception as e:
601
+ print(f"{Fore.RED}❌ Playwright auto-installation failed: {e}{Style.RESET_ALL}")
602
+ print(f"💡 Manual Tip: pip install \"webtools-cli[playwright]\"")
603
+ return False
604
+
564
605
  def ensure_textblob_corpora():
565
606
  """Ensure necessary NLTK corpora for TextBlob are downloaded"""
566
607
  try:
567
608
  import nltk
568
- needed = ['punkt', 'brown', 'averaged_perceptron_tagger']
609
+ # OFFICIAL TEXTBLOB DOWNLOAD COMMAND (Ensures all defaults are met)
610
+ try:
611
+ # Check if one major corpus usually missing is there
612
+ nltk.data.find('corpora/brown')
613
+ except:
614
+ if COLOR_SUPPORT: print(f"{Fore.CYAN}🧠 Fetching AI Intelligence Datasets...{Style.RESET_ALL}")
615
+ else: print("🧠 Fetching AI Intelligence Datasets...")
616
+ subprocess.run([sys.executable, "-m", "textblob.download_corpora"], check=False)
617
+
618
+ needed = ['punkt', 'brown', 'averaged_perceptron_tagger', 'wordnet', 'omw-1.4', 'conll2000', 'stopwords']
569
619
  for corpus in needed:
570
620
  try:
571
- nltk.data.find(f'tokenizers/{corpus}' if corpus == 'punkt' else f'corpora/{corpus}')
621
+ # Check for tokenizer or general data
622
+ if corpus == 'punkt':
623
+ try:
624
+ nltk.data.find('tokenizers/punkt')
625
+ except:
626
+ nltk.data.find('tokenizers/punkt.zip')
627
+ else:
628
+ try:
629
+ nltk.data.find(f'corpora/{corpus}')
630
+ except:
631
+ nltk.data.find(f'corpora/{corpus}.zip')
572
632
  except (LookupError, AttributeError):
573
- print(f"Downloading required AI data: {corpus}...")
633
+ from webtools.core import Fore # Reuse branding colors if available
634
+ print(f"📦 Installing AI Intelligence Data: {corpus}...")
574
635
  nltk.download(corpus, quiet=True)
575
- except:
636
+ except Exception as e:
637
+ print(f"⚠️ AI Data Error: Could not download {needed}. AI features may be limited. ({e})")
576
638
  pass
577
639
 
578
640
  def analyze_ai_content(text):
@@ -834,16 +896,50 @@ def execute_scrape_logic(url, fetch_images=False, fetch_videos=False, crawl_dept
834
896
  else:
835
897
  return {'success': False, 'error': f'Request failed and Playwright fallback failed: {str(e)}'}
836
898
  else:
837
- error_msg = f"Request failed: {str(e)}"
899
+ # Specific Error Analysis for better UX
838
900
  if response and response.status_code == 404:
839
- error_msg += "\n💡 Tip: URL might be expired or the site is blocking direct requests. Install Playwright for better results: pip install webtools-cli[playwright]"
901
+ error_msg = f"❌ Page Not Found (404): {url}\n💡 Tip: The URL might be incorrect or has been moved."
902
+ elif response and response.status_code in [403, 429]:
903
+ error_msg = f"❌ Access Denied ({response.status_code}): {url}\n💡 Tip: Site is blocking direct requests. Try installing Playwright for better bypassing:\n pip install webtools-cli[playwright]"
840
904
  else:
841
- error_msg += "\n💡 Tip: Try installing Playwright for better bypassing: pip install webtools-cli[playwright]"
905
+ error_msg = f"❌ Request Failed: {str(e)}\n💡 Tip: If this site requires JavaScript or uses strong anti-bot, install Playwright:\n pip install webtools-cli[playwright]"
842
906
  return {'success': False, 'error': error_msg}
843
907
 
844
908
  soup = BeautifulSoup(response.text, 'html.parser')
845
909
  perf_tracker.record_phase("HTML Parsing")
846
910
 
911
+ # --- AUTO-SAVE FILES (For Persistence) ---
912
+ try:
913
+ # Save HTML
914
+ with open(os.path.join(SCRAPED_DIR, 'index.html'), 'w', encoding='utf-8') as f:
915
+ f.write(response.text)
916
+
917
+ # Save CSS (Combined)
918
+ css_links = [l.get('href') for l in soup.find_all('link', rel='stylesheet')]
919
+ css_content = []
920
+ for link in css_links:
921
+ if not link: continue
922
+ try:
923
+ full_url = requests.compat.urljoin(url, link)
924
+ css_content.append(requests.get(full_url, headers=headers, timeout=5).text)
925
+ except: continue
926
+ with open(os.path.join(SCRAPED_DIR, 'style.css'), 'w', encoding='utf-8') as f:
927
+ f.write('\n\n'.join(css_content))
928
+
929
+ # Save JS (Mock/Combined)
930
+ js_links = [s.get('src') for s in soup.find_all('script') if s.get('src')]
931
+ js_content = []
932
+ for link in js_links:
933
+ try:
934
+ full_url = requests.compat.urljoin(url, link)
935
+ js_content.append(requests.get(full_url, headers=headers, timeout=5).text)
936
+ except: continue
937
+ with open(os.path.join(SCRAPED_DIR, 'script.js'), 'w', encoding='utf-8') as f:
938
+ f.write('\n\n'.join(js_content))
939
+
940
+ except Exception as e:
941
+ print(f"⚠️ Auto-Save Warning: Could not save local copies: {e}")
942
+
847
943
  # --- HONEYPOT DETECTOR (Security Scout) ---
848
944
  security_report = {'level': 'LOW', 'threats': [], 'honeypots': 0}
849
945
 
@@ -1697,7 +1793,7 @@ def api_bulk():
1697
1793
  return jsonify({'success': False, 'error': 'No URLs provided'})
1698
1794
 
1699
1795
  timestamp = int(time.time())
1700
- base_folder = f'webfiles/bulk/batch_{timestamp}'
1796
+ base_folder = os.path.join(BULK_DIR, f'batch_{timestamp}')
1701
1797
  os.makedirs(base_folder, exist_ok=True)
1702
1798
  headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'}
1703
1799
  processed = 0
@@ -1767,7 +1863,7 @@ def api_bulk():
1767
1863
 
1768
1864
  @app.route('/download/bulk/<path:filename>')
1769
1865
  def serve_bulk_file(filename):
1770
- return send_from_directory('webfiles/bulk', filename)
1866
+ return send_from_directory(BULK_DIR, filename)
1771
1867
 
1772
1868
  @app.route('/api/save', methods=['POST'])
1773
1869
  def api_save():
@@ -1777,7 +1873,8 @@ def api_save():
1777
1873
  content = data.get('content')
1778
1874
 
1779
1875
  if filename in ['index.html', 'style.css', 'script.js']:
1780
- with open(f'webfiles/scraped/{filename}', 'w', encoding='utf-8') as f:
1876
+ output_path = os.path.join(SCRAPED_DIR, filename)
1877
+ with open(output_path, 'w', encoding='utf-8') as f:
1781
1878
  f.write(content)
1782
1879
  return jsonify({'success': True})
1783
1880
  else:
@@ -2356,8 +2453,8 @@ def run_cli_mode(initial_url=None):
2356
2453
  print(f"{Fore.CYAN}{Style.BRIGHT} ADVANCED CLI INTELLIGENCE MODE{Style.RESET_ALL}")
2357
2454
 
2358
2455
  try:
2359
- url = initial_url if initial_url else input(f"{Fore.LIGHTGREEN_EX if COLOR_SUPPORT else ''}link > {Style.RESET_ALL}").strip()
2360
- if not url: return
2456
+ url = initial_url if initial_url else input(f"{Fore.LIGHTGREEN_EX if COLOR_SUPPORT else ''}link (or /q to back) > {Style.RESET_ALL}").strip()
2457
+ if not url or url.lower() in ['/q', 'q', '/back', '/exit']: return
2361
2458
 
2362
2459
  # Double check validity if manual input
2363
2460
  if not initial_url and not is_valid_url(url):
@@ -2396,9 +2493,10 @@ def run_cli_mode(initial_url=None):
2396
2493
  result = execute_scrape_logic(url, fetch_img, fetch_vid, depth, use_proxy)
2397
2494
  print_cli_report(result)
2398
2495
 
2399
- input("Press Enter to return to main menu and CLEAR session data...")
2400
- clear_scraped_data()
2401
- print("🧹 Session data cleared.")
2496
+ print(f"\n📁 Scraped Data Location: {Fore.CYAN}{SCRAPED_DIR}{Style.RESET_ALL}")
2497
+ input("Press Enter to return to main menu...")
2498
+ # clear_scraped_data() removed to allow data persistence
2499
+ # clear_scraped_data()
2402
2500
  time.sleep(1)
2403
2501
  except KeyboardInterrupt:
2404
2502
  print("\n\n⚠️ Input interrupted. Returning to menu...")
@@ -2417,8 +2515,8 @@ def run_image_forensics_mode(initial_image=None):
2417
2515
  print(f"{' ' * 45}{Fore.WHITE}{Style.DIM}Dev : Abhinav Adarsh{Style.RESET_ALL}\n")
2418
2516
 
2419
2517
  try:
2420
- user_input = initial_image if initial_image else input(f"{Fore.LIGHTGREEN_EX if COLOR_SUPPORT else ''}image link or local path > {Style.RESET_ALL}").strip()
2421
- if not user_input: return
2518
+ user_input = initial_image if initial_image else input(f"{Fore.LIGHTGREEN_EX if COLOR_SUPPORT else ''}image link or local path (or /q to back) > {Style.RESET_ALL}").strip()
2519
+ if not user_input or user_input.lower() in ['/q', 'q', '/back', '/exit']: return
2422
2520
 
2423
2521
  # Handle quotes (e.g. from copy-pasting path)
2424
2522
  user_input = user_input.strip('"\'')
@@ -2526,6 +2624,9 @@ def print_image_forensics_report(data):
2526
2624
 
2527
2625
  def main_launcher():
2528
2626
  """Mode selection menu on startup"""
2627
+ # Ensure Playwright on startup
2628
+ ensure_playwright()
2629
+
2529
2630
  menu_commands = ['/web', '/cli', '/image', '/help', '/clear', '/quit', '/history', '/w', '/c', '/i', '/h', '/q', '/hi', '--help']
2530
2631
  setup_autocomplete(menu_commands)
2531
2632
 
@@ -2603,14 +2704,17 @@ def start_web_server():
2603
2704
  os.system('cls' if os.name == 'nt' else 'clear')
2604
2705
  print(f"Scan this QR code :\n")
2605
2706
  display_qr_image(public_url)
2606
- print(f"\nPress Ctrl+C to stop.")
2707
+ print(f"\nType {Fore.CYAN}/q{Fore.WHITE} or press {Fore.CYAN}Ctrl+C{Fore.WHITE} to stop.")
2607
2708
 
2608
2709
  try:
2609
2710
  if 'google.colab' in sys.modules:
2610
2711
  print("\n Running in Background.")
2611
2712
  while True: time.sleep(100)
2612
2713
  else:
2613
- while True: time.sleep(1)
2714
+ while True:
2715
+ cmd = input(f"{Fore.LIGHTGREEN_EX}> {Style.RESET_ALL}").strip().lower()
2716
+ if cmd in ['/q', 'q', '/back', '/exit']:
2717
+ break
2614
2718
  except KeyboardInterrupt:
2615
2719
  print("\n Thank you for using ^_^ Web Tools")
2616
2720
  if tunnel_proc:
@@ -4,8 +4,8 @@
4
4
  <head>
5
5
  <meta charset="UTF-8">
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>Web Tools</title>
8
- <link rel="icon" type="image/png" href="/favicon.png">
7
+ <title>WebTools | Web Intelligence Suite</title>
8
+ <link rel="icon" type="image/png" href="https://i.postimg.cc/Gh7Gnn18/Web-Tools.png">
9
9
  <script src="https://cdn.tailwindcss.com"></script>
10
10
  <script src="https://cdn.jsdelivr.net/npm/motion@10.15.5/dist/motion.js"></script>
11
11
  <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
@@ -14,26 +14,25 @@
14
14
  <script src="script.js" defer></script>
15
15
  </head>
16
16
 
17
- <body
18
- class="bg-gray-950 dark:bg-gray-950 text-slate-200 min-h-screen selection:bg-indigo-500/30 transition-colors duration-300">
19
- <div style="position: fixed; inset: 0; z-index: -1; pointer-events: none;">
20
- <canvas id="flickering-grid"
21
- style="width: 100%; height: 100%; mask-image: radial-gradient(circle at center, white, transparent 90%); -webkit-mask-image: radial-gradient(circle at center, white, transparent 90%); opacity: 0.4;"></canvas>
17
+ <body class="min-h-screen selection:bg-blue-500/30 transition-colors duration-300">
18
+ <!-- Background Effects -->
19
+ <div class="grid-bg"></div>
20
+ <div class="glow-orb" style="top: -10%; left: -10%;"></div>
21
+ <div class="glow-orb"
22
+ style="bottom: -10%; right: -10%; background: radial-gradient(circle, rgba(139, 92, 246, 0.12) 0%, transparent 70%);">
22
23
  </div>
23
24
  <div class="container mx-auto px-4 py-8 max-w-7xl flex flex-col items-center">
24
25
  <header id="main-header" class="text-left mb-8 transform opacity-0 translate-y-[-20px] w-full">
25
26
  <div class="flex justify-between items-center mb-4 w-full">
26
27
  <div class="flex items-center gap-2">
27
- <div class="inline-flex items-center justify-center p-1.5 rounded-xl">
28
- <img src="/favicon.png" alt="Web Tools" class="w-8 h-8">
29
- </div>
30
- <div>
31
- <h1
32
- class="text-lg md:text-xl font-extrabold bg-clip-text text-transparent bg-gradient-to-r from-white via-indigo-200 to-indigo-400 tracking-tight text-left">
33
- Web Tools
34
- </h1>
35
- <p class="text-[10px] text-slate-400 font-light leading-tight">Extract HTML, CSS, JS, Images &
36
- Videos</p>
28
+ <div class="logo ascii-logo" style="max-width: 200px; overflow: hidden;">
29
+ <pre
30
+ style="font-family: 'JetBrains Mono', monospace; font-size: 3.5px; line-height: 1; margin: 0; white-space: pre; background: linear-gradient(135deg, #3b82f6, #8b5cf6, #06b6d4); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; pointer-events: none;">██╗ ██╗███████╗██████╗ ████████╗ ██████╗ ██████╗ ██╗ ███████╗
31
+ ██║ ██║██╔════╝██╔══██╗ ╚══██╔══╝██╔═══██╗██╔═══██╗██║ ██╔════╝
32
+ ██║ █╗ ██║█████╗ ██████╔╝ ██║ ██║ ██║██║ ██║██║ ███████╗
33
+ ██║███╗██║██╔══╝ ██╔══██╗ ██║ ██║ ██║██║ ██║██║ ╚════██║
34
+ ╚███╔███╔╝███████╗██████╔╝ ██║ ╚██████╔╝╚██████╔╝███████╗███████║
35
+ ╚══╝╚══╝ ╚══════╝╚═════╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚══════╝</pre>
37
36
  </div>
38
37
  </div>
39
38
  <div class="flex gap-2">
@@ -76,7 +75,7 @@
76
75
  class="bg-black/40 rounded-2xl p-4 md:p-6 border border-white/5 relative overflow-hidden">
77
76
  <!-- WEBSCRAPER MODE -->
78
77
  <div id="mode-scraper" class="transition-all duration-300">
79
- <div class="flex flex-row gap-2 md:gap-3 mb-2">
78
+ <div id="scraper-input-row" class="flex flex-row gap-2 md:gap-3 mb-2">
80
79
  <div class="flex-1 relative group">
81
80
  <div class="absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none">
82
81
  <svg class="w-5 h-5 text-slate-500 group-focus-within:text-indigo-400 transition-colors"
@@ -289,16 +289,23 @@ function toggleBulkMode() {
289
289
  const isBulk = document.getElementById('bulkMode').checked;
290
290
  const singleInput = document.getElementById('urlInput').parentElement;
291
291
  const bulkInput = document.getElementById('bulk-input-container');
292
-
292
+ const scrapeBtn = document.getElementById('scrapeBtn');
293
+ const inputRow = document.getElementById('scraper-input-row');
293
294
 
294
295
  if(isBulk) {
295
296
  singleInput.classList.add('hidden');
296
-
297
297
  bulkInput.classList.remove('hidden');
298
+
299
+ // Move button below bulk text area
300
+ bulkInput.appendChild(scrapeBtn);
301
+ scrapeBtn.classList.add('w-full', 'mt-4');
298
302
  } else {
299
303
  singleInput.classList.remove('hidden');
300
-
301
304
  bulkInput.classList.add('hidden');
305
+
306
+ // Move button back to original row
307
+ inputRow.appendChild(scrapeBtn);
308
+ scrapeBtn.classList.remove('w-full', 'mt-4');
302
309
  }
303
310
  }
304
311
 
@@ -1062,7 +1069,7 @@ function showError(msg) {
1062
1069
  const errorEl = document.getElementById('error');
1063
1070
  document.getElementById('errorMsg').textContent = msg;
1064
1071
  errorEl.classList.remove('hidden');
1065
- setTimeout(() => errorEl.classList.add('hidden'), 5000);
1072
+ setTimeout(() => errorEl.classList.add('hidden'), 10000);
1066
1073
  }
1067
1074
 
1068
1075
  // Entry animation & Auto-Clear
@@ -1215,6 +1222,31 @@ window.addEventListener('DOMContentLoaded', () => {
1215
1222
  // --- IMAGE ANALYSIS FEATURE ---
1216
1223
  let currentMode = 'scrape';
1217
1224
 
1225
+ const LOGO_WEBTOOLS = `██╗ ██╗███████╗██████╗ ████████╗ ██████╗ ██████╗ ██╗ ███████╗
1226
+ ██║ ██║██╔════╝██╔══██╗ ╚══██╔══╝██╔═══██╗██╔═══██╗██║ ██╔════╝
1227
+ ██║ █╗ ██║█████╗ ██████╔╝ ██║ ██║ ██║██║ ██║██║ ███████╗
1228
+ ██║███╗██║██╔══╝ ██╔══██╗ ██║ ██║ ██║██║ ██║██║ ╚════██║
1229
+ ╚███╔███╔╝███████╗██████╔╝ ██║ ╚██████╔╝╚██████╔╝███████╗███████║
1230
+ ╚══╝╚══╝ ╚══════╝╚═════╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚══════╝`;
1231
+
1232
+ const LOGO_FORENSICS = `██╗███╗ ███╗ █████╗ ██████╗ ███████╗ ███████╗ ██████╗ ██████╗ ███████╗███╗ ██╗███████╗██╗ ██████╗███████╗
1233
+ ██║████╗ ████║██╔══██╗██╔════╝ ██╔════╝ ██╔════╝██╔═══██╗██╔══██╗██╔════╝████╗ ██║██╔════╝██║██╔════╝██╔════╝
1234
+ ██║██╔████╔██║███████║██║ ███╗█████╗ █████╗ ██║ ██║██████╔╝█████╗ ██╔██╗ ██║███████╗██║██║ ███████╗
1235
+ ██║██║╚██╔╝██║██╔══██║██║ ██║██╔══╝ ██╔══╝ ██║ ██║██╔══██╗██╔══╝ ██║╚██╗██║╚════██║██║██║ ╚════██║
1236
+ ██║██║ ╚═╝ ██║██║ ██║╚██████╔╝███████╗ ██║ ╚██████╔╝██║ ██║███████╗██║ ╚████║███████║██║╚██████╗███████║
1237
+ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝╚══════╝╚═╝ ╚═════╝╚══════╝`;
1238
+
1239
+ function setHeaderLogo(text) {
1240
+ const pre = document.querySelector('.ascii-logo pre');
1241
+ if (!pre) return;
1242
+ pre.style.opacity = '0';
1243
+ pre.style.transition = 'opacity 0.25s ease';
1244
+ setTimeout(() => {
1245
+ pre.textContent = text;
1246
+ pre.style.opacity = '1';
1247
+ }, 250);
1248
+ }
1249
+
1218
1250
  function toggleImageMode() {
1219
1251
  const btn = document.getElementById('btn-image-mode');
1220
1252
  const scraperMode = document.getElementById('mode-scraper');
@@ -1233,6 +1265,9 @@ function toggleImageMode() {
1233
1265
  btn.classList.remove('text-indigo-400', 'bg-slate-800/50');
1234
1266
  btn.classList.add('text-slate-400');
1235
1267
 
1268
+ // Restore WEBTOOLS logo
1269
+ setHeaderLogo(LOGO_WEBTOOLS);
1270
+
1236
1271
  // Hide image results, show scrape results if they exist
1237
1272
  document.getElementById('image-results').classList.add('hidden');
1238
1273
  if(document.querySelector('.active-results')) document.getElementById('results').classList.remove('hidden');
@@ -1247,11 +1282,15 @@ function toggleImageMode() {
1247
1282
  btn.classList.add('text-indigo-400', 'bg-slate-800/50');
1248
1283
  btn.classList.remove('text-slate-400');
1249
1284
 
1285
+ // Switch to IMAGE FORENSICS logo
1286
+ setHeaderLogo(LOGO_FORENSICS);
1287
+
1250
1288
  // Hide scrape results
1251
1289
  document.getElementById('results').classList.add('hidden');
1252
1290
  }
1253
1291
  }
1254
1292
 
1293
+
1255
1294
  function handleImageUpload(input) {
1256
1295
  if (input.files && input.files[0]) {
1257
1296
  const reader = new FileReader();
@@ -1296,6 +1335,7 @@ function showError(msg) {
1296
1335
  if(errorEl) {
1297
1336
  errorEl.classList.remove('hidden');
1298
1337
  document.getElementById('errorMsg').textContent = msg;
1338
+ setTimeout(() => errorEl.classList.add('hidden'), 10000);
1299
1339
  } else {
1300
1340
  alert(msg);
1301
1341
  }
@@ -0,0 +1,410 @@
1
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap');
2
+
3
+ /* =============================================
4
+ DESIGN TOKENS — matches landing page
5
+ ============================================= */
6
+ :root {
7
+ --bg-dark: #050508;
8
+ --bg-card: rgba(255, 255, 255, 0.03);
9
+ --text-primary: #f0f0f0;
10
+ --text-secondary: #888;
11
+ --accent-blue: #3b82f6;
12
+ --accent-purple: #8b5cf6;
13
+ --glass-border: rgba(255, 255, 255, 0.08);
14
+ --gradient-primary: linear-gradient(135deg, #3b82f6, #8b5cf6, #06b6d4);
15
+ --font-main: 'Inter', sans-serif;
16
+ --font-mono: 'JetBrains Mono', monospace;
17
+ }
18
+
19
+ /* =============================================
20
+ BASE
21
+ ============================================= */
22
+ *, *::before, *::after { box-sizing: border-box; }
23
+
24
+ body {
25
+ font-family: var(--font-main) !important;
26
+ background-color: var(--bg-dark) !important;
27
+ color: var(--text-primary) !important;
28
+ position: relative;
29
+ overflow-x: hidden;
30
+ }
31
+
32
+ /* Flickering grid background */
33
+ .grid-bg {
34
+ position: fixed;
35
+ inset: 0;
36
+ z-index: 0;
37
+ pointer-events: none;
38
+ background-image:
39
+ linear-gradient(rgba(255,255,255,0.025) 1px, transparent 1px),
40
+ linear-gradient(90deg, rgba(255,255,255,0.025) 1px, transparent 1px);
41
+ background-size: 40px 40px;
42
+ mask-image: radial-gradient(ellipse 80% 80% at 50% 50%, black, transparent);
43
+ -webkit-mask-image: radial-gradient(ellipse 80% 80% at 50% 50%, black, transparent);
44
+ }
45
+
46
+ /* Glow orbs */
47
+ .glow-orb {
48
+ position: fixed;
49
+ width: 600px;
50
+ height: 600px;
51
+ border-radius: 50%;
52
+ background: radial-gradient(circle, rgba(59, 130, 246, 0.12) 0%, transparent 70%);
53
+ pointer-events: none;
54
+ z-index: 0;
55
+ }
56
+
57
+ /* Ensure content sits above bg */
58
+ .container { position: relative; z-index: 1; }
59
+
60
+ /* =============================================
61
+ GLASS CARDS
62
+ ============================================= */
63
+ .glass-dark {
64
+ background: rgba(10, 10, 20, 0.6) !important;
65
+ backdrop-filter: blur(20px) !important;
66
+ -webkit-backdrop-filter: blur(20px) !important;
67
+ border: 1px solid var(--glass-border) !important;
68
+ }
69
+
70
+ /* =============================================
71
+ HEADER / TITLE
72
+ ============================================= */
73
+ #main-header h1 {
74
+ font-family: var(--font-main) !important;
75
+ font-weight: 800 !important;
76
+ background: var(--gradient-primary) !important;
77
+ -webkit-background-clip: text !important;
78
+ background-clip: text !important;
79
+ -webkit-text-fill-color: transparent !important;
80
+ }
81
+
82
+ /* =============================================
83
+ INPUTS
84
+ ============================================= */
85
+ input[type="url"],
86
+ input[type="text"],
87
+ input[type="number"],
88
+ textarea,
89
+ select {
90
+ background: rgba(0, 0, 0, 0.5) !important;
91
+ border: 1px solid var(--glass-border) !important;
92
+ color: var(--text-primary) !important;
93
+ border-radius: 12px !important;
94
+ font-family: var(--font-main) !important;
95
+ transition: border-color 0.3s, box-shadow 0.3s !important;
96
+ }
97
+
98
+ input[type="url"]:focus,
99
+ input[type="text"]:focus,
100
+ textarea:focus,
101
+ select:focus {
102
+ border-color: var(--accent-blue) !important;
103
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15) !important;
104
+ outline: none !important;
105
+ }
106
+
107
+ /* =============================================
108
+ SCRAPE / PRIMARY BUTTON
109
+ ============================================= */
110
+ .scrape-btn-custom {
111
+ background: linear-gradient(135deg, #1e40af, #6d28d9, #0891b2) !important;
112
+ border: 1px solid rgba(255, 255, 255, 0.1) !important;
113
+ border-radius: 12px !important;
114
+ color: white !important;
115
+ font-weight: 700 !important;
116
+ font-family: var(--font-main) !important;
117
+ transition: all 0.3s ease !important;
118
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5) !important;
119
+ }
120
+
121
+ .scrape-btn-custom:hover {
122
+ filter: brightness(1.2) !important;
123
+ box-shadow: 0 6px 30px rgba(0, 0, 0, 0.6) !important;
124
+ }
125
+
126
+ .scrape-btn-custom:active {
127
+ transform: scale(0.97) !important;
128
+ }
129
+
130
+ /* =============================================
131
+ TABS
132
+ ============================================= */
133
+ .tab-active {
134
+ border-bottom: 2px solid var(--accent-blue) !important;
135
+ color: var(--accent-blue) !important;
136
+ }
137
+
138
+ #tab-intel.tab-active {
139
+ border-bottom: 2px solid #f97316 !important;
140
+ color: #f97316 !important;
141
+ }
142
+
143
+ #tab-intel:hover { color: #fb923c !important; }
144
+
145
+ /* =============================================
146
+ CODE EDITOR
147
+ ============================================= */
148
+ .code-editor {
149
+ font-family: var(--font-mono) !important;
150
+ background: #0a0a0f !important;
151
+ color: #e2e8f0 !important;
152
+ border: 1px solid var(--glass-border) !important;
153
+ border-radius: 12px !important;
154
+ }
155
+
156
+ /* =============================================
157
+ SCROLLBARS
158
+ ============================================= */
159
+ ::-webkit-scrollbar { width: 6px; height: 6px; }
160
+ ::-webkit-scrollbar-track { background: transparent; }
161
+ ::-webkit-scrollbar-thumb {
162
+ background: rgba(59, 130, 246, 0.3);
163
+ border-radius: 4px;
164
+ }
165
+ ::-webkit-scrollbar-thumb:hover {
166
+ background: rgba(59, 130, 246, 0.6);
167
+ }
168
+
169
+ #content-intel ::-webkit-scrollbar-thumb { background: rgba(249, 115, 22, 0.4); }
170
+
171
+ /* =============================================
172
+ LOADING BORDER ANIMATION
173
+ ============================================= */
174
+ @keyframes border-rotate {
175
+ 100% { transform: translate(-50%, -50%) rotate(360deg); }
176
+ }
177
+
178
+ .loading-beam-border {
179
+ position: relative;
180
+ overflow: hidden !important;
181
+ border-color: transparent !important;
182
+ }
183
+
184
+ .loading-beam-border::before {
185
+ content: '';
186
+ position: absolute;
187
+ top: 50%; left: 50%;
188
+ width: 200%; height: 200%;
189
+ background: conic-gradient(from 0deg, transparent 60%, #3b82f6cc 80%, #8b5cf6 100%);
190
+ animation: border-rotate 3s linear infinite;
191
+ transform: translate(-50%, -50%);
192
+ z-index: -2;
193
+ }
194
+
195
+ .loading-beam-border::after {
196
+ content: '';
197
+ position: absolute;
198
+ inset: 0.5px;
199
+ background: #080810;
200
+ border-radius: inherit;
201
+ z-index: -1;
202
+ }
203
+
204
+ /* =============================================
205
+ TAB GRADIENT BORDER ANIMATION
206
+ ============================================= */
207
+ @property --beam-angle { syntax: '<angle>'; initial-value: 0deg; inherits: false; }
208
+
209
+ .tab-gradient-border {
210
+ position: relative;
211
+ background: transparent !important;
212
+ border: none !important;
213
+ box-shadow: none !important;
214
+ }
215
+
216
+ .tab-gradient-border::before {
217
+ content: "";
218
+ position: absolute;
219
+ inset: 0;
220
+ border-radius: 1rem;
221
+ padding: 2px;
222
+ background: conic-gradient(from var(--beam-angle), #00000000, #3b82f6, #8b5cf6, #00000000);
223
+ -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
224
+ mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
225
+ -webkit-mask-composite: xor;
226
+ mask-composite: exclude;
227
+ pointer-events: none;
228
+ z-index: 0;
229
+ animation: beam-rotate 4s linear infinite;
230
+ }
231
+
232
+ @keyframes beam-rotate { to { --beam-angle: 360deg; } }
233
+
234
+ /* =============================================
235
+ TREE VIEW
236
+ ============================================= */
237
+ .tree-view { font-family: var(--font-mono); font-size: 0.85rem; }
238
+ .tree-item { position: relative; padding-left: 1.5rem; margin-top: 0.5rem; }
239
+ .tree-item::before {
240
+ content: "";
241
+ position: absolute; left: 0; top: 0; bottom: 0;
242
+ width: 1px; background: rgba(59, 130, 246, 0.2);
243
+ }
244
+ .tree-item::after {
245
+ content: "";
246
+ position: absolute; left: 0; top: 0.7rem;
247
+ width: 1rem; height: 1px;
248
+ background: rgba(59, 130, 246, 0.2);
249
+ }
250
+ .tree-item:last-child::before { height: 0.7rem; }
251
+
252
+ /* =============================================
253
+ PREVIEW FRAME
254
+ ============================================= */
255
+ .preview-frame {
256
+ background: white;
257
+ border: none;
258
+ width: 100%;
259
+ height: 600px;
260
+ border-radius: 12px;
261
+ }
262
+
263
+ /* =============================================
264
+ VIDEO CARDS
265
+ ============================================= */
266
+ .video-card {
267
+ background: var(--bg-card) !important;
268
+ border: 1px solid var(--glass-border) !important;
269
+ box-shadow: 0 4px 20px rgba(0,0,0,0.3) !important;
270
+ transition: all 0.3s ease !important;
271
+ }
272
+ .video-card:hover {
273
+ box-shadow: 0 8px 40px rgba(59, 130, 246, 0.2) !important;
274
+ border-color: rgba(59, 130, 246, 0.3) !important;
275
+ }
276
+
277
+ /* =============================================
278
+ BLUR FADE IN ANIMATION
279
+ ============================================= */
280
+ @keyframes blurFadeIn {
281
+ from { opacity: 0; filter: blur(10px); transform: scale(0.95); }
282
+ to { opacity: 1; filter: blur(0); transform: scale(1); }
283
+ }
284
+ .animate-blur-fade {
285
+ animation: blurFadeIn 0.6s cubic-bezier(0.16, 1, 0.3, 1) forwards;
286
+ }
287
+
288
+ /* =============================================
289
+ COMPACT INTELLIGENCE SECTION
290
+ ============================================= */
291
+ #content-seo {
292
+ max-height: 75vh;
293
+ overflow-y: auto;
294
+ padding-right: 4px;
295
+ }
296
+
297
+ #content-seo h3 {
298
+ font-size: 0.8rem !important;
299
+ margin-bottom: 0.5rem !important;
300
+ }
301
+
302
+ #content-seo h4 {
303
+ font-size: 0.7rem !important;
304
+ margin-bottom: 0.4rem !important;
305
+ }
306
+
307
+ /* Compact cards */
308
+ #content-seo [class*="rounded-2xl"],
309
+ #content-seo [class*="rounded-xl"] {
310
+ padding: 0.6rem 0.8rem !important;
311
+ margin-bottom: 0.5rem !important;
312
+ border-radius: 10px !important;
313
+ }
314
+
315
+ /* Tighter space-y gaps */
316
+ #content-seo [class*="space-y-4"],
317
+ #content-seo [class*="space-y-6"],
318
+ #content-seo [class*="space-y-3"] {
319
+ gap: 0.4rem !important;
320
+ }
321
+ #content-seo [class*="space-y-4"] > *,
322
+ #content-seo [class*="space-y-6"] > *,
323
+ #content-seo [class*="space-y-3"] > *,
324
+ #content-seo [class*="space-y-4"] > * + *,
325
+ #content-seo [class*="space-y-6"] > * + *,
326
+ #content-seo [class*="space-y-3"] > * + * {
327
+ margin-top: 0.35rem !important;
328
+ }
329
+
330
+ /* Tighter grid gaps */
331
+ #content-seo [class*="grid"] {
332
+ gap: 0.4rem !important;
333
+ }
334
+
335
+ /* Smaller text throughout */
336
+ #content-seo p,
337
+ #content-seo span:not([class*="text-2xl"]),
338
+ #content-seo a,
339
+ #content-seo td,
340
+ #content-seo th {
341
+ font-size: 0.72rem !important;
342
+ }
343
+
344
+ /* Compact table rows */
345
+ #content-seo table th,
346
+ #content-seo table td {
347
+ padding: 0.3rem 0.6rem !important;
348
+ }
349
+
350
+ /* Compact intel-contacts items */
351
+ #intel-contacts > div,
352
+ #intel-locations > div {
353
+ padding: 0.2rem 0 !important;
354
+ gap: 0.4rem !important;
355
+ }
356
+
357
+ /* Compact AI score numbers — keep them readable */
358
+ #ai-sentiment-score,
359
+ #ai-readability-score {
360
+ font-size: 1.4rem !important;
361
+ margin-bottom: 0.25rem !important;
362
+ }
363
+
364
+ /* Compact keyword tags */
365
+ #content-seo [class*="px-3 py-1.5"] {
366
+ padding: 0.2rem 0.5rem !important;
367
+ }
368
+
369
+ /* mb-4 -> mb-2 overrides inside intel */
370
+ #content-seo [class*="mb-4"] {
371
+ margin-bottom: 0.4rem !important;
372
+ }
373
+ #content-seo [class*="mb-6"] {
374
+ margin-bottom: 0.5rem !important;
375
+ }
376
+
377
+ .hacker-theme {
378
+ --bg-color: #000000;
379
+ --text-color: #00ff41;
380
+ --accent-color: #008F11;
381
+ background-color: var(--bg-color) !important;
382
+ color: var(--text-color) !important;
383
+ font-family: var(--font-mono) !important;
384
+ }
385
+ .hacker-theme .glass-dark {
386
+ background: rgba(0, 10, 0, 0.95) !important;
387
+ border: 1px solid var(--text-color) !important;
388
+ box-shadow: 0 0 10px var(--accent-color) !important;
389
+ }
390
+ .hacker-theme .text-slate-400,
391
+ .hacker-theme .text-slate-500,
392
+ .hacker-theme .text-gray-400 { color: #008F11 !important; }
393
+ .hacker-theme .text-white,
394
+ .hacker-theme h1,
395
+ .hacker-theme h2,
396
+ .hacker-theme h3 { color: var(--text-color) !important; }
397
+ .hacker-theme input,
398
+ .hacker-theme select,
399
+ .hacker-theme textarea {
400
+ background-color: #001100 !important;
401
+ border-color: var(--text-color) !important;
402
+ color: var(--text-color) !important;
403
+ }
404
+ .hacker-theme .scrape-btn-custom {
405
+ background: #000 !important;
406
+ border: 1px solid var(--text-color) !important;
407
+ box-shadow: 0 0 15px var(--text-color) !important;
408
+ color: var(--text-color) !important;
409
+ }
410
+ .hacker-theme svg { color: var(--text-color) !important; }
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: webtools-cli
3
- Version: 1.0.4
3
+ Version: 1.0.6
4
4
  Summary: Advanced Web Intelligence & Scraping Toolkit with CLI and Web UI
5
5
  Author: Abhinav Adarsh
6
6
  License-Expression: MIT
7
- Project-URL: Homepage, https://github.com/abhinavgautam08/webtools-cli
7
+ Project-URL: Homepage, https://webtoolscli.pages.dev
8
8
  Keywords: web-scraping,osint,seo,intelligence,cli
9
9
  Classifier: Development Status :: 4 - Beta
10
10
  Classifier: Environment :: Console
@@ -41,7 +41,9 @@ Dynamic: license-file
41
41
 
42
42
  ![WebTools CLI Interface](https://i.postimg.cc/7LXjQqBm/CLI.png)
43
43
 
44
- WebTools CLI is an advanced web intelligence suite for researchers, OSINT enthusiasts, and developers. It brings the power of deep web analysis and automated scraping directly into your terminal, bridging the gap between a high-speed **Terminal UI** and a feature-rich **Cyber-themed Dashboard**.
44
+ try : [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1l4-ZChKGYhOFrPwp2_JPLJ1X0ZYSVrZk?usp=sharing)
45
+
46
+ An advanced web intelligence suite for researchers, OSINT enthusiasts, and developers. It brings the power of deep web analysis and automated scraping directly into your terminal.
45
47
 
46
48
  ---
47
49
 
@@ -79,6 +81,7 @@ pip install webtools-cli --upgrade
79
81
  For Single Page Application (SPA) support:
80
82
 
81
83
  ```bash
84
+ pip install "webtools-cli[playwright]"
82
85
  playwright install chromium
83
86
  ```
84
87
 
@@ -99,9 +102,9 @@ playwright install chromium
99
102
  - **Honeypot Detector**: Identifies hidden traps and anti-bot measures (Cloudflare/CAPTCHAs).
100
103
 
101
104
  ### Modern Experience
102
- - **Matrix Background**: "Flickering Grid" animated dashboard (Canvas-based).
103
- - **Responsive Preview**: Live rendering scaling for desktop and mobile viewpoints.
104
- - **History & Stats**: Phase-by-phase performance tracking and historical session management.
105
+ - **Premium Visual Engine**: Sleek glassmorphism, fluid gradients, and premium Motion One animations.
106
+ - **Edge-to-Edge Responsiveness**: Rock-solid layout stability on every device, from iPhone SE to 4K monitors.
107
+ - **Dynamic Interactions**: Flickering grid backgrounds, hover-glow effects, and high-performance transitions.
105
108
 
106
109
  ---
107
110
 
@@ -158,5 +161,11 @@ This tool is for **educational and testing purposes only**. Always respect `robo
158
161
  ---
159
162
 
160
163
  <p align="center">
161
- Built with ❤️ by <strong>Abhinav Adarsh</strong> and the open source community
164
+ Built with ❤️ by
165
+ <strong>
166
+ <a href="https://abhinavgautam08.pages.dev/" target="_blank" rel="noopener noreferrer">
167
+ Abhinav Adarsh
168
+ </a>
169
+ </strong>
170
+ and the open source community
162
171
  </p>
@@ -5,7 +5,6 @@ webtools/__init__.py
5
5
  webtools/__main__.py
6
6
  webtools/cli.py
7
7
  webtools/core.py
8
- webtools/web/Web_Tools.png
9
8
  webtools/web/index.html
10
9
  webtools/web/script.js
11
10
  webtools/web/style.css
@@ -1,71 +0,0 @@
1
- @import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');
2
- body {
3
- font-family: 'Outfit', sans-serif;
4
- }
5
- .glass-dark {
6
- background: rgba(30, 41, 59, 0.7);
7
- backdrop-filter: blur(20px);
8
- border: 1px solid #ffffff14;
9
- }
10
- @keyframes border-rotate {
11
- 100% { transform: translate(-50%, -50%) rotate(360deg); }
12
- }
13
- .loading-beam-border {
14
- position: relative; overflow: hidden !important; border-color: transparent !important;
15
- }
16
- .loading-beam-border::before {
17
- content: ''; position: absolute; top: 50%; left: 50%; width: 200%; height: 200%;
18
- background: conic-gradient(from 0deg, transparent 60%, #6366f1cc 80%, #ec4899 100%);
19
- animation: border-rotate 3s linear infinite;
20
- transform: translate(-50%, -50%); z-index: -2;
21
- }
22
- .loading-beam-border::after {
23
- content: ''; position: absolute; inset: 0.5px; background: #1e293b; border-radius: inherit; z-index: -1;
24
- }
25
- .code-editor {
26
- font-family: 'JetBrains Mono', monospace; background: #1e1e1e; color: #d4d4d4;
27
- }
28
- .preview-frame {
29
- background: white; border: none; width: 100%; height: 600px; border-radius: 0.75rem;
30
- }
31
- ::-webkit-scrollbar { width: 8px; height: 8px; }
32
- ::-webkit-scrollbar-track { background: transparent; }
33
- ::-webkit-scrollbar-thumb { background: #475569; border-radius: 4px; }
34
- .tab-active { border-bottom: 2px solid #3d3e5a; color: #a3a3c9; }
35
- .video-card { background: transparent !important; border: 1px solid #00000000 !important; box-shadow: 0 0 10px #0000004d !important; }
36
- .video-card:hover { box-shadow: 0 0 20px #00000080 !important; border-color: #000000 !important; }
37
- .scrape-btn-custom { background: linear-gradient(#020617, #020617) padding-box, linear-gradient(to right, #db2777, #7c3aed) border-box; border: 2px solid transparent !important; border-radius: 0.75rem; transition: all 0.3s ease; }
38
- .scrape-btn-custom:hover { background: linear-gradient(#0f172a, #0f172a) padding-box, linear-gradient(to right, #db2777, #7c3aed) border-box; }
39
- .scrape-btn-custom:active { transform: scale(0.95); }
40
- .hacker-theme { --bg-color: #000000; --text-color: #00ff41; --accent-color: #008F11; background-color: var(--bg-color) !important; color: var(--text-color) !important; font-family: 'JetBrains Mono', monospace !important; }
41
- .hacker-theme .glass-dark { background: rgba(0, 10, 0, 0.95); border: 1px solid var(--text-color); box-shadow: 0 0 10px var(--accent-color); }
42
- .hacker-theme .text-slate-400, .hacker-theme .text-slate-500, .hacker-theme .text-gray-400 { color: #008F11 !important; }
43
- .hacker-theme .text-white, .hacker-theme h1, .hacker-theme h2, .hacker-theme h3 { color: var(--text-color) !important; }
44
- .hacker-theme input, .hacker-theme select, .hacker-theme textarea { background-color: #001100 !important; border-color: var(--text-color) !important; color: var(--text-color) !important; }
45
- .hacker-theme .scrape-btn-custom { background: #000 !important; border: 1px solid var(--text-color) !important; box-shadow: 0 0 15px var(--text-color) !important; color: var(--text-color) !important; }
46
- .hacker-theme svg { color: var(--text-color) !important; }
47
- @property --beam-angle { syntax: '<angle>'; initial-value: 0deg; inherits: false; }
48
- .tab-gradient-border { position: relative; background: transparent !important; border: none !important; box-shadow: none !important; }
49
- .tab-gradient-border::before { content: ""; position: absolute; inset: 0; border-radius: 1rem; padding: 2px; background: conic-gradient(from var(--beam-angle), #00000000); -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); -webkit-mask-composite: xor; mask-composite: exclude; pointer-events: none; z-index: 0; animation: beam-rotate 4s linear infinite; }
50
- @keyframes beam-rotate { to { --beam-angle: 360deg; } }
51
- .tree-view { font-family: 'JetBrains Mono', monospace; font-size: 0.85rem; }
52
- .tree-item { position: relative; padding-left: 1.5rem; margin-top: 0.5rem; }
53
- .tree-item::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 1px; background: #334155; }
54
- .tree-item::after { content: ""; position: absolute; left: 0; top: 0.7rem; width: 1rem; height: 1px; background: #334155; }
55
- .tree-item:last-child::before { height: 0.7rem; }
56
- @keyframes blurFadeIn {
57
- from { opacity: 0; filter: blur(10px); transform: scale(0.95); }
58
- to { opacity: 1; filter: blur(0); transform: scale(1); } }
59
- .animate-blur-fade {
60
- animation: blurFadeIn 0.6s cubic-bezier(0.16, 1, 0.3, 1) forwards;
61
- }
62
- #tab-intel.tab-active {
63
- border-bottom: 2px solid #f9741628; /* Orange-500 */
64
- color: #f9741688;
65
- }
66
- #tab-intel:hover {
67
- color: #fdbb7437; /* Orange-500 */
68
- }
69
- #content-intel ::-webkit-scrollbar-thumb {
70
- background: #c2400c75;
71
- }
File without changes
File without changes