Files
AccountForger-neuerUpload/controllers/main_controller.py
Claude Project Manager f0320a9298 X-Problem gelöst
2025-09-14 02:47:52 +02:00

409 Zeilen
18 KiB
Python

"""
Hauptcontroller für die Social Media Account Generator Anwendung.
"""
import logging
import sys
from PyQt5.QtWidgets import QMessageBox, QApplication
from views.main_window import MainWindow
from views.dialogs.license_activation_dialog import LicenseActivationDialog
from controllers.platform_controllers.instagram_controller import InstagramController
from controllers.platform_controllers.tiktok_controller import TikTokController
from controllers.account_controller import AccountController
from controllers.settings_controller import SettingsController
from controllers.session_controller import SessionController
from database.db_manager import DatabaseManager
from utils.proxy_rotator import ProxyRotator
from utils.email_handler import EmailHandler
from utils.theme_manager import ThemeManager
from localization.language_manager import LanguageManager
from licensing.license_manager import LicenseManager
from updates.update_checker import UpdateChecker
from application.services.platform_service import PlatformService
logger = logging.getLogger("main")
class MainController:
"""Hauptcontroller, der die Anwendung koordiniert."""
def __init__(self, app):
# QApplication Referenz speichern
self.app = app
# Theme Manager initialisieren
self.theme_manager = ThemeManager(app)
# Language Manager initialisieren
self.language_manager = LanguageManager(app)
# Lizenz Manager als erstes initialisieren
self.license_manager = LicenseManager()
# Lizenz prüfen bevor andere Komponenten geladen werden
if not self._check_and_activate_license():
logger.error("Keine gültige Lizenz - Anwendung wird beendet")
sys.exit(1)
# Modelle initialisieren
self.db_manager = DatabaseManager()
self.proxy_rotator = ProxyRotator()
self.email_handler = EmailHandler()
self.update_checker = UpdateChecker(self.license_manager.api_client)
self.platform_service = PlatformService(self.db_manager)
# Haupt-View erstellen
self.view = MainWindow(self.theme_manager, self.language_manager, self.db_manager)
# Untercontroller erstellen
self.account_controller = AccountController(self.db_manager)
self.account_controller.set_parent_view(self.view)
self.settings_controller = SettingsController(
self.proxy_rotator,
self.email_handler,
self.license_manager
)
self.session_controller = SessionController(self.db_manager)
# Plattform-Controller initialisieren - nur für aktive Plattformen
self.platform_controllers = {}
self._initialize_active_platform_controllers()
# Signals verbinden
self.connect_signals()
# Remove unused theme_toggled connection
# The theme toggle is now handled directly in MainWindow
# Platform Selector Signal-Verbindungen
if hasattr(self.view.platform_selector, 'export_requested'):
self.view.platform_selector.export_requested.connect(
lambda accounts: self.account_controller.export_accounts(None, accounts)
)
if hasattr(self.view.platform_selector, 'login_requested'):
self.view.platform_selector.login_requested.connect(
self.session_controller.perform_one_click_login
)
# Session-Status-Update Signal entfernt (Session-Funktionalität deaktiviert)
# Login-Result Signals verbinden
self.session_controller.login_successful.connect(self._on_login_successful)
self.session_controller.login_failed.connect(self._on_login_failed)
# Session starten
self._start_license_session()
# Auf Updates prüfen
self.check_for_updates()
# Hauptfenster anzeigen
self.view.show()
def _on_login_successful(self, account_id: str, session_data: dict):
"""Behandelt erfolgreiches Login"""
# GEÄNDERT: Kein Popup mehr - User sieht Erfolg direkt im Browser
try:
account = self.db_manager.get_account(int(account_id))
username = account.get('username', 'Unknown') if account else 'Unknown'
platform = account.get('platform', 'Unknown') if account else 'Unknown'
logger.info(f"Login erfolgreich für Account {account_id} ({username}) - Browser bleibt offen")
# Popup entfernt - User hat direktes Feedback über Browser-Status
except Exception as e:
print(f"Error showing success message: {e}")
def _on_login_failed(self, account_id: str, error_message: str):
"""Behandelt fehlgeschlagenes Login"""
from PyQt5.QtWidgets import QMessageBox
# Account-Details für die Nachricht holen
try:
account = self.db_manager.get_account(int(account_id))
username = account.get('username', 'Unknown') if account else 'Unknown'
msg = QMessageBox(self.view)
msg.setIcon(QMessageBox.Warning)
msg.setWindowTitle("Login Fehlgeschlagen")
msg.setText(f"Ein-Klick-Login fehlgeschlagen!")
msg.setInformativeText(f"Account: {username}\nFehler: {error_message}")
msg.setStandardButtons(QMessageBox.Ok)
msg.exec_()
except Exception as e:
print(f"Error showing failure message: {e}")
def connect_signals(self):
"""Verbindet alle Signale mit den entsprechenden Slots."""
# Plattformauswahl-Signal verbinden
self.view.platform_selected.connect(self.on_platform_selected)
# Zurück-Button verbinden
self.view.back_to_selector_requested.connect(self.show_platform_selector)
def on_platform_selected(self, platform: str):
"""Wird aufgerufen, wenn eine Plattform ausgewählt wird."""
logger.info(f"Plattform ausgewählt: {platform}")
# Aktuelle Plattform setzen
self.current_platform = platform.lower()
# Prüfen, ob die Plattform unterstützt wird
if self.current_platform not in self.platform_controllers:
logger.error(f"Plattform '{platform}' wird nicht unterstützt")
QMessageBox.critical(
self.view,
"Nicht unterstützt",
f"Die Plattform '{platform}' ist noch nicht implementiert."
)
return
# Plattformspezifischen Controller abrufen
platform_controller = self.platform_controllers.get(self.current_platform)
# Plattform-View initialisieren
self.view.init_platform_ui(platform, platform_controller)
# Tab-Hooks verbinden
self.connect_tab_hooks(platform_controller)
# Plattformspezifische Ansicht anzeigen
self.view.show_platform_ui()
def on_theme_toggled(self):
"""Wird aufgerufen, wenn das Theme gewechselt wird."""
if self.theme_manager:
theme_name = self.theme_manager.get_current_theme()
logger.info(f"Theme gewechselt zu: {theme_name}")
# Hier kann zusätzliche Logik für Theme-Wechsel hinzugefügt werden
# z.B. UI-Elemente aktualisieren, die nicht automatisch aktualisiert werden
def connect_tab_hooks(self, platform_controller):
"""Verbindet die Tab-Hooks mit dem Plattform-Controller."""
# Generator-Tab-Hooks
# HINWEIS: account_created Signal ist nicht mehr verbunden, da Accounts
# jetzt über SessionController mit Clean Architecture gespeichert werden
if hasattr(platform_controller, "get_generator_tab"):
generator_tab = platform_controller.get_generator_tab()
# generator_tab.account_created.connect(self.account_controller.on_account_created) # Deaktiviert
# Einstellungen-Tab-Hooks
if hasattr(platform_controller, "get_settings_tab"):
settings_tab = platform_controller.get_settings_tab()
settings_tab.proxy_settings_saved.connect(self.settings_controller.save_proxy_settings)
settings_tab.proxy_tested.connect(self.settings_controller.test_proxy)
settings_tab.email_settings_saved.connect(self.settings_controller.save_email_settings)
settings_tab.email_tested.connect(self.settings_controller.test_email)
settings_tab.license_activated.connect(self.settings_controller.activate_license)
def show_platform_selector(self):
"""Zeigt den Plattform-Selektor an."""
logger.info("Zurück zur Plattformauswahl")
self.view.show_platform_selector()
if hasattr(self.view, "platform_selector"):
self.view.platform_selector.load_accounts()
def show_platform_selector_and_reset(self):
"""Zeigt den Plattform-Selektor an und setzt die Eingabefelder zurück."""
logger.info("Zurück zur Plattformauswahl mit Reset der Eingabefelder")
# Eingabefelder des aktuellen Platform-Controllers zurücksetzen
if hasattr(self, 'current_platform') and self.current_platform in self.platform_controllers:
controller = self.platform_controllers[self.current_platform]
if hasattr(controller, '_generator_tab') and controller._generator_tab:
# Tab auf None setzen, damit beim nächsten Öffnen ein neuer erstellt wird
controller._generator_tab = None
# Zur Plattformauswahl zurückkehren
self.show_platform_selector()
def _check_and_activate_license(self):
"""
Prüft die Lizenz und zeigt den Aktivierungsdialog wenn nötig.
Returns:
True wenn Lizenz gültig, False wenn Benutzer abbricht
"""
# Versuche Session fortzusetzen
if self.license_manager.resume_session():
logger.info("Bestehende Session fortgesetzt")
return True
# Prüfe ob Lizenz vorhanden ist
if self.license_manager.is_licensed():
# Starte neue Session
if self.license_manager.start_session():
logger.info("Neue Session gestartet")
return True
else:
logger.error("Session konnte nicht gestartet werden")
# Zeige Fehlermeldung statt Aktivierungsdialog
# Hole detaillierte Fehlermeldung
session_result = self.license_manager.session_manager.start_session(
self.license_manager.license_data["key"],
self.license_manager.license_data.get("activation_id")
)
error_msg = session_result.get("error", "Unbekannter Fehler")
QMessageBox.critical(
None,
"Session-Fehler",
f"Die Lizenz ist gültig, aber es konnte keine Session gestartet werden.\n\n"
f"Grund: {error_msg}\n\n"
"Mögliche Lösungen:\n"
"- Schließen Sie andere laufende Instanzen\n"
"- Warten Sie einen Moment und versuchen Sie es erneut\n"
"- Kontaktieren Sie den Support",
QMessageBox.Ok
)
return False
# Keine gültige Lizenz - zeige Aktivierungsdialog
logger.info("Keine gültige Lizenz gefunden - zeige Aktivierungsdialog")
dialog = LicenseActivationDialog(self.license_manager)
dialog.activation_successful.connect(self._on_license_activated)
result = dialog.exec_()
return result == dialog.Accepted
def _on_license_activated(self):
"""Wird aufgerufen wenn Lizenz erfolgreich aktiviert wurde."""
logger.info("Lizenz wurde erfolgreich aktiviert")
def _start_license_session(self):
"""Startet die Lizenz-Session für die laufende Anwendung."""
if not self.license_manager.session_manager.is_session_active():
if self.license_manager.is_licensed():
self.license_manager.start_session()
def check_license(self):
"""Überprüft den Lizenzstatus (für UI Updates)."""
is_licensed = self.license_manager.is_licensed()
license_info = self.license_manager.get_license_info()
status_text = self.license_manager.get_status_text()
# UI kann hier aktualisiert werden basierend auf Lizenzstatus
logger.info(f"Lizenzstatus: {status_text}")
return is_licensed
def check_for_updates(self):
"""Prüft auf Updates."""
try:
# Mit Lizenzschlüssel prüfen wenn vorhanden
license_key = self.license_manager.get_license_info().get("key")
update_info = self.update_checker.check_for_updates(license_key=license_key)
if update_info["has_update"]:
reply = QMessageBox.question(
self.view,
"Update verfügbar",
f"Eine neue Version ist verfügbar: {update_info['latest_version']}\n"
f"(Aktuelle Version: {update_info['current_version']})\n\n"
f"Release-Datum: {update_info['release_date']}\n"
f"Release-Notes:\n{update_info['release_notes']}\n\n"
"Möchten Sie das Update jetzt herunterladen?",
QMessageBox.Yes | QMessageBox.No,
QMessageBox.Yes
)
if reply == QMessageBox.Yes:
self.download_update(update_info)
except Exception as e:
logger.error(f"Fehler bei der Update-Prüfung: {e}")
def download_update(self, update_info):
"""Lädt ein Update herunter."""
try:
download_result = self.update_checker.download_update(
update_info["download_url"],
update_info["latest_version"]
)
if download_result["success"]:
QMessageBox.information(
self.view,
"Download erfolgreich",
f"Update wurde heruntergeladen: {download_result['file_path']}\n\n"
"Bitte schließen Sie die Anwendung und führen Sie das Update aus."
)
else:
QMessageBox.warning(
self.view,
"Download fehlgeschlagen",
f"Fehler beim Herunterladen des Updates:\n{download_result['error']}"
)
except Exception as e:
logger.error(f"Fehler beim Herunterladen des Updates: {e}")
QMessageBox.critical(
self.view,
"Fehler",
f"Fehler beim Herunterladen des Updates:\n{str(e)}"
)
def _initialize_active_platform_controllers(self):
"""Initialisiert nur Controller für aktive Plattformen."""
active_platforms = self.platform_service.get_active_platforms()
for platform in active_platforms:
platform_id = platform.id.lower()
try:
if platform_id == "instagram":
controller = InstagramController(
self.db_manager,
self.proxy_rotator,
self.email_handler,
self.language_manager
)
controller.return_to_main_requested = lambda: self.show_platform_selector_and_reset()
controller.session_controller = self.session_controller
self.platform_controllers["instagram"] = controller
elif platform_id == "tiktok":
controller = TikTokController(
self.db_manager,
self.proxy_rotator,
self.email_handler,
self.language_manager
)
controller.return_to_main_requested = lambda: self.show_platform_selector_and_reset()
controller.session_controller = self.session_controller
self.platform_controllers["tiktok"] = controller
elif platform_id == "x":
from controllers.platform_controllers.x_controller import XController
controller = XController(
self.db_manager,
self.proxy_rotator,
self.email_handler,
self.language_manager
)
controller.return_to_main_requested = lambda: self.show_platform_selector_and_reset()
controller.session_controller = self.session_controller
self.platform_controllers["x"] = controller
elif platform_id == "facebook":
from controllers.platform_controllers.facebook_controller import FacebookController
controller = FacebookController(
self.db_manager,
self.proxy_rotator,
self.email_handler,
self.language_manager
)
controller.return_to_main_requested = lambda: self.show_platform_selector_and_reset()
controller.session_controller = self.session_controller
self.platform_controllers["facebook"] = controller
logger.info(f"Controller für Plattform '{platform_id}' initialisiert")
except ImportError as e:
logger.warning(f"Controller für Plattform '{platform_id}' konnte nicht geladen werden: {e}")
except Exception as e:
logger.error(f"Fehler beim Initialisieren des Controllers für '{platform_id}': {e}")