Commit 8aabb70e authored by Hardik Zinzuvadiya's avatar Hardik Zinzuvadiya
Browse files

Redesign main menu: compact header, 2-column grid, 1-based numbering, ? help

Header:
- Replace 8-line pixelated ASCII logo with a compact 9-line styled panel
- Shows tool name, version, repo URL, and legal warning in one block
- Screen is now cleared inside build_menu() on each main menu render

Menu layout:
- Single narrow column → 2-column grid (9 left / 8 right)
- Full terminal width is used; short display labels prevent truncation
- tool_definitions gains a third field (menu_label) for the grid;
  full TITLE is still used when entering a category

Numbering:
- 0-based → 1-based throughout interact_menu()
- ToolManager is item 18 (was mislabeled 99, conflicting with exit)
- Input validation: 1 <= choice <= len(all_tools) → all_tools[choice - 1]

Commands:
- Add ? / help   → show Quick Help overlay (main/category/tool reference)
- Add q / quit / exit → clean exit with goodbye message
- Remove Confirm.ask("Return to main menu?") — pressing 99 in any
  sub-menu already returns here; the extra prompt was redundant friction
- Ctrl+C still works as force quit

Error messages updated to reflect new command set
parent 2834bd69
Loading
Loading
Loading
Loading
+158 −92
Original line number Diff line number Diff line
@@ -12,18 +12,19 @@ if sys.version_info < (3, 10):

import os
import webbrowser
from platform import system
from itertools import zip_longest

from rich.console import Console
from rich.panel import Panel
from rich.table import Table
from rich.prompt import IntPrompt, Confirm
from rich.prompt import Prompt, Confirm
from rich.align import Align
from rich.text import Text
from rich import box
from rich.rule import Rule
from rich.columns import Columns

from core import HackingToolsCollection
from core import HackingToolsCollection, clear_screen, console
from constants import VERSION_DISPLAY, REPO_WEB_URL
from config import get_tools_dir
from tools.anonsurf import AnonSurfTools
@@ -45,39 +46,30 @@ from tools.wireless_attack import WirelessAttackTools
from tools.wordlist_generator import WordlistGeneratorTools
from tools.xss_attack import XSSAttackTools

console = Console()

ASCII_LOGO = r"""
   ▄█    █▄       ▄████████  ▄████████    ▄█   ▄█▄  ▄█  ███▄▄▄▄      ▄██████▄           ███      ▄██████▄   ▄██████▄   ▄█
  ███    ███     ███    ███ ███    ███   ███ ▄███▀ ███  ███▀▀▀██▄   ███    ███      ▀█████████▄ ███    ███ ███    ███ ███
  ███    ███     ███    ███ ███    █▀    ███▐██▀   ███▌ ███   ███   ███    █▀          ▀███▀▀██ ███    ███ ███    ███ ███
 ▄███▄▄▄▄███▄▄   ███    ███ ███         ▄█████▀    ███▌ ███   ███  ▄███                 ███   ▀ ███    ███ ███    ███ ███
▀▀███▀▀▀▀███▀  ▀███████████ ███        ▀▀█████▄    ███▌ ███   ███ ▀▀███ ████▄           ███     ███    ███ ███    ███ ███
  ███    ███     ███    ███ ███    █▄    ███▐██▄   ███  ███   ███   ███    ███          ███     ███    ███ ███    ███ ███
  ███    ███     ███    ███ ███    ███   ███ ▀███▄ ███  ███   ███   ███    ███          ███     ███    ███ ███    ███ ███▌    ▄
  ███    █▀      ███    █▀  ████████▀    ███   ▀█▀ █▀    ▀█   █▀    ████████▀          ▄████▀    ▀██████▀   ▀██████▀  █████▄▄██
                                         ▀                                                                            ▀
"""
# ── Tool registry ──────────────────────────────────────────────────────────────

# (full_title, icon, menu_label)
# menu_label is the concise name shown in the 2-column main menu grid.
# full_title is shown when entering the category.
tool_definitions = [
    ("Anonymously Hiding Tools",           "🛡"),
    ("Information gathering tools",        "🔍"),
    ("Wordlist Generator",                 "📚"),
    ("Wireless attack tools",              "📶"),
    ("SQL Injection Tools",                "🧩"),
    ("Phishing attack tools",              "🎣"),
    ("Web Attack tools",                   "🌐"),
    ("Post exploitation tools",            "🔧"),
    ("Forensic tools",                     "🕵"),
    ("Payload creation tools",             "📦"),
    ("Exploit framework",                  "🧰"),
    ("Reverse engineering tools",          "🔁"),
    ("DDOS Attack Tools",                  ""),
    ("Remote Administrator Tools (RAT)",   "🖥"),
    ("XSS Attack Tools",                   "💥"),
    ("Steganography tools",                "🖼"),
    ("Other tools",                        ""),
    ("Update or Uninstall | Hackingtool",  ""),
    ("Anonymously Hiding Tools",           "🛡 ", "Anonymously Hiding"),
    ("Information gathering tools",        "🔍",  "Information Gathering"),
    ("Wordlist Generator",                 "📚",  "Wordlist Generator"),
    ("Wireless attack tools",              "📶",  "Wireless Attack"),
    ("SQL Injection Tools",                "🧩",  "SQL Injection"),
    ("Phishing attack tools",              "🎣",  "Phishing Attack"),
    ("Web Attack tools",                   "🌐",  "Web Attack"),
    ("Post exploitation tools",            "🔧",  "Post Exploitation"),
    ("Forensic tools",                     "🕵 ", "Forensics"),
    ("Payload creation tools",             "📦",  "Payload Creation"),
    ("Exploit framework",                  "🧰",  "Exploit Framework"),
    ("Reverse engineering tools",          "🔁",  "Reverse Engineering"),
    ("DDOS Attack Tools",                  "",  "DDOS Attack"),
    ("Remote Administrator Tools (RAT)",   "🖥 ", "Remote Admin (RAT)"),
    ("XSS Attack Tools",                   "💥",  "XSS Attack"),
    ("Steganography tools",                "🖼 ", "Steganography"),
    ("Other tools",                        "",  "Other Tools"),
    ("Update or Uninstall | Hackingtool",  " ",  "Update / Uninstall"),
]

all_tools = [
@@ -101,88 +93,166 @@ all_tools = [
    ToolManager(),
]


# Used by generate_readme.py
class AllTools(HackingToolsCollection):
    TITLE = "All tools"
    TOOLS = all_tools

    def show_info(self):
        header = Text(ASCII_LOGO, style="bold magenta")
        footer = Text.assemble(
            (f" {REPO_WEB_URL} ", "bold bright_black"),
            (" | ",),
            (VERSION_DISPLAY, "bold green"),
        )
        warning = Text(" Please Don't Use For Illegal Activity ", style="bold red")
        panel = Panel(
            Align.center(header + Text("\n") + footer + Text("\n") + warning),
            box=box.DOUBLE,
            padding=(1, 2),

# ── Help overlay ───────────────────────────────────────────────────────────────

def show_help():
    console.print(Panel(
        Text.assemble(
            ("  Main menu\n", "bold white"),
            ("  ─────────────────────────────────────\n", "dim"),
            ("  1–17   ", "bold cyan"), ("open a category\n", "white"),
            ("  18     ", "bold cyan"), ("Update / Uninstall hackingtool\n", "white"),
            ("  ?      ", "bold cyan"), ("show this help\n", "white"),
            ("  q      ", "bold cyan"), ("quit hackingtool\n\n", "white"),
            ("  Inside a category\n", "bold white"),
            ("  ─────────────────────────────────────\n", "dim"),
            ("  1–N    ", "bold cyan"), ("select a tool\n", "white"),
            ("  99     ", "bold cyan"), ("back to main menu\n", "white"),
            ("  98     ", "bold cyan"), ("open project page (if available)\n\n", "white"),
            ("  Inside a tool\n", "bold white"),
            ("  ─────────────────────────────────────\n", "dim"),
            ("  1      ", "bold cyan"), ("install tool\n", "white"),
            ("  2      ", "bold cyan"), ("run tool\n", "white"),
            ("  99     ", "bold cyan"), ("back to category\n", "white"),
        ),
        title="[bold magenta] ? Quick Help [/bold magenta]",
        border_style="magenta",
        )
        console.print(panel)
        box=box.ROUNDED,
        padding=(0, 2),
    ))
    Prompt.ask("[dim]Press Enter to return[/dim]", default="")


# ── Main menu renderer ─────────────────────────────────────────────────────────

def build_menu():
    table = Table.grid(expand=True)
    table.add_column("idx", width=6, justify="right")
    table.add_column("name", justify="left")

    for idx, (title, icon) in enumerate(tool_definitions):
        if idx == len(tool_definitions) - 1:
            label = "[bold magenta]99[/bold magenta]"
            name  = f"[bold magenta]{icon} {title}[/bold magenta]"
        else:
            label = f"[bold magenta]{idx}[/bold magenta]"
            name  = f"[white]{icon}[/white]  [magenta]{title}[/magenta]"
        table.add_row(label, name)
    clear_screen()

    # ── Compact header ──
    console.print(Panel(
        Align.center(Text("HackingTool — Main Menu", style="bold white on magenta"), vertical="middle"),
        style="magenta", padding=(0, 1), box=box.ROUNDED,
        Text.assemble(
            ("\n    ⚔   H A C K I N G  T O O L\n\n", "bold magenta"),
            ("    All-in-One Security Research Framework", "white"),
            ("   ·   ", "dim"),
            (VERSION_DISPLAY, "bold green"),
            ("\n    ", ""),
            (REPO_WEB_URL, "dim cyan"),
            ("\n\n    ", ""),
            ("For authorized security testing only\n", "dim red"),
        ),
        box=box.HEAVY,
        border_style="magenta",
        padding=(0, 2),
    ))
    console.print(Panel.fit(
        table,
        title="[bold magenta]Select a tool[/bold magenta]",

    # ── 2-column category grid ──
    # Items 1-17 in two columns, item 18 (ToolManager) shown separately
    categories = tool_definitions[:-1]   # 17 items
    update_def = tool_definitions[-1]    # ToolManager

    mid = (len(categories) + 1) // 2    # 9  (left), 8 (right)
    left  = list(enumerate(categories[:mid],  start=1))
    right = list(enumerate(categories[mid:],  start=mid + 1))

    grid = Table.grid(padding=(0, 1), expand=True)
    grid.add_column("ln", justify="right", style="bold magenta", width=5)
    grid.add_column("li", width=3)
    grid.add_column("lt", style="magenta", ratio=1, no_wrap=True)
    grid.add_column("gap", width=3)
    grid.add_column("rn", justify="right", style="bold magenta", width=5)
    grid.add_column("ri", width=3)
    grid.add_column("rt", style="magenta", ratio=1, no_wrap=True)

    for (li, (_, lic, ll)), r in zip_longest(left, right, fillvalue=None):
        if r:
            ri, (_, ric, rl) = r
            grid.add_row(str(li), lic, ll, "", str(ri), ric, rl)
        else:
            grid.add_row(str(li), lic, ll, "", "", "", "")

    console.print(Panel(
        grid,
        title="[bold magenta] Select a Category [/bold magenta]",
        border_style="bright_magenta",
        box=box.SQUARE,
        box=box.ROUNDED,
        padding=(0, 1),
    ))
    console.print(Rule(style="bright_black"))
    console.print(Align.center(Text(
        "Choose number and press Enter — 99 to exit",
        style="italic bright_black",
    )))
    console.print("")

    # ── ToolManager row ──
    console.print(
        f"  [bold magenta]  18[/bold magenta]  {update_def[1]}  "
        f"[magenta]{update_def[2]}[/magenta]"
    )

    # ── Hint bar ──
    console.print(Rule(style="dim magenta"))
    console.print(
        "  [dim]Enter number to open  ·  "
        "[bold cyan]?[/bold cyan] help  ·  "
        "[bold cyan]q[/bold cyan] quit[/dim]\n"
    )


# ── Main interaction loop ──────────────────────────────────────────────────────

def interact_menu():
    while True:
        try:
            build_menu()
            choice = IntPrompt.ask("[magenta]Choose a tool to proceed[/magenta]", default=0)
            if choice == 99:
                console.print(Panel("[bold white on magenta]Goodbye — Come Back Safely[/bold white on magenta]"))
            raw = Prompt.ask("[bold magenta]>[/bold magenta]", default="").strip().lower()

            if not raw:
                continue

            if raw in ("?", "help"):
                show_help()
                continue

            if raw in ("q", "quit", "exit"):
                console.print(Panel(
                    "[bold white on magenta]  Goodbye — Come Back Safely  [/bold white on magenta]",
                    box=box.HEAVY, border_style="magenta",
                ))
                break
            if 0 <= choice < len(all_tools):
                tool = all_tools[choice]
                name = tool_definitions[choice][0]

            try:
                choice = int(raw)
            except ValueError:
                console.print("[red]⚠  Invalid input — enter a number, ? for help, or q to quit.[/red]")
                Prompt.ask("[dim]Press Enter to continue[/dim]", default="")
                continue

            if 1 <= choice <= len(all_tools):
                title, icon, _ = tool_definitions[choice - 1]
                console.print(Panel(
                    f"[bold magenta]{tool_definitions[choice][1]}  Selected:[/bold magenta] [white]{name}[/white]"
                    f"[bold magenta]{icon}  {title}[/bold magenta]",
                    border_style="magenta", box=box.ROUNDED,
                ))
                try:
                    tool.show_options()
                    all_tools[choice - 1].show_options()
                except Exception as e:
                    console.print(Panel(f"[red]Error while opening {name}[/red]\n{e}", border_style="red"))
                if not Confirm.ask("[magenta]Return to main menu?[/magenta]", default=True):
                    console.print(Panel("[bold white on magenta]Exiting...[/bold white on magenta]"))
                    break
                    console.print(Panel(
                        f"[red]Error while opening {title}[/red]\n{e}",
                        border_style="red",
                    ))
                    Prompt.ask("[dim]Press Enter to return to main menu[/dim]", default="")
            else:
                console.print("[red]Invalid selection. Pick a number from the menu.[/red]")
                console.print(f"[red]⚠  Choose 1–{len(all_tools)}, ? for help, or q to quit.[/red]")
                Prompt.ask("[dim]Press Enter to continue[/dim]", default="")

        except KeyboardInterrupt:
            console.print("\n[bold red]Interrupted — exiting[/bold red]")
            break


# ── Entry point ────────────────────────────────────────────────────────────────

def main():
    try:
        from os_detect import CURRENT_OS
@@ -196,11 +266,7 @@ def main():
        if CURRENT_OS.system not in ("linux", "macos"):
            console.print(f"[yellow]Unsupported OS: {CURRENT_OS.system}. Proceeding anyway...[/yellow]")

        # Ensure ~/.hackingtool/tools/ exists — no os.chdir(), tools use absolute paths
        tools_dir = get_tools_dir()
        console.print(f"[dim]Tools directory: {tools_dir}[/dim]")

        AllTools().show_info()
        get_tools_dir()   # ensures ~/.hackingtool/tools/ exists
        interact_menu()

    except KeyboardInterrupt: