Skip to content

Commit a6c212c

Browse files
committed
Create interface.py
1 parent fe71275 commit a6c212c

File tree

1 file changed

+181
-0
lines changed

1 file changed

+181
-0
lines changed

hacxgpt/ui/interface.py

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
2+
import os
3+
import time
4+
import pyperclip
5+
from rich.console import Console
6+
from rich.panel import Panel
7+
from rich.markdown import Markdown
8+
from rich.live import Live
9+
from rich.table import Table
10+
from rich.spinner import Spinner
11+
from rich.align import Align
12+
from ..config import Config
13+
from ..core.extractor import CodeExtractor
14+
from .banner import Banner
15+
16+
class UI:
17+
"""Advanced Terminal User Interface using Rich"""
18+
19+
def __init__(self):
20+
self.console = Console()
21+
22+
def clear(self):
23+
os.system('cls' if os.name == 'nt' else 'clear')
24+
25+
def banner(self):
26+
self.clear()
27+
Banner.print_banner(self.console)
28+
29+
def main_menu(self):
30+
table = Table(show_header=False, box=None, padding=(0, 2))
31+
table.add_column("Icon", style="bold yellow", justify="right")
32+
table.add_column("Option", style="bold white")
33+
34+
table.add_row("[1]", "Initialize Uplink (Start Chat)")
35+
table.add_row("[2]", "Configure Security Keys (API Setup)")
36+
table.add_row("[3]", "System Manifesto (About)")
37+
table.add_row("[4]", "Terminate Session (Exit)")
38+
39+
panel = Panel(
40+
Align.center(table),
41+
title="[bold cyan]MAIN MENU[/bold cyan]",
42+
border_style="bright_blue",
43+
padding=(1, 5)
44+
)
45+
self.console.print(panel)
46+
47+
def show_msg(self, title: str, content: str, color: str = "white"):
48+
self.console.print(Panel(content, title=f"[bold]{title}[/]", border_style=color))
49+
50+
def get_input(self, label: str = "COMMAND") -> str:
51+
prompt_style = Config.Colors.USER_PROMPT
52+
self.console.print(f"[{prompt_style}]┌──({label})-[~][/]")
53+
return self.console.input(f"[{prompt_style}]└─> [/]")
54+
55+
def stream_markdown(self, title: str, content_generator):
56+
"""
57+
Renders Markdown content in real-time as it streams.
58+
"""
59+
full_response = ""
60+
61+
with Live(
62+
Panel(Spinner("dots", text="Decryption in progress..."), title=title, border_style="cyan"),
63+
console=self.console,
64+
refresh_per_second=12,
65+
transient=False
66+
) as live:
67+
68+
for chunk in content_generator:
69+
full_response += chunk
70+
71+
# Clean format for display
72+
display_text = full_response.replace("[HacxGPT]:", "").replace("[CODE]:", "").strip()
73+
if not display_text: display_text = "..."
74+
75+
md = Markdown(display_text, code_theme=Config.CODE_THEME)
76+
77+
live.update(
78+
Panel(
79+
md,
80+
title=f"[bold cyan]{title}[/bold cyan] [dim](Stream Active)[/dim]",
81+
border_style="cyan"
82+
)
83+
)
84+
85+
display_text = full_response.replace("[HacxGPT]:", "").replace("[CODE]:", "").strip()
86+
live.update(
87+
Panel(
88+
Markdown(display_text, code_theme=Config.CODE_THEME),
89+
title=f"[bold green]{title}[/bold green] [bold]✓[/]",
90+
border_style="green"
91+
)
92+
)
93+
94+
return full_response
95+
96+
def handle_code_blocks(self, response_text: str):
97+
"""Handle code block extraction and user actions with Pro UI"""
98+
code_blocks = CodeExtractor.extract_code_blocks(response_text)
99+
100+
if not code_blocks:
101+
return
102+
103+
self.console.print(Panel(f"[bold yellow]🔍 Detected {len(code_blocks)} code block(s)[/]", border_style="yellow"))
104+
105+
# Display code blocks info
106+
table = Table(show_header=True, header_style="bold magenta", border_style="dim white", expand=True)
107+
table.add_column("#", style="cyan", justify="center", width=4)
108+
table.add_column("Language", style="green")
109+
table.add_column("Preview", style="dim white")
110+
table.add_column("Lines", style="yellow", justify="right")
111+
112+
for idx, (lang, code) in enumerate(code_blocks, 1):
113+
lines = code.split('\n')
114+
preview = lines[0].strip()[:50] + "..." if len(lines[0]) > 50 else lines[0].strip()
115+
table.add_row(str(idx), lang.upper(), preview, str(len(lines)))
116+
117+
self.console.print(table)
118+
119+
# Pro Menu
120+
menu_text = """
121+
[bold cyan]Options:[/bold cyan]
122+
[bold green][1][/] Save All [bold green][2][/] Copy All [bold green][3][/] Save One [bold green][4][/] Copy One [bold red][SEMICOLON/Space][/] Skip
123+
"""
124+
self.console.print(Panel(menu_text.strip(), border_style="blue", title="[bold]Action Menu[/]"))
125+
self.console.print("[dim]Press the corresponding key...[/]")
126+
127+
while True:
128+
import msvcrt
129+
key = msvcrt.getch()
130+
try:
131+
char = key.decode("utf-8").lower()
132+
except:
133+
continue
134+
135+
if char == '1':
136+
self._save_all_blocks(code_blocks)
137+
break
138+
elif char == '2':
139+
self._copy_all_blocks(code_blocks)
140+
break
141+
elif char == '3':
142+
self._save_specific_block_interactive(code_blocks)
143+
break
144+
elif char == '4':
145+
self._copy_specific_block_interactive(code_blocks)
146+
break
147+
elif char == ' ' or char == ';':
148+
self.console.print("[yellow]Skipped.[/]")
149+
break
150+
151+
def _save_specific_block_interactive(self, code_blocks):
152+
self.console.print("[bold cyan]Press the number of the block to save (1-9)...[/]")
153+
while True:
154+
import msvcrt
155+
key = msvcrt.getch()
156+
try:
157+
char = key.decode("utf-8")
158+
if char.isdigit() and 1 <= int(char) <= len(code_blocks):
159+
idx = int(char) - 1
160+
lang, code = code_blocks[idx]
161+
filepath = CodeExtractor.save_code_block(code, lang, idx)
162+
self.console.print(f"[bold green]✓ Saved Block {char} to: {filepath}[/]")
163+
break
164+
except:
165+
pass
166+
167+
def _copy_specific_block_interactive(self, code_blocks):
168+
self.console.print("[bold cyan]Press the number of the block to copy (1-9)...[/]")
169+
while True:
170+
import msvcrt
171+
key = msvcrt.getch()
172+
try:
173+
char = key.decode("utf-8")
174+
if char.isdigit() and 1 <= int(char) <= len(code_blocks):
175+
idx = int(char) - 1
176+
lang, code = code_blocks[idx]
177+
pyperclip.copy(code)
178+
self.console.print(f"[bold green]✓ Block {char} copied to clipboard![/]")
179+
break
180+
except:
181+
pass

0 commit comments

Comments
 (0)