Bienvenue sur CFTPfr.fr › Forums › core › interface_demarrage.py — v2 (Linux, bug corrigé)
- Ce sujet est vide.
Affichage de 1 message (sur 1 au total)
-
AuteurMessages
-
26.07.2026 à 21h30 #224
Mario Da Conceicao
Maître des clésVersion corrigée du 25/07/2026 — étape 3 du portage Linux. Trois changements :
- Chemins calculés automatiquement (plus de "D:…" en dur)
- Remplacement des mécanismes Windows-only (STARTUPINFO, CREATE_NO_WINDOW) par un lancement de processus simple, qui fonctionne pareil sous Windows et Linux
- Utilise directement l’interpréteur Python en cours d’exécution (sys.executable) au lieu d’un chemin figé vers pythonw.exe — logique une fois qu’on n’aura plus WinPython embarqué
⚠️ Point non résolu, à valider avec toi : le bouton "Lancer l’IA" pointait par erreur vers mira_os.py. Or mira_ia.py (le vrai module IA) n’a pas d’écran à lui — c’est une brique utilisée en coulisse par mira_os.py et par ce fichier. En attendant qu’on décide ensemble s’il faut lui construire un écran propre, j’ai fait pointer ce bouton vers le chat (chat_ia.py), qui est la chose la plus proche d’"interagir avec l’IA" qui ait un vrai écran aujourd’hui. Dis-moi si tu préfères autre chose.
import tkinter as tk from tkinter import messagebox, simpledialog from pathlib import Path import subprocess import sys import os import json import hashlib import secrets import importlib.util # --- CORRECTION 1 : chemins calculés automatiquement, plus de "D:\..." en dur --- BASE_DIR = Path(__file__).resolve().parent # CORRECTION 3 : on utilise l'interpréteur Python en cours d'exécution, plus de pythonw.exe figé PYTHON_EXE = Path(sys.executable) MIRA_OS_FILE = (BASE_DIR / "mira_os" / "mira_os.py").resolve() CHAT_FILE = (BASE_DIR / "mira_ai" / "chat_ia.py").resolve() USERS_FILE = (BASE_DIR / "mira_ai" / "utilisateurs.json").resolve() PLUGINS_DIR = (BASE_DIR / "mira_ai" / "plugins").resolve() CONFIG_FILE = (BASE_DIR / "mira_ai" / "config.json").resolve() MIRA_LANG_FILE = (BASE_DIR / "mira_lang" / "main.py").resolve() # --- Fonctions de hachage des mots de passe (inchangées, déjà correctes) --- def hacher_mot_de_passe(mot_de_passe: str) -> str: salt = secrets.token_hex(16) hash_mdp = hashlib.sha256((mot_de_passe + salt).encode("utf-8")).hexdigest() return f"{salt}:{hash_mdp}" def verifier_mot_de_passe(mot_de_passe: str, stocke: str) -> bool: try: salt, hash_stocke = stocke.split(":") return hashlib.sha256((mot_de_passe + salt).encode("utf-8")).hexdigest() == hash_stocke except Exception: return False class PluginManager: def __init__(self, plugins_dir=PLUGINS_DIR): self.plugins_dir = Path(plugins_dir) self.plugins = {} self.charger_plugins() def charger_plugins(self): self.plugins = {} if not self.plugins_dir.exists(): self.plugins_dir.mkdir(parents=True, exist_ok=True) return for file in self.plugins_dir.glob("*.py"): if file.name.startswith("_"): continue try: spec = importlib.util.spec_from_file_location(file.stem, file) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) if hasattr(module, "INTENTION") and hasattr(module, "executer"): self.plugins[module.INTENTION] = module except Exception as e: print(f"Erreur chargement plugin {file.name}: {e}") def executer(self, intention, message, app): module = self.plugins.get(intention) if module: try: return module.executer(message, app) except Exception as e: return f"Erreur dans le plugin '{intention}': {e}" return None class InterfaceDemarrage: def __init__(self): self.fenetre = tk.Tk() self.fenetre.title("MIRA_OS - Centre de contrôle") self.fenetre.geometry("600x550") (BASE_DIR / "mira_ai").mkdir(parents=True, exist_ok=True) PLUGINS_DIR.mkdir(parents=True, exist_ok=True) self.verifier_utilisateurs_par_defaut() self.plugin_manager = PluginManager() self.creer_interface() def verifier_utilisateurs_par_defaut(self): if not USERS_FILE.exists(): try: with open(USERS_FILE, "w", encoding="utf-8") as f: json.dump({ "utilisateurs": [ {"nom": "admin", "mot_de_passe": hacher_mot_de_passe("admin123"), "role": "administrateur"} ] }, f, indent=4, ensure_ascii=False) except Exception as e: messagebox.showerror("Erreur", f"Impossible de créer le fichier: {e}") def creer_interface(self): tk.Label(self.fenetre, text="Bienvenue dans MIRA_OS", font=("Arial", 16, "bold")).pack(pady=10) frame_boutons = tk.Frame(self.fenetre) frame_boutons.pack(pady=20) boutons = [ ("🖥️ Lancer MIRA_OS", self.lancer_mira_os, "#4CAF50", 0, 0), ("🤖 Lancer l'IA", self.lancer_ia, "#2196F3", 0, 1), ("💬 Chat avec l'IA", self.lancer_chat, "#FF9800", 0, 2), ("📘 Lancer MIRA_LANG", self.lancer_lang, "#3F51B5", 1, 0), ("🔄 Mise à jour", self.mise_a_jour_ia, "#17A2B8", 1, 1), ("👤 Gérer les utilisateurs", self.gerer_utilisateurs, "#9C27B0", 1, 2), ("🔌 Recharger plugins", self.recharger_plugins, "#607D8B", 2, 0) ] for texte, commande, couleur, row, col in boutons: tk.Button( frame_boutons, text=texte, command=commande, width=15, height=3, font=("Arial", 10, "bold"), bg=couleur, fg="white" ).grid(row=row, column=col, padx=10, pady=10) tk.Button( self.fenetre, text="❌ Quitter", command=self.quitter, width=10, height=2, font=("Arial", 10, "bold"), bg="#F44336", fg="white" ).pack(pady=20) def lancer_processus(self, fichier_py): """ CORRECTION 2 : lancement de processus simplifié, sans STARTUPINFO ni CREATE_NO_WINDOW (mécanismes Windows-only). Fonctionne pareil sous Windows et Linux. Sur un système sans bureau, il n'y a de toute façon pas de fenêtre à cacher. """ if not PYTHON_EXE.exists(): messagebox.showerror("Erreur critique", f"Interpréteur Python introuvable :\n{PYTHON_EXE}") return if not fichier_py.exists(): messagebox.showerror( "Erreur critique", f"Fichier introuvable.\n\nChemin attendu :\n{fichier_py}" ) return try: process = subprocess.Popen( [str(PYTHON_EXE), str(fichier_py)], cwd=str(fichier_py.parent), stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True ) try: stdout, stderr = process.communicate(timeout=1) if process.returncode != 0: messagebox.showerror( "Erreur d'exécution", f"Le script a échoué avec le code {process.returncode}.\n\n" f"Erreur :\n{stderr}\n\nSortie :\n{stdout}\n\n" f"Fichier : {fichier_py}" ) except subprocess.TimeoutExpired: # Normal pour une interface graphique qui continue de tourner pass except FileNotFoundError as e: messagebox.showerror("Erreur système", f"Fichier ou programme introuvable :\n{e}") except PermissionError as e: messagebox.showerror("Erreur de permissions", f"Permission refusée :\n{e}") except Exception as e: messagebox.showerror("Erreur inattendue", f"Impossible de lancer le processus :\n{e}") def lancer_mira_os(self): self.lancer_processus(MIRA_OS_FILE) def lancer_ia(self): # CORRECTION BUG : pointait par erreur vers MIRA_OS_FILE. # mira_ia.py n'a pas d'écran propre (voir note en tête de sujet) ; # on pointe vers le chat en attendant une décision sur ce point. self.lancer_processus(CHAT_FILE) def lancer_chat(self): self.lancer_processus(CHAT_FILE) def lancer_lang(self): self.lancer_processus(MIRA_LANG_FILE) def mise_a_jour_ia(self): nouveaux_plugins = self.plugin_manager.charger_plugins() if nouveaux_plugins: messagebox.showinfo("Mise à jour", f"Nouveaux plugins détectés :\n- " + "\n- ".join(nouveaux_plugins)) else: messagebox.showinfo("Mise à jour", "Aucun nouveau plugin détecté.") def gerer_utilisateurs(self): nom = simpledialog.askstring("Connexion", "Nom d'utilisateur :") if not nom: return mot_de_passe = simpledialog.askstring("Connexion", "Mot de passe :", show="*") if not mot_de_passe: return if self.verifier_utilisateur(nom, mot_de_passe): self.fenetre_utilisateurs() else: messagebox.showerror("Erreur", "Nom d'utilisateur ou mot de passe incorrect.") def verifier_utilisateur(self, nom, mot_de_passe): if not USERS_FILE.exists(): return False try: with open(USERS_FILE, "r", encoding="utf-8") as f: data = json.load(f) for utilisateur in data.get("utilisateurs", []): if utilisateur["nom"] == nom and verifier_mot_de_passe(mot_de_passe, utilisateur["mot_de_passe"]): return True return False except Exception: return False def fenetre_utilisateurs(self): fenetre_users = tk.Toplevel(self.fenetre) fenetre_users.title("Gestion des utilisateurs") fenetre_users.geometry("400x300") tk.Button( fenetre_users, text="➕ Ajouter un utilisateur", command=self.ajouter_utilisateur, width=30, height=2, font=("Arial", 10, "bold"), bg="#4CAF50", fg="white" ).pack(pady=10) tk.Button( fenetre_users, text="➖ Supprimer un utilisateur", command=self.supprimer_utilisateur, width=30, height=2, font=("Arial", 10, "bold"), bg="#F44336", fg="white" ).pack(pady=10) def ajouter_utilisateur(self): nom = simpledialog.askstring("Nouvel utilisateur", "Nom :") if not nom: return mot_de_passe = simpledialog.askstring("Nouvel utilisateur", "Mot de passe :", show="*") if not mot_de_passe: return role = simpledialog.askstring("Nouvel utilisateur", "Rôle :", initialvalue="utilisateur") or "utilisateur" try: if USERS_FILE.exists(): with open(USERS_FILE, "r", encoding="utf-8") as f: data = json.load(f) else: data = {"utilisateurs": []} for u in data["utilisateurs"]: if u["nom"] == nom: messagebox.showerror("Erreur", f"L'utilisateur {nom} existe déjà !") return data["utilisateurs"].append({ "nom": nom, "mot_de_passe": hacher_mot_de_passe(mot_de_passe), "role": role }) with open(USERS_FILE, "w", encoding="utf-8") as f: json.dump(data, f, indent=4, ensure_ascii=False) messagebox.showinfo("Succès", f"Utilisateur {nom} ajouté !") except Exception as e: messagebox.showerror("Erreur", f"Erreur: {e}") def supprimer_utilisateur(self): nom = simpledialog.askstring("Supprimer un utilisateur", "Nom :") if not nom: return if not USERS_FILE.exists(): messagebox.showerror("Erreur", "Aucun utilisateur.") return try: with open(USERS_FILE, "r", encoding="utf-8") as f: data = json.load(f) utilisateurs = [u for u in data["utilisateurs"] if u["nom"] != nom] if len(utilisateurs) == len(data["utilisateurs"]): messagebox.showerror("Erreur", f"Utilisateur {nom} introuvable.") return data["utilisateurs"] = utilisateurs with open(USERS_FILE, "w", encoding="utf-8") as f: json.dump(data, f, indent=4, ensure_ascii=False) messagebox.showinfo("Succès", f"Utilisateur {nom} supprimé !") except Exception as e: messagebox.showerror("Erreur", f"Erreur: {e}") def recharger_plugins(self): nouveaux = self.plugin_manager.charger_plugins() if nouveaux: messagebox.showinfo("Plugins", f"Nouveaux plugins chargés:\n- " + "\n- ".join(nouveaux)) else: messagebox.showinfo("Plugins", "Aucun nouveau plugin détecté.") def quitter(self): self.fenetre.destroy() def run(self): self.fenetre.mainloop() if __name__ == "__main__": app = InterfaceDemarrage() app.run() -
AuteurMessages
Affichage de 1 message (sur 1 au total)
- Vous devez être connecté pour répondre à ce sujet.