402 Zeilen
17 KiB
Python
402 Zeilen
17 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
|
|
|
|
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)
|
|
|
|
# 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
|
|
self.platform_controllers = {}
|
|
|
|
# Instagram Controller hinzufügen
|
|
instagram_controller = InstagramController(
|
|
self.db_manager,
|
|
self.proxy_rotator,
|
|
self.email_handler,
|
|
self.language_manager
|
|
)
|
|
# Signal für Rückkehr zur Hauptseite verbinden
|
|
instagram_controller.return_to_main_requested = lambda: self.show_platform_selector_and_reset()
|
|
# SessionController referenz hinzufügen
|
|
instagram_controller.session_controller = self.session_controller
|
|
self.platform_controllers["instagram"] = instagram_controller
|
|
|
|
# TikTok Controller hinzufügen
|
|
tiktok_controller = TikTokController(
|
|
self.db_manager,
|
|
self.proxy_rotator,
|
|
self.email_handler,
|
|
self.language_manager
|
|
)
|
|
# Signal für Rückkehr zur Hauptseite verbinden
|
|
tiktok_controller.return_to_main_requested = lambda: self.show_platform_selector_and_reset()
|
|
# SessionController referenz hinzufügen
|
|
tiktok_controller.session_controller = self.session_controller
|
|
self.platform_controllers["tiktok"] = tiktok_controller
|
|
|
|
# X (Twitter) Controller hinzufügen
|
|
from controllers.platform_controllers.x_controller import XController
|
|
x_controller = XController(
|
|
self.db_manager,
|
|
self.proxy_rotator,
|
|
self.email_handler,
|
|
self.language_manager
|
|
)
|
|
# Signal für Rückkehr zur Hauptseite verbinden
|
|
x_controller.return_to_main_requested = lambda: self.show_platform_selector_and_reset()
|
|
# SessionController referenz hinzufügen
|
|
x_controller.session_controller = self.session_controller
|
|
self.platform_controllers["x"] = x_controller
|
|
|
|
# Gmail Controller hinzufügen
|
|
from controllers.platform_controllers.gmail_controller import GmailController
|
|
gmail_controller = GmailController(
|
|
self.db_manager,
|
|
self.proxy_rotator,
|
|
self.email_handler,
|
|
self.language_manager
|
|
)
|
|
# Signal für Rückkehr zur Hauptseite verbinden
|
|
gmail_controller.return_to_main_requested = lambda: self.show_platform_selector_and_reset()
|
|
# SessionController referenz hinzufügen
|
|
gmail_controller.session_controller = self.session_controller
|
|
self.platform_controllers["gmail"] = gmail_controller
|
|
|
|
# Hier können in Zukunft weitere Controller hinzugefügt werden:
|
|
# self.platform_controllers["facebook"] = FacebookController(...)
|
|
|
|
# Signals verbinden
|
|
self.connect_signals()
|
|
|
|
# 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)
|
|
|
|
# Theme-Toggle verbinden
|
|
self.view.theme_toggled.connect(self.on_theme_toggled)
|
|
|
|
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)}"
|
|
) |