import ctypes
import os
import shutil
import subprocess
import sys
import uuid
import urllib.request
import zipfile
import json


def elevate_privileges():
    """Checks if the script is running with Administrator privileges on Windows."""
    try:
        if not ctypes.windll.shell32.IsUserAnAdmin():
            print("[!] Administrator privileges required. Prompting for UAC...")
            ctypes.windll.shell32.ShellExecuteW(
                None, "runas", sys.executable, " ".join(sys.argv), None, 1
            )
            sys.exit(0)
    except Exception as e:
        print(f"[-] Failed to elevate privileges automatically: {e}")
        sys.exit(1)


# Enforce Windows Administrator elevation immediately on startup
elevate_privileges()


def get_base_dir():
    """Returns the base directory (next to .exe if frozen, next to .py if script)."""
    if getattr(sys, 'frozen', False):
        return os.path.dirname(sys.executable)
    else:
        return os.path.dirname(os.path.abspath(__file__))


def check_nmap_setup():
    """Checks if Nmap is properly set up. If not, guides the user through installation."""
    base_dir = get_base_dir()
    nmap_dir = os.path.join(base_dir, "Nmap")
    nmap_installer = os.path.join(nmap_dir, "nmap-7.991-setup.exe")
    nmap_exe = os.path.join(nmap_dir, "nmap.exe")
    flag_file = os.path.join(base_dir, "Nmap-Installed.flag")
    
    # Check if Nmap is already installed and working
    if os.path.exists(nmap_exe):
        current_path = os.environ.get("PATH", "")
        if nmap_dir not in current_path:
            os.environ["PATH"] = nmap_dir + os.pathsep + current_path
        return True
    
    # Check if user has already been prompted
    if os.path.exists(flag_file):
        # Silently return whether it exists or not, no printing as requested
        return os.path.exists(nmap_exe)
    
    # First time - show message and launch installer
    try:
        import tkinter as tk
        from tkinter import messagebox
        
        root = tk.Tk()
        root.withdraw()  # Hide the main window
        root.attributes('-topmost', True)  # Bring to front
        
        messagebox.showinfo(
            "HackaShell - Nmap Required",
            "You must download and install Nmap.\n\n"
            "Please place the Nmap installer (nmap-7.991-setup.exe) in the 'Nmap' folder\n"
            "next to HackaShell, then click OK to begin installation.\n\n"
            "After installation completes, run HackaShell again."
        )
        
        root.destroy()
        
        if not os.path.exists(nmap_installer):
            print("[-] Nmap installer not found!")
            print(f"[-] Please download nmap-7.991-setup.exe from https://nmap.org/download.html")
            print(f"[-] and place it in: {nmap_dir}")
            print("[*] Creating flag file...")
            with open(flag_file, "w") as f:
                f.write("pending")
            sys.exit(0)
        
        print("[*] Creating installation flag...")
        with open(flag_file, "w") as f:
            f.write("installing")
        
        print("[*] Launching Nmap installer...")
        print(f"[*] Installer: {nmap_installer}")
        print("[*] IMPORTANT: Install to the following folder:")
        print(f"[*] {nmap_dir}")
        print("[*] HackaShell will close now. Run it again after installation completes.")
        
        subprocess.run([nmap_installer])
        sys.exit(0)
        
    except ImportError:
        print("[-] tkinter not available for GUI message.")
        print("[-] Please download Nmap manually from https://nmap.org/download.html")
        print(f"[-] Install it to: {nmap_dir}")
        sys.exit(1)


# Run Nmap setup check on startup
check_nmap_setup()


def check_and_install_packages():
    """Checks if python-nmap and evil-winrm-py are available."""
    nmap_installed = True
    try:
        import nmap
    except ImportError:
        nmap_installed = False

    evil_winrm_installed = (
        shutil.which("evil-winrm-py") is not None
        or shutil.which("evil-winrm") is not None
    )
    if not evil_winrm_installed and shutil.which("pipx"):
        try:
            result = subprocess.run(
                ["pipx", "list"], capture_output=True, text=True, check=True
            )
            if "evil-winrm-py" in result.stdout:
                evil_winrm_installed = True
        except Exception:
            pass

    if not nmap_installed or not evil_winrm_installed:
        print("[!] Some required tools/packages are missing. Resolving...")

        if not nmap_installed:
            print("[*] Installing python-nmap via pip...")
            try:
                subprocess.check_call([sys.executable, "-m", "pip", "install", "python-nmap"])
            except Exception as e:
                print(f"[-] Failed to install python-nmap: {e}")

        if not evil_winrm_installed:
            if shutil.which("pipx"):
                print("[*] Installing evil-winrm-py via pipx...")
                try:
                    subprocess.check_call(["pipx", "install", "evil-winrm-py"])
                except Exception as e:
                    print(f"[-] Failed to install evil-winrm-py via pipx: {e}")
            else:
                print("[*] pipx not found. Installing evil-winrm-py via pip...")
                try:
                    subprocess.check_call([sys.executable, "-m", "pip", "install", "evil-winrm-py"])
                except Exception as e:
                    print(f"[-] Failed to install evil-winrm-py: {e}")

        print("[+] Setup completed! Restarting HackaShell...")
        os.execv(sys.executable, [sys.executable] + sys.argv)


# Run dependency checks on startup
check_and_install_packages()

import nmap


def get_packages_dir():
    return os.path.join(get_base_dir(), "Packages")


def get_portable_python_dir():
    return os.path.join(get_base_dir(), "Portable_Python")


def find_portable_python():
    portable_dir = get_portable_python_dir()
    if not os.path.exists(portable_dir):
        return None
    for root, dirs, files in os.walk(portable_dir):
        for file in files:
            if file.lower() == "python.exe":
                return os.path.join(root, file)
    return None


def get_wifi_mac():
    """Retrieves the current MAC address of the Wi-Fi adapter."""
    try:
        result = subprocess.run(['getmac', '/v', '/fo', 'csv'], capture_output=True, text=True, check=True)
        for line in result.stdout.strip().split('\n'):
            if 'Wi-Fi' in line:
                parts = line.split(',')
                if len(parts) >= 3:
                    return parts[2].strip('"').strip()
    except Exception:
        pass
    return "Unknown"


def banner():
    font = {
        "H": [r" _   _ ", r"| | | |", r"| |_| |", r"|  _  |", r"| | | |", r"|_| |_|"],
        "a": [r"       ", r"  __ _ ", r" / _` |", r"| (_| |", r" \__,_|", r"       "],
        "c": [r"       ", r"  ___  ", r" / __| ", r"| (__  ", r" \___| ", r"       "],
        "k": [r" _     ", r"| | __ ", r"| |/ / ", r"| ' <  ", r"|_|\_\ ", r"       "],
        "S": [r" ____  ", r"/ ___| ", r"\___ \ ", r" ___) |", r"|____/ ", r"       "],
        "h": [r" _     ", r"| |__  ", r"| '_ \ ", r"| | | |", r"|_| |_|", r"       "],
        "e": [r"       ", r"  ___  ", r" / _ \ ", r"|  __/ ", r" \___| ", r"       "],
        "l": [r" _   ", r"| |  ", r"| |  ", r"| |  ", r"|_|  ", r"     "],
    }
    lines = [""] * 6
    for ch in "HackaShell":
        for i in range(6):
            lines[i] += font[ch][i]

    print()
    for line in lines:
        print(line.rstrip())
    print()
    print("        [ Terminal for Hacking & Reconnaissance ]")
    print()
    print("Welcome to HackaShell (Windows Administrator Mode)")
    print("Type 'help' to see available commands.\n")


def print_help():
    print("--- HackaShell Command Manual ---")
    print("  clear                     - Clears the terminal screen")
    print("  help                      - Shows this help menu")
    print("  exit                      - Exits HackaShell")
    print("  Scan My Network           - Scans the router and all devices on the network")
    print("  Scan <IP/Domain>          - Quick port scan on ANY target IP or domain")
    print("  Scan 192.168.0.1          - Scans the router and all devices on the network")
    print("  Scan <IP/Domain> for OS   - Detailed OS and version detection")
    print("  evil-winrm-py ...         - Run WinRM shell commands")
    print("  hs (package here)         - Install a package (e.g., hs vbrev)")
    print("  hs list                   - Lists all installed and available packages")
    print("  hs make <file> public link- Uploads a file and returns a public link")

    if os.path.exists(os.path.join(get_packages_dir(), "Vbrev")):
        print("  Vbrev Launch              - Launches VbRevUi.exe")

    if os.path.exists(os.path.join(get_packages_dir(), "Ncat.exe")):
        print("  ncat <args>               - Run Ncat (e.g., ncat -lvp 4444)")

    if os.path.exists(os.path.join(get_packages_dir(), "macshift.exe")):
        print("  macspoof wifi             - Spoofs Wi-Fi MAC address (shows old and new)")
        print("  macspoof disconnect       - Disconnects and restores original MAC address")

    if os.path.exists(os.path.join(get_packages_dir(), "maigret_standalone.exe")):
        print("  username <user>           - Search for username across social networks (Maigret)")

    if os.path.exists(get_portable_python_dir()):
        print("  py mode                   - Enters portable Python terminal")
        print("  py exit                   - Exits Python mode back to HackaShell")

    print("  Pinggy <port>             - Creates a public TCP link via Pinggy")
    print("-" * 33)


