import customtkinter as ctk
import socket
import platform
from datetime import datetime
# =========================
# CONFIG
# =========================
ctk.set_appearance_mode("dark")
ctk.set_default_color_theme("dark-blue")
PURPLE = "#8B5CF6"
PURPLE_DARK = "#6D28D9"
BG = "#08080D"
PANEL = "#101016"
PANEL_2 = "#15151D"
TEXT = "#F5F5F5"
MUTED = "#888899"
class NexusAI(ctk.CTk):
def __init__(self):
super().__init__()
self.title("NEXUS AI")
self.geometry("1200×720")
self.minsize(950, 600)
self.configure(fg_color=BG)
self.build_ui()
self.show_home()
# =========================
# UI PRINCIPALE
# =========================
def build_ui(self):
# Sidebar
self.sidebar = ctk.CTkFrame(
self,
width=210,
corner_radius=0,
fg_color=PANEL
)
self.sidebar.pack(side="left", fill="y")
self.sidebar.pack_propagate(False)
# Logo
logo = ctk.CTkLabel(
self.sidebar,
text="NEXUS",
font=ctk.CTkFont(size=25, weight="bold"),
text_color=PURPLE
)
logo.pack(pady=(30, 2))
sub = ctk.CTkLabel(
self.sidebar,
text="AI SYSTEM",
font=ctk.CTkFont(size=10),
text_color=MUTED
)
sub.pack(pady=(0, 30))
# Boutons
self.add_button("⌂ Dashboard", self.show_home)
self.add_button("◈ Assistant", self.show_chat)
self.add_button("◎ OSINT public", self.show_osint)
self.add_button("⌁ Network / DNS", self.show_network)
self.add_button("▣ PC Info", self.show_pc)
self.add_button("</> Python", self.show_python)
self.add_button("⚙ Settings", self.show_settings)
# Bas sidebar
self.status = ctk.CTkLabel(
self.sidebar,
text="● SYSTEM ONLINE",
text_color="#6EE7B7",
font=ctk.CTkFont(size=11, weight="bold")
)
self.status.pack(side="bottom", pady=25)
# Zone principale
self.main = ctk.CTkFrame(
self,
corner_radius=0,
fg_color=BG
)
self.main.pack(side="left", fill="both", expand=True)
# Header
self.header = ctk.CTkFrame(
self.main,
height=70,
fg_color=PANEL,
corner_radius=0
)
self.header.pack(fill="x")
self.header.pack_propagate(False)
self.page_title = ctk.CTkLabel(
self.header,
text="Dashboard",
font=ctk.CTkFont(size=21, weight="bold")
)
self.page_title.pack(side="left", padx=25)
self.clock = ctk.CTkLabel(
self.header,
text="",
text_color=MUTED
)
self.clock.pack(side="right", padx=25)
self.update_clock()
# Contenu
self.content = ctk.CTkFrame(
self.main,
fg_color=BG,
corner_radius=0
)
self.content.pack(fill="both", expand=True, padx=20, pady=20)
# =========================
# SIDEBAR BUTTON
# =========================
def add_button(self, text, command):
button = ctk.CTkButton(
self.sidebar,
text=text,
command=command,
height=42,
corner_radius=8,
fg_color="transparent",
hover_color="#211B35",
text_color="#D8D8E5",
anchor="w",
font=ctk.CTkFont(size=13)
)
button.pack(fill="x", padx=12, pady=4)
# =========================
# UTILITAIRES
# =========================
def clear_content(self):
for widget in self.content.winfo_children():
widget.destroy()
def set_title(self, title):
self.page_title.configure(text=title)
def update_clock(self):
now = datetime.now().strftime("%H:%M:%S")
self.clock.configure(text=now)
self.after(1000, self.update_clock)
# =========================
# DASHBOARD
# =========================
def show_home(self):
self.clear_content()
self.set_title("Dashboard")
welcome = ctk.CTkLabel(
self.content,
text="Bienvenue dans NEXUS AI",
font=ctk.CTkFont(size=30, weight="bold")
)
welcome.pack(anchor="w", pady=(20, 5))
desc = ctk.CTkLabel(
self.content,
text="Centre de contrôle • Assistant • OSINT public • Network",
text_color=MUTED,
font=ctk.CTkFont(size=13)
)
desc.pack(anchor="w")
cards = ctk.CTkFrame(
self.content,
fg_color="transparent"
)
cards.pack(fill="x", pady=35)
self.card(cards, "AI", "Assistant offline", "READY", 0)
self.card(cards, "OSINT", "Informations publiques", "READY", 1)
self.card(cards, "NET", "DNS / réseau", "READY", 2)
info = ctk.CTkFrame(
self.content,
fg_color=PANEL,
corner_radius=12
)
info.pack(fill="both", expand=True)
ctk.CTkLabel(
info,
text="QUICK START",
font=ctk.CTkFont(size=13, weight="bold"),
text_color=PURPLE
).pack(anchor="w", padx=20, pady=(20, 8))
ctk.CTkLabel(
info,
text="Choisis un module dans la barre de gauche pour commencer.",
text_color=MUTED
).pack(anchor="w", padx=20)
def card(self, parent, title, description, status, column):
card = ctk.CTkFrame(
parent,
fg_color=PANEL,
corner_radius=12,
width=200,
height=120
)
card.grid(row=0, column=column, padx=8, sticky="nsew")
card.grid_propagate(False)
ctk.CTkLabel(
card,
text=title,
text_color=PURPLE,
font=ctk.CTkFont(size=20, weight="bold")
).pack(anchor="w", padx=15, pady=(15, 3))
ctk.CTkLabel(
card,
text=description,
text_color=MUTED
).pack(anchor="w", padx=15)
ctk.CTkLabel(
card,
text="● " + status,
text_color="#6EE7B7",
font=ctk.CTkFont(size=10, weight="bold")
).pack(anchor="w", padx=15, pady=10)
# =========================
# CHAT
# =========================
def show_chat(self):
self.clear_content()
self.set_title("Assistant")
self.chat_box = ctk.CTkTextbox(
self.content,
fg_color=PANEL,
corner_radius=12,
font=ctk.CTkFont(size=13)
)
self.chat_box.pack(fill="both", expand=True)
self.chat_box.insert(
"end",
"NEXUS AI\n"
"──────────────\n"
"Salut 👋 Je suis prêt.\n"
"Pose-moi une question.\n\n"
)
self.chat_box.configure(state="disabled")
bottom = ctk.CTkFrame(
self.content,
fg_color="transparent"
)
bottom.pack(fill="x", pady=(10, 0))
self.chat_entry = ctk.CTkEntry(
bottom,
height=45,
placeholder_text="Écris ton message…"
)
self.chat_entry.pack(side="left", fill="x", expand=True, padx=(0, 10))
self.chat_entry.bind(
"<Return>",
lambda event: self.send_message()
)
ctk.CTkButton(
bottom,
text="SEND",
width=100,
height=45,
fg_color=PURPLE,
hover_color=PURPLE_DARK,
command=self.send_message
).pack(side="right")
def send_message(self):
message = self.chat_entry.get().strip()
if not message:
return
self.chat_entry.delete(0, "end")
if "bonjour" in message.lower() or "salut" in message.lower():
response = "Salut 👋 Comment je peux t'aider ?"
elif "python" in message.lower():
response = "Je peux t'aider à créer ou corriger du Python."
elif "osint" in message.lower():
response = "Le module OSINT permet de récupérer des informations techniques publiques."
elif "pc" in message.lower():
response = "Regarde le module PC Info pour voir les informations de ta machine."
else:
response = "Je suis en mode offline pour cette V1."
self.chat_box.configure(state="normal")
self.chat_box.insert("end", f"\nYOU\n{message}\n\nNEXUS\n{response}\n")
self.chat_box.see("end")
self.chat_box.configure(state="disabled")
# =========================
# OSINT
# =========================
def show_osint(self):
self.clear_content()
self.set_title("OSINT public")
ctk.CTkLabel(
self.content,
text="Domain Lookup",
font=ctk.CTkFont(size=25, weight="bold")
).pack(anchor="w", pady=(10, 5))
ctk.CTkLabel(
self.content,
text="Recherche technique publique d'un domaine.",
text_color=MUTED
).pack(anchor="w")
self.osint_entry = ctk.CTkEntry(
self.content,
height=45,
placeholder_text="exemple.com"
)
self.osint_entry.pack(fill="x", pady=20)
ctk.CTkButton(
self.content,
text="ANALYSER",
height=42,
fg_color=PURPLE,
hover_color=PURPLE_DARK,
command=self.run_osint
).pack(anchor="w")
self.osint_result = ctk.CTkTextbox(
self.content,
fg_color=PANEL,
corner_radius=12
)
self.osint_result.pack(fill="both", expand=True, pady=20)
def run_osint(self):
domain = self.osint_entry.get().strip()
if not domain:
return
try:
ip = socket.gethostbyname(domain)
result = (
"NEXUS OSINT\n"
"──────────────\n\n"
f"Domaine : {domain}\n"
f"IPv4 : {ip}\n\n"
"Source : résolution DNS publique\n"
)
except Exception as e:
result = f"Erreur : {e}"
self.osint_result.delete("1.0", "end")
self.osint_result.insert("end", result)
# =========================
# NETWORK
# =========================
def show_network(self):
self.clear_content()
self.set_title("Network / DNS")
ctk.CTkLabel(
self.content,
text="DNS Resolver",
font=ctk.CTkFont(size=25, weight="bold")
).pack(anchor="w", pady=(10, 5))
self.net_entry = ctk.CTkEntry(
self.content,
height=45,
placeholder_text="Domaine à résoudre…"
)
self.net_entry.pack(fill="x", pady=20)
ctk.CTkButton(
self.content,
text="RESOLVE",
height=42,
fg_color=PURPLE,
hover_color=PURPLE_DARK,
command=self.resolve_dns
).pack(anchor="w")
self.net_result = ctk.CTkTextbox(
self.content,
fg_color=PANEL
)
self.net_result.pack(fill="both", expand=True, pady=20)
def resolve_dns(self):
domain = self.net_entry.get().strip()
if not domain:
return
try:
infos = socket.getaddrinfo(domain, None)
addresses = set()
for info in infos:
addresses.add(info[4][0])
result = "DNS RESULTS\n──────────────\n\n"
for address in addresses:
result += f"• {address}\n"
except Exception as e:
result = f"Erreur : {e}"
self.net_result.delete("1.0", "end")
self.net_result.insert("end", result)
# =========================
# PC INFO
# =========================
def show_pc(self):
self.clear_content()
self.set_title("PC Information")
ctk.CTkLabel(
self.content,
text="System Information",
font=ctk.CTkFont(size=25, weight="bold")
).pack(anchor="w", pady=(10, 20))
frame = ctk.CTkFrame(
self.content,
fg_color=PANEL,
corner_radius=12
)
frame.pack(fill="both", expand=True)
info = (
f"Système : {platform.system()}\n"
f"Version : {platform.version()}\n"
f"Machine : {platform.machine()}\n"
f"Processeur : {platform.processor()}\n"
f"Architecture : {platform.architecture()[0]}\n"
f"Python : {platform.python_version()}\n"
)
ctk.CTkLabel(
frame,
text=info,
justify="left",
font=ctk.CTkFont(size=14)
).pack(anchor="nw", padx=25, pady=25)
# =========================
# PYTHON
# =========================
def show_python(self):
self.clear_content()
self.set_title("Python")
ctk.CTkLabel(
self.content,
text="Python Tools",
font=ctk.CTkFont(size=25, weight="bold")
).pack(anchor="w", pady=(10, 5))
ctk.CTkLabel(
self.content,
text="Espace réservé aux outils Python.",
text_color=MUTED
).pack(anchor="w", pady=(0, 20))
box = ctk.CTkTextbox(
self.content,
fg_color=PANEL,
corner_radius=12
)
box.pack(fill="both", expand=True)
box.insert(
"end",
"# NEXUS Python Workspace\n\n"
"print('Hello NEXUS')\n"
)
# =========================
# SETTINGS
# =========================
def show_settings(self):
self.clear_content()
self.set_title("Settings")
ctk.CTkLabel(
self.content,
text="Settings",
font=ctk.CTkFont(size=25, weight="bold")
).pack(anchor="w", pady=(10, 25))
frame = ctk.CTkFrame(
self.content,
fg_color=PANEL,
corner_radius=12
)
frame.pack(fill="x")
ctk.CTkLabel(
frame,
text="Interface",
font=ctk.CTkFont(size=15, weight="bold")
).pack(anchor="w", padx=20, pady=(20, 5))
ctk.CTkLabel(
frame,
text="Mode sombre activé",
text_color=MUTED
).pack(anchor="w", padx=20, pady=(0, 15))
switch = ctk.CTkSwitch(
frame,
text="Dark Mode",
command=self.toggle_theme
)
switch.select()
switch.pack(anchor="w", padx=20, pady=(0, 20))
def toggle_theme(self):
mode = ctk.get_appearance_mode()
if mode == "Dark":
ctk.set_appearance_mode("Light")
else:
ctk.set_appearance_mode("Dark")
# =========================
# START
# =========================
if __name__ == "__main__":
app = NexusAI()
app.mainloop()
Source: r/u/Ill-Gain8546 · by /u/Ill-Gain8546