diff --git a/Modules/submenu.py b/Modules/submenu.py index 093cca3..6d21cc7 100644 --- a/Modules/submenu.py +++ b/Modules/submenu.py @@ -1,33 +1,118 @@ import sys # For exiting the program -from Modules.All_Pages.clear_screen import clear_screen -from Modules.All_Pages.wrappers import header # Import the header function +from Modules.wrappers import * -def build_submenu(menu_title, target_ip, actions, open_ports): - # Initialize a dictionary to track the status of actions - action_status = {key: False for key in actions} # False means not completed +# Global action status to persist across all submenus and their nested submenus +GLOBAL_ACTION_STATUS = {} +GLOBAL_TOTAL_PROGRESS = {"completed": 0, "total": 0} # Tracks progress across all sections +GLOBAL_HIGHLIGHTS = {} # Tracks highlighted actions + + +def build_submenu(menu_title, actions, module=None): + """ + Builds a submenu and tracks progress across all nested submenus. + Automatically adds an 'All' option to execute all actions. + """ + # Initialize global action status for this submenu if not already set + if menu_title not in GLOBAL_ACTION_STATUS: + GLOBAL_ACTION_STATUS[menu_title] = {key: False for key in actions} # False means not completed + GLOBAL_HIGHLIGHTS[menu_title] = {key: False for key in actions} # False means not highlighted + + # Update global total progress for tracking across all menus + GLOBAL_TOTAL_PROGRESS["total"] += len(actions) + + # Access the action status and highlight status for this specific submenu + action_status = GLOBAL_ACTION_STATUS[menu_title] + highlight_status = GLOBAL_HIGHLIGHTS[menu_title] + + # Dynamically add "All" option + actions["all"] = { + "description": "Run All", + "function": lambda: run_all_actions(actions, module, action_status), + } + + # Ensure the "all" option is in the dictionaries + if "all" not in action_status: + action_status["all"] = False + if "all" not in highlight_status: + highlight_status["all"] = False while True: clear_screen() - header(target_ip, open_ports) # Call the header with the target_ip and open_ports + header() # Call the header without arguments print("=====================================") print(f" {menu_title} Menu ") print("=====================================\n") - # Display menu options with status + # Display global progress only (not specific to this submenu) + global_completed = GLOBAL_TOTAL_PROGRESS["completed"] + global_total = GLOBAL_TOTAL_PROGRESS["total"] + print(f"Global Progress: {global_completed}/{global_total} tasks completed\n") + + # Display menu options with status, progress, and highlighting for key, action in actions.items(): - status = "✔️ " if action_status[key] else "❌" # Check mark if completed, cross otherwise - print(f"[{key}] {status} {action['description']}") + if key == "all": # Highlight the "All" option in blue + print(f"\033[94m[{key.upper()}] {action['description']}\033[0m") + else: + # Check the status and highlight of the submenu or action + if "submenu" in action: + submenu_completed = is_submenu_complete(action["submenu"]) + status = "✔️" if submenu_completed else "❌" + else: + status = "✔️ " if action_status[key] else "❌" + + if highlight_status[key]: # Highlight in yellow if flagged + print(f"\033[93m[{key}] {status} {action['description']}\033[0m") + else: + print(f"[{key}] {status} {action['description']}") print("[0] Return to Main Menu") print("[q] EXIT\n") # Get user choice choice = input("Enter your choice: ").strip().lower() + # Handle highlighting + if choice.endswith("!") and choice[:-1] in actions: + key_to_toggle = choice[:-1] + highlight_status[key_to_toggle] = not highlight_status[key_to_toggle] + if highlight_status[key_to_toggle]: + print(f"Action [{key_to_toggle}] has been highlighted.") + else: + print(f"Highlight removed from action [{key_to_toggle}].") + input("Press Enter to continue...") + continue + + # Handle unchecking of actions + if choice.startswith("-") and choice[1:] in actions: + key_to_uncheck = choice[1:] + if action_status[key_to_uncheck]: + action_status[key_to_uncheck] = False + GLOBAL_TOTAL_PROGRESS["completed"] -= 1 + print(f"Unchecked action [{key_to_uncheck}]") + else: + print(f"Action [{key_to_uncheck}] was not completed.") + input("Press Enter to continue...") + continue + # Handle menu choices if choice in actions: - # Call the associated function with target_ip and update status - actions[choice]["function"](target_ip, open_ports) - action_status[choice] = True # Mark the action as completed + if choice == "all": + run_all_actions(actions, module, action_status) + action_status["all"] = True # Mark the "All" option as completed + elif "submenu" in actions[choice]: # Navigate to nested submenu + actions[choice]["submenu"]() + # After returning, check if all nested submenu items are done + if is_submenu_complete(actions[choice]["submenu"]): + if not action_status[choice]: + action_status[choice] = True # Mark this submenu as complete + GLOBAL_TOTAL_PROGRESS["completed"] += 1 + elif "function" in actions[choice]: # Execute the associated function + actions[choice]["function"]() + if not action_status[choice]: + action_status[choice] = True # Mark the action as completed + GLOBAL_TOTAL_PROGRESS["completed"] += 1 + + # Propagate status updates to the parent menu + propagate_status_to_parent(menu_title) elif choice == "0": print("Returning to main menu...") break @@ -36,4 +121,54 @@ def build_submenu(menu_title, target_ip, actions, open_ports): sys.exit() else: print("Invalid choice. Please try again.") - input("Press Enter to continue...") \ No newline at end of file + input("Press Enter to continue...") + + # Propagate parent status again after menu completion + propagate_status_to_parent(menu_title) + + +def run_all_actions(actions, module, action_status): + """ + Executes all actions in the submenu sequentially. + """ + for key, action in actions.items(): + if key != "all": # Skip the "All" option itself + if "function" in action: + if not action_status[key]: + action["function"]() + action_status[key] = True + GLOBAL_TOTAL_PROGRESS["completed"] += 1 + elif "submenu" in action: # Recursively handle submenus + actions[key]["submenu"]() + if is_submenu_complete(actions[key]["submenu"]): + if not action_status[key]: + action_status[key] = True + GLOBAL_TOTAL_PROGRESS["completed"] += 1 + + +def is_submenu_complete(submenu_function): + """ + Check if all actions in a submenu are complete. + """ + submenu_title = get_submenu_title(submenu_function) + if submenu_title in GLOBAL_ACTION_STATUS: + return all(GLOBAL_ACTION_STATUS[submenu_title].values()) + return False + + +def propagate_status_to_parent(menu_title): + """ + Propagates the status to the parent menu when all submenu items are completed. + """ + for parent_title, statuses in GLOBAL_ACTION_STATUS.items(): + if menu_title in statuses: + statuses[menu_title] = all( + GLOBAL_ACTION_STATUS[menu_title].values() + ) # Mark parent complete if all are done + + +def get_submenu_title(submenu_function): + """ + Converts a submenu function name to a readable submenu title. + """ + return submenu_function.__name__.replace("_submenu", "").replace("_", " ").title() diff --git a/Modules/wrappers.py b/Modules/wrappers.py new file mode 100644 index 0000000..1a26144 --- /dev/null +++ b/Modules/wrappers.py @@ -0,0 +1,59 @@ +import os +import platform +from colorama import Fore, Style + +from Assets.ascii_text_prompts import ascii_art, full_ascii_art, infinitei +from Assets.random_tip import get_random_tip_with_color + +def clear_screen(): + # Check the system platform and use the appropriate command + if platform.system().lower() == "windows": + os.system('cls') # Windows command to clear the screen + else: + os.system('clear') # Unix-based (Linux/macOS) command to clear the screen + +def header(is_main_menu=False): + """ + Displays the header with optional full application details. + :param is_main_menu: Boolean to indicate whether to display full details. + """ + clear_screen() + if is_main_menu: + print(center_text(full_ascii_art)) # Full application name in ASCII art + print(center_text(infinitei)) # "Created By Me" + else: + print(center_text(ascii_art)) # Minimal header + print(center_text(get_random_tip_with_color()) + "\n") + +def display_menu(menu_options): + while True: + header(is_main_menu=True) # Show full details on main menu + for key, value in menu_options.items(): + print(f"[{key}] {value['name'].upper()}") + print("[0] Logout\n") + + choice = input("Enter your choice: ").strip().lower() + + # Match the choice to a menu option + if choice in menu_options: + menu_options[choice]["submenu"]() # Call the submenu without arguments + elif choice in ["0", "q", "exit", "quit"]: + print("Logging out...") + break + else: + print("Invalid choice. Please try again.") + +def print_info(title, content): + header() + print("=" * 40) + print(f"{title.center(40)}") + print("=" * 40) + print(content) + input("\nPress Enter to return to the menu...") + +def center_text(text): + terminal_width = os.get_terminal_size().columns + centered_lines = [] + for line in text.splitlines(): + centered_lines.append(line.center(terminal_width)) + return "\n".join(centered_lines)