def install_vbrev():
    packages_dir = get_packages_dir()
    os.makedirs(packages_dir, exist_ok=True)
    vbrev_dir = os.path.join(packages_dir, "Vbrev")

    if os.path.exists(vbrev_dir):
        print("[*] Vbrev is already installed.")
        return

    print("[*] Downloading Vbrev...")
    zip_url = "https://github.com/VbScrub/VbRev/releases/download/v0.4/VbRev.zip"
    zip_path = os.path.join(packages_dir, "VbRev.zip")

    try:
        req = urllib.request.Request(zip_url, headers={'User-Agent': 'Mozilla/5.0'})
        with urllib.request.urlopen(req) as response, open(zip_path, 'wb') as out_file:
            out_file.write(response.read())
        print("[*] Extracting Vbrev...")
        with zipfile.ZipFile(zip_path, 'r') as zip_ref:
            zip_ref.extractall(vbrev_dir)
        os.remove(zip_path)
        print("[+] Vbrev installed successfully!")
    except Exception as e:
        print(f"[-] Failed to install Vbrev: {e}")


def install_ncat():
    packages_dir = get_packages_dir()
    os.makedirs(packages_dir, exist_ok=True)
    ncat_path = os.path.join(packages_dir, "Ncat.exe")

    if os.path.exists(ncat_path):
        print("[*] Ncat is already installed.")
        return

    print("[*] Downloading Ncat...")
    exe_url = "https://github.com/Dkwizard01/Updated-Portable-Ncat-exe/releases/download/Ncat/Ncat-V1.exe"

    try:
        req = urllib.request.Request(exe_url, headers={'User-Agent': 'Mozilla/5.0'})
        with urllib.request.urlopen(req) as response, open(ncat_path, 'wb') as out_file:
            out_file.write(response.read())
        print("[+] Ncat installed successfully!")
    except Exception as e:
        print(f"[-] Failed to install Ncat: {e}")
        if os.path.exists(ncat_path):
            os.remove(ncat_path)


def install_macspoofing():
    """Downloads MacShift into the Packages folder."""
    packages_dir = get_packages_dir()
    os.makedirs(packages_dir, exist_ok=True)
    macshift_path = os.path.join(packages_dir, "macshift.exe")

    if os.path.exists(macshift_path):
        print("[*] MacSpoofing (MacShift) is already installed.")
        return

    print("[*] Downloading MacShift...")
    exe_url = "https://www.nayuki.io/res/macshift-nayukis-version/macshift.exe"

    try:
        req = urllib.request.Request(exe_url, headers={'User-Agent': 'Mozilla/5.0'})
        with urllib.request.urlopen(req) as response, open(macshift_path, 'wb') as out_file:
            out_file.write(response.read())
        print("[+] MacSpoofing installed successfully!")
    except Exception as e:
        print(f"[-] Failed to install MacSpoofing: {e}")
        if os.path.exists(macshift_path):
            os.remove(macshift_path)


def install_username():
    """Downloads Maigret username scanner into the Packages folder."""
    packages_dir = get_packages_dir()
    os.makedirs(packages_dir, exist_ok=True)
    maigret_path = os.path.join(packages_dir, "maigret_standalone.exe")

    if os.path.exists(maigret_path):
        print("[*] Username scanner (Maigret) is already installed.")
        return

    print("[*] Downloading Maigret username scanner...")
    exe_url = "https://github.com/soxoj/maigret/releases/download/nightly-main/maigret_standalone.exe"

    try:
        req = urllib.request.Request(exe_url, headers={'User-Agent': 'Mozilla/5.0'})
        with urllib.request.urlopen(req) as response, open(maigret_path, 'wb') as out_file:
            out_file.write(response.read())
        print("[+] Username scanner (Maigret) installed successfully!")
    except Exception as e:
        print(f"[-] Failed to install Maigret: {e}")
        if os.path.exists(maigret_path):
            os.remove(maigret_path)


def launch_vbrev():
    packages_dir = get_packages_dir()
    exe_path = None
    for root, dirs, files in os.walk(packages_dir):
        for file in files:
            if file.lower() == "vbrevui.exe":
                exe_path = os.path.join(root, file)
                break
        if exe_path:
            break
    if exe_path:
        print(f"[*] Launching {exe_path}...")
        subprocess.Popen([exe_path])
    else:
        print("[-] VbRevUi.exe not found. Is Vbrev installed? Try: hs vbrev")


def run_ncat(raw_command):
    packages_dir = get_packages_dir()
    ncat_path = os.path.join(packages_dir, "Ncat.exe")
    if not os.path.exists(ncat_path):
        print("[-] Ncat is not installed. Try: hs ncat")
        return
    parts = raw_command.split()
    args = parts[1:]
    print(f"[*] Running Ncat with args: {' '.join(args)}...")
    try:
        subprocess.run([ncat_path] + args)
    except Exception as e:
        print(f"[-] Failed to run Ncat: {e}")


def run_macspoof_wifi():
    """Spoofs the Wi-Fi MAC address and displays old/new."""
    packages_dir = get_packages_dir()
    macshift_path = os.path.join(packages_dir, "macshift.exe")
    
    if not os.path.exists(macshift_path):
        print("[-] MacSpoofing is not installed. Try: hs macspoofing")
        return
    
    old_mac = get_wifi_mac()
    print(f"[*] Current Wi-Fi MAC Address: {old_mac}")
    print("[*] Running MacShift to spoof MAC address...")
    
    try:
        result = subprocess.run([macshift_path, "Wi-Fi"], capture_output=True, text=True)
        if result.stdout:
            print(result.stdout.strip())
        if result.stderr:
            print(result.stderr.strip())
    except Exception as e:
        print(f"[-] Failed to run MacShift: {e}")
        return
        
    new_mac = get_wifi_mac()
    print(f"[+] New Wi-Fi MAC Address: {new_mac}")


def run_macspoof_disconnect():
    """Disconnects and restores the original Wi-Fi MAC address."""
    packages_dir = get_packages_dir()
    macshift_path = os.path.join(packages_dir, "macshift.exe")
    
    if not os.path.exists(macshift_path):
        print("[-] MacSpoofing is not installed. Try: hs macspoofing")
        return
    
    print("[*] Running MacShift to disconnect and restore MAC address...")
    try:
        result = subprocess.run([macshift_path, "Wi-Fi", "-d"], capture_output=True, text=True)
        if result.stdout:
            print(result.stdout.strip())
        if result.stderr:
            print(result.stderr.strip())
    except Exception as e:
        print(f"[-] Failed to run MacShift: {e}")


def run_username_search(username):
    """Searches for a username across social networks using Maigret."""
    packages_dir = get_packages_dir()
    maigret_path = os.path.join(packages_dir, "maigret_standalone.exe")
    
    if not os.path.exists(maigret_path):
        print("[-] Username scanner (Maigret) is not installed. Try: hs username")
        return
    
    if not username:
        print("[-] Please provide a username. Example: username sarah")
        return
    
    print(f"[*] Searching for username: {username}")
    print("[*] This may take a few minutes...")
    print("[*] Running Maigret OSINT scan...\n")
    
    try:
        # Run maigret with the username
        subprocess.run([maigret_path, username])
    except Exception as e:
        print(f"[-] Failed to run Maigret: {e}")


def upload_file(filename):
    packages_dir = get_packages_dir()
    file_path = None
    for root, dirs, files in os.walk(packages_dir):
        for file in files:
            if file.lower() == filename.lower():
                file_path = os.path.join(root, file)
                break
        if file_path:
            break
    if not file_path:
        print(f"[-] File '{filename}' not found in Packages folder.")
        return
    print(f"[*] Uploading '{filename}' to get public link...")
    try:
        boundary = uuid.uuid4().hex
        body = (
            f"--{boundary}\r\n"
            f"Content-Disposition: form-data; name=\"file\"; filename=\"{filename}\"\r\n"
            f"Content-Type: application/octet-stream\r\n\r\n"
        ).encode('utf-8')
        with open(file_path, 'rb') as f:
            file_data = f.read()
        body += file_data
        body += f"\r\n--{boundary}--\r\n".encode('utf-8')
        req = urllib.request.Request(
            "https://tmpfiles.org/api/v1/upload",
            data=body,
            headers={
                "Content-Type": f"multipart/form-data; boundary={boundary}",
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
            }
        )
        with urllib.request.urlopen(req) as response:
            res_data = response.read().decode('utf-8').strip()
            try:
                json_res = json.loads(res_data)
                if json_res.get("status") == "success":
                    url = json_res["data"]["url"]
                    public_link = url.replace("tmpfiles.org/", "tmpfiles.org/dl/")
                    print(f"[+] Public link: {public_link}")
                else:
                    print(f"[-] Upload failed: {res_data}")
            except json.JSONDecodeError:
                print(f"[+] Public link (raw): {res_data}")
    except Exception as e:
        print(f"[-] Failed to upload file: {e}")


def run_nmap_scan(target, arguments):
    print(f"[*] Initializing Nmap scan on target: {target} with args: '{arguments}'...")
    nm = nmap.PortScanner()
    try:
        nm.scan(hosts=target, arguments=arguments)
        for host in nm.all_hosts():
            print(f"\n[+] Host: {host} ({nm[host].hostname()})")
            print(f"[+] State: {nm[host].state()}")
            if "osmatch" in nm[host] and nm[host]["osmatch"]:
                print("\n[+] OS Detection Results:")
                for osmatch in nm[host]["osmatch"]:
                    print(f"    -> {osmatch['name']} (Accuracy: {osmatch['accuracy']}%)")
            for proto in nm[host].all_protocols():
                print(f"[+] Protocol: {proto}")
                lport = nm[host][proto].keys()
                for port in lport:
                    state = nm[host][proto][port]["state"]
                    service = nm[host][proto][port].get("name", "unknown")
                    print(f"    -> Port {port} ({service}): {state}")
        print("\n[+] Scan completed successfully.")
    except Exception as e:
        print(f"[-] Scan failed. Details: {e}")


def run_evil_winrm(raw_command):
    print("[*] Initializing WinRM connection...")
    try:
        parts = raw_command.split()
        command_name = parts[0].lower()
        if command_name == "evil-winrm":
            parts[0] = "evil-winrm-py"
        if shutil.which(parts[0]) is not None:
            subprocess.run(parts)
        elif shutil.which("pipx") is not None:
            subprocess.run(["pipx", "run", "evil-winrm-py"] + parts[1:])
        else:
            subprocess.run(parts)
    except Exception as e:
        print(f"[-] Failed to execute evil-winrm-py session: {e}")


def main():
    os.system("cls")
    banner()

    in_py_mode = False
    py_python_exe = None
    py_notebooks_dir = None
    py_python_dir = None

    while True:
        try:
            if in_py_mode:
                raw_command = input("HackaShell [Python]> ").strip()
            else:
                raw_command = input("HackaShell [Admin]> ").strip()

            if not raw_command:
                continue

            command = raw_command.lower()

            if in_py_mode and command == "py exit":
                in_py_mode = False
                print("[*] Exiting Python mode. Returning to HackaShell.")
                continue

            if not in_py_mode and command == "py mode":
                portable_dir = get_portable_python_dir()
                py_python_exe = find_portable_python()
                py_notebooks_dir = os.path.join(portable_dir, "notebooks")

                if not os.path.exists(portable_dir):
                    print("[-] Portable_Python folder not found.")
                    continue
                if not py_python_exe:
                    print("[-] Could not find python.exe in Portable_Python folder.")
                    continue
                if not os.path.exists(py_notebooks_dir):
                    os.makedirs(py_notebooks_dir, exist_ok=True)

                py_python_dir = os.path.dirname(py_python_exe)
                in_py_mode = True
                print(f"[*] Entering Python Mode (Portable Python)")
                print(f"[*] Python: {py_python_exe}")
                print(f"[*] Working Dir: {py_notebooks_dir}")
                print("[*] Type 'py exit' to return to HackaShell")
                print("-" * 40)
                continue

            if in_py_mode:
                scripts_dir = os.path.join(py_python_dir, "Scripts")
                env = os.environ.copy()
                new_path = py_python_dir
                if os.path.exists(scripts_dir):
                    new_path = new_path + os.pathsep + scripts_dir
                env["PATH"] = new_path + os.pathsep + env.get("PATH", "")
                env.pop("PYTHONHOME", None)
                env.pop("PYTHONPATH", None)
                try:
                    subprocess.run(raw_command, shell=True, cwd=py_notebooks_dir, env=env)
                except Exception as e:
                    print(f"[-] Command failed: {e}")
                continue

            if command == "exit":
                print("Exiting HackaShell. Stay safe out there!")
                break
            elif command == "clear":
                os.system("cls")
                banner()
            elif command == "help":
                print_help()
            elif command == "scan my network" or command == "scan 192.168.0.1":
                run_nmap_scan("192.168.0.0/24", "-sn")
            elif command.startswith("scan ") and command.endswith(" for os"):
                parts = raw_command.split()
                if len(parts) >= 4:
                    run_nmap_scan(parts[1], "-O -sV")
                else:
                    print("[-] Invalid format. Example: Scan 192.168.0.80 for OS")
            elif command.startswith("scan "):
                parts = raw_command.split()
                if len(parts) >= 2:
                    run_nmap_scan(parts[1], "-F")
                else:
                    print("[-] Invalid format. Example: Scan 8.8.8.8")
            elif command.startswith("evil-winrm-py") or command.startswith("evil-winrm"):
                run_evil_winrm(raw_command)
            elif command == "hs list":
                packages_dir = get_packages_dir()
                available = {
                    "Vbrev": "vbrev", 
                    "Ncat": "ncat.exe", 
                    "MacSpoofing": "macshift.exe",
                    "Username": "maigret_standalone.exe"
                }
                installed = []
                if os.path.exists(packages_dir):
                    for item in os.listdir(packages_dir):
                        if item.lower() in available.values():
                            installed.append(item.lower())
                print("\n[*] Available packages:")
                for p, disk_name in available.items():
                    status = "[Installed]" if disk_name in installed else "[Available]"
                    print(f"  - {p} {status}")
                print("\n[*] Installed packages:")
                if installed:
                    for p, disk_name in available.items():
                        if disk_name in installed:
                            print(f"  - {p}")
                else:
                    print("  None")
                print()
            elif command.startswith("hs make ") and command.endswith(" public link"):
                parts = raw_command.split()
                if len(parts) >= 4:
                    upload_file(" ".join(parts[2:-2]))
                else:
                    print("[-] Invalid format. Example: hs make file.exe public link")
            elif command.startswith("hs ") and len(command.split()) == 2:
                pkg = command.split()[1].lower()
                if pkg == "vbrev":
                    install_vbrev()
                elif pkg == "ncat":
                    install_ncat()
                elif pkg == "macspoofing":
                    install_macspoofing()
                elif pkg == "username":
                    install_username()
                else:
                    print(f"[-] Unknown package '{pkg}'. Type 'hs list' to see available.")
            elif command == "vbrev launch":
                launch_vbrev()
            elif command == "ncat" or command.startswith("ncat "):
                run_ncat(raw_command)
            elif command == "macspoof wifi":
                run_macspoof_wifi()
            elif command == "macspoof disconnect":
                run_macspoof_disconnect()
            elif command.startswith("username "):
                parts = raw_command.split()
                if len(parts) >= 2:
                    username = parts[1]
                    run_username_search(username)
                else:
                    print("[-] Invalid format. Example: username sarah")
            elif command.startswith("pinggy "):
                parts = raw_command.split()
                if len(parts) == 2:
                    print(f"[*] Starting Pinggy tunnel on port {parts[1]}...")
                    try:
                        subprocess.run(["ssh", "-p", "443", f"-R0:localhost:{parts[1]}", "tcp@free.pinggy.io"])
                    except Exception as e:
                        print(f"[-] Failed to start Pinggy: {e}")
                else:
                    print("[-] Invalid format. Example: Pinggy 4444")
            else:
                print(f"[-] Unknown command: '{raw_command}'. Type 'help' for valid commands.")

        except KeyboardInterrupt:
            if in_py_mode:
                print("\n[!] Type 'py exit' to leave Python mode.")
            else:
                print("\n[!] Use 'exit' to quit HackaShell.")
        except EOFError:
            break


if __name__ == "__main__":
    main()