Skip to content

Commit 7df27d8

Browse files
authored
Feat/rich UI menu lovely (#567)
1 parent c43f290 commit 7df27d8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+2787
-574
lines changed

.github/workflows/test_install.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
cache: 'pip'
2727
- run: pip install --upgrade pip
2828
- run: pwd && ls -hal
29-
- run: sudo ./install.sh 1
29+
- run: sudo ./install.py 1
3030
- run: pwd && ls -hal
3131
# Typing "1" will allow us to manually enter the filepath to hackingtool.
3232
# Provide the filepath ${HOME}/work/hackingtool/hackingtool

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -204,11 +204,11 @@
204204
- [Crivo](https://github.com/GMDSantana/crivo)
205205

206206

207-
![](https://github.com/Z4nzu/hackingtool/blob/master/images/A00.png)
208-
![](https://github.com/Z4nzu/hackingtool/blob/master/images/A0.png)
209-
![](https://github.com/Z4nzu/hackingtool/blob/master/images/A1.png)
210-
![](https://github.com/Z4nzu/hackingtool/blob/master/images/A2.png)
211-
![](https://github.com/Z4nzu/hackingtool/blob/master/images/A4.png)
207+
![](https://github.com/Z4nzu/hackingtool/blob/master/images/A.png)
208+
![](https://github.com/Z4nzu/hackingtool/blob/master/images/AA.png)
209+
![](https://github.com/Z4nzu/hackingtool/blob/master/images/AAA.png)
210+
![](https://github.com/Z4nzu/hackingtool/blob/master/images/AAAA.png)
211+
![](https://github.com/Z4nzu/hackingtool/blob/master/images/AAAAA.png)
212212

213213
## Installation For Linux <img src="https://konpa.github.io/devicon/devicon.git/icons/linux/linux-original.svg" alt="linux" width="25" height="25"/></p><p align="center">
214214

@@ -233,7 +233,7 @@
233233

234234
## Step : 4 Run hackingtool
235235

236-
sudo bash install.sh
236+
sudo python install.py
237237

238238
## Step : 5 For installing tools in directory
239239

README_template.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@
2323

2424
# Hackingtool Menu 🧰
2525

26-
![](https://github.com/Z4nzu/hackingtool/blob/master/images/A00.png)
27-
![](https://github.com/Z4nzu/hackingtool/blob/master/images/A0.png)
28-
![](https://github.com/Z4nzu/hackingtool/blob/master/images/A1.png)
29-
![](https://github.com/Z4nzu/hackingtool/blob/master/images/A2.png)
30-
![](https://github.com/Z4nzu/hackingtool/blob/master/images/A4.png)
26+
![](https://github.com/Z4nzu/hackingtool/blob/master/images/A.png)
27+
![](https://github.com/Z4nzu/hackingtool/blob/master/images/AA.png)
28+
![](https://github.com/Z4nzu/hackingtool/blob/master/images/AAA.png)
29+
![](https://github.com/Z4nzu/hackingtool/blob/master/images/AAAA.png)
30+
![](https://github.com/Z4nzu/hackingtool/blob/master/images/AAAAA.png)
3131

3232
## Installation guide for Linux <img src="https://konpa.github.io/devicon/devicon.git/icons/linux/linux-original.svg" alt="linux" width="25" height="25"/></p><p align="center">
3333

@@ -41,7 +41,7 @@
4141

4242
sudo pip3 install -r requirements.txt
4343

44-
bash install.sh
44+
python install.py
4545

4646
sudo hackingtool
4747

core.py

Lines changed: 75 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
1+
from rich.console import Console
2+
from rich.panel import Panel
3+
from rich.table import Table
4+
from rich import box
5+
from rich.traceback import install
6+
from rich.theme import Theme
7+
18
import os
29
import sys
310
import webbrowser
411
from platform import system
512
from traceback import print_exc
6-
from typing import Callable
7-
from typing import List
8-
from typing import Tuple
13+
from typing import Callable, List, Tuple
14+
15+
# Enable rich tracebacks
16+
install()
17+
_theme = Theme({"purple": "#7B61FF"})
18+
console = Console(theme=_theme)
919

1020

1121
def clear_screen():
@@ -24,153 +34,159 @@ def validate_input(ip, val_range):
2434

2535

2636
class HackingTool(object):
27-
# About the HackingTool
28-
TITLE: str = "" # used to show info in the menu
37+
TITLE: str = ""
2938
DESCRIPTION: str = ""
30-
3139
INSTALL_COMMANDS: List[str] = []
3240
INSTALLATION_DIR: str = ""
33-
3441
UNINSTALL_COMMANDS: List[str] = []
35-
3642
RUN_COMMANDS: List[str] = []
37-
3843
OPTIONS: List[Tuple[str, Callable]] = []
39-
4044
PROJECT_URL: str = ""
4145

42-
def __init__(self, options = None, installable: bool = True,
43-
runnable: bool = True):
46+
def __init__(self, options=None, installable=True, runnable=True):
4447
options = options or []
4548
if isinstance(options, list):
4649
self.OPTIONS = []
4750
if installable:
48-
self.OPTIONS.append(('Install', self.install))
51+
self.OPTIONS.append(("Install", self.install))
4952
if runnable:
50-
self.OPTIONS.append(('Run', self.run))
53+
self.OPTIONS.append(("Run", self.run))
5154
self.OPTIONS.extend(options)
5255
else:
53-
raise Exception(
54-
"options must be a list of (option_name, option_fn) tuples")
56+
raise Exception("options must be a list of (option_name, option_fn) tuples")
5557

5658
def show_info(self):
57-
desc = self.DESCRIPTION
59+
desc = f"[cyan]{self.DESCRIPTION}[/cyan]"
5860
if self.PROJECT_URL:
59-
desc += '\n\t[*] '
60-
desc += self.PROJECT_URL
61-
os.system(f'echo "{desc}"|boxes -d boy | lolcat')
61+
desc += f"\n[green]🔗 {self.PROJECT_URL}[/green]"
62+
console.print(Panel(desc, title=f"[bold purple]{self.TITLE}[/bold purple]", border_style="purple", box=box.DOUBLE))
6263

63-
def show_options(self, parent = None):
64+
def show_options(self, parent=None):
6465
clear_screen()
6566
self.show_info()
67+
68+
table = Table(title="Options", box=box.SIMPLE_HEAVY)
69+
table.add_column("No.", style="bold cyan", justify="center")
70+
table.add_column("Action", style="bold yellow")
71+
6672
for index, option in enumerate(self.OPTIONS):
67-
print(f"[{index + 1}] {option[0]}")
73+
table.add_row(str(index + 1), option[0])
74+
6875
if self.PROJECT_URL:
69-
print(f"[{98}] Open project page")
70-
print(f"[{99}] Back to {parent.TITLE if parent is not None else 'Exit'}")
71-
option_index = input("Select an option : ").strip()
76+
table.add_row("98", "Open Project Page")
77+
table.add_row("99", f"Back to {parent.TITLE if parent else 'Exit'}")
78+
79+
console.print(table)
80+
81+
option_index = input("\n[?] Select an option: ").strip()
7282
try:
7383
option_index = int(option_index)
7484
if option_index - 1 in range(len(self.OPTIONS)):
7585
ret_code = self.OPTIONS[option_index - 1][1]()
7686
if ret_code != 99:
77-
input("\n\nPress ENTER to continue:").strip()
87+
input("\nPress [Enter] to continue...")
7888
elif option_index == 98:
7989
self.show_project_page()
8090
elif option_index == 99:
8191
if parent is None:
8292
sys.exit()
8393
return 99
8494
except (TypeError, ValueError):
85-
print("Please enter a valid option")
86-
input("\n\nPress ENTER to continue:").strip()
95+
console.print("[red]⚠ Please enter a valid option.[/red]")
96+
input("\nPress [Enter] to continue...")
8797
except Exception:
88-
print_exc()
89-
input("\n\nPress ENTER to continue:").strip()
90-
return self.show_options(parent = parent)
98+
console.print_exception(show_locals=True)
99+
input("\nPress [Enter] to continue...")
100+
return self.show_options(parent=parent)
91101

92-
def before_install(self):
93-
pass
102+
def before_install(self): pass
94103

95104
def install(self):
96105
self.before_install()
97106
if isinstance(self.INSTALL_COMMANDS, (list, tuple)):
98107
for INSTALL_COMMAND in self.INSTALL_COMMANDS:
108+
console.print(f"[yellow]→ {INSTALL_COMMAND}[/yellow]")
99109
os.system(INSTALL_COMMAND)
100110
self.after_install()
101111

102112
def after_install(self):
103-
print("Successfully installed!")
113+
console.print("[green]✔ Successfully installed![/green]")
104114

105115
def before_uninstall(self) -> bool:
106-
""" Ask for confirmation from the user and return """
107116
return True
108117

109118
def uninstall(self):
110119
if self.before_uninstall():
111120
if isinstance(self.UNINSTALL_COMMANDS, (list, tuple)):
112121
for UNINSTALL_COMMAND in self.UNINSTALL_COMMANDS:
122+
console.print(f"[red]→ {UNINSTALL_COMMAND}[/red]")
113123
os.system(UNINSTALL_COMMAND)
114124
self.after_uninstall()
115125

116-
def after_uninstall(self):
117-
pass
126+
def after_uninstall(self): pass
118127

119-
def before_run(self):
120-
pass
128+
def before_run(self): pass
121129

122130
def run(self):
123131
self.before_run()
124132
if isinstance(self.RUN_COMMANDS, (list, tuple)):
125133
for RUN_COMMAND in self.RUN_COMMANDS:
134+
console.print(f"[cyan]⚙ Running:[/cyan] [bold]{RUN_COMMAND}[/bold]")
126135
os.system(RUN_COMMAND)
127136
self.after_run()
128137

129-
def after_run(self):
130-
pass
138+
def after_run(self): pass
131139

132-
def is_installed(self, dir_to_check = None):
133-
print("Unimplemented: DO NOT USE")
140+
def is_installed(self, dir_to_check=None):
141+
console.print("[yellow]⚠ Unimplemented: DO NOT USE[/yellow]")
134142
return "?"
135143

136144
def show_project_page(self):
145+
console.print(f"[blue]🌐 Opening project page: {self.PROJECT_URL}[/blue]")
137146
webbrowser.open_new_tab(self.PROJECT_URL)
138147

139148

140149
class HackingToolsCollection(object):
141-
TITLE: str = "" # used to show info in the menu
150+
TITLE: str = ""
142151
DESCRIPTION: str = ""
143-
TOOLS = [] # type: List[Any[HackingTool, HackingToolsCollection]]
152+
TOOLS: List = []
144153

145154
def __init__(self):
146155
pass
147156

148157
def show_info(self):
149-
os.system("figlet -f standard -c {} | lolcat".format(self.TITLE))
150-
# os.system(f'echo "{self.DESCRIPTION}"|boxes -d boy | lolcat')
151-
# print(self.DESCRIPTION)
158+
console.rule(f"[bold purple]{self.TITLE}[/bold purple]", style="purple")
159+
console.print(f"[italic cyan]{self.DESCRIPTION}[/italic cyan]\n")
152160

153-
def show_options(self, parent = None):
161+
def show_options(self, parent=None):
154162
clear_screen()
155163
self.show_info()
164+
165+
table = Table(title="Available Tools", box=box.MINIMAL_DOUBLE_HEAD)
166+
table.add_column("No.", justify="center", style="bold cyan")
167+
table.add_column("Tool Name", style="bold yellow")
168+
156169
for index, tool in enumerate(self.TOOLS):
157-
print(f"[{index} {tool.TITLE}")
158-
print(f"[{99}] Back to {parent.TITLE if parent is not None else 'Exit'}")
159-
tool_index = input("Choose a tool to proceed: ").strip()
170+
table.add_row(str(index), tool.TITLE)
171+
172+
table.add_row("99", f"Back to {parent.TITLE if parent else 'Exit'}")
173+
console.print(table)
174+
175+
tool_index = input("\n[?] Choose a tool: ").strip()
160176
try:
161177
tool_index = int(tool_index)
162178
if tool_index in range(len(self.TOOLS)):
163-
ret_code = self.TOOLS[tool_index].show_options(parent = self)
179+
ret_code = self.TOOLS[tool_index].show_options(parent=self)
164180
if ret_code != 99:
165-
input("\n\nPress ENTER to continue:").strip()
181+
input("\nPress [Enter] to continue...")
166182
elif tool_index == 99:
167183
if parent is None:
168184
sys.exit()
169185
return 99
170186
except (TypeError, ValueError):
171-
print("Please enter a valid option")
172-
input("\n\nPress ENTER to continue:").strip()
187+
console.print("[red]⚠ Please enter a valid option.[/red]")
188+
input("\nPress [Enter] to continue...")
173189
except Exception:
174-
print_exc()
175-
input("\n\nPress ENTER to continue:").strip()
176-
return self.show_options(parent = parent)
190+
console.print_exception(show_locals=True)
191+
input("\nPress [Enter] to continue...")
192+
return self.show_options(parent=parent)

generate_readme.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
1+
# coding=utf-8
12
import re
23

4+
from rich.console import Console
5+
from rich.theme import Theme
6+
37
from core import HackingTool
48
from core import HackingToolsCollection
59
from hackingtool import all_tools
610

11+
_theme = Theme({"purple": "#7B61FF"})
12+
console = Console(theme=_theme)
13+
714

815
def sanitize_anchor(s):
916
return re.sub(r"\W", "-", s.lower())
@@ -48,4 +55,4 @@ def generate_readme():
4855

4956

5057
if __name__ == '__main__':
51-
generate_readme()
58+
generate_readme()

0 commit comments

Comments
 (0)