""" Controller für TikTok-spezifische Funktionalität. Mit TextSimilarity-Integration für robusteres UI-Element-Matching. """ import logging import time import random from PyQt5.QtCore import QThread, pyqtSignal, QObject from controllers.platform_controllers.base_controller import BasePlatformController from views.tabs.generator_tab import GeneratorTab from views.tabs.accounts_tab import AccountsTab from views.tabs.settings_tab import SettingsTab from social_networks.tiktok.tiktok_automation import TikTokAutomation from utils.text_similarity import TextSimilarity logger = logging.getLogger("tiktok_controller") class TikTokWorkerThread(QThread): """Thread für die TikTok-Account-Erstellung.""" # Signale update_signal = pyqtSignal(str) log_signal = pyqtSignal(str) progress_signal = pyqtSignal(int) finished_signal = pyqtSignal(dict) error_signal = pyqtSignal(str) def __init__(self, params): super().__init__() self.params = params self.running = True # TextSimilarity für robustes Fehler-Matching self.text_similarity = TextSimilarity(default_threshold=0.7) # Fehler-Patterns für robustes Fehler-Matching self.error_patterns = [ "Fehler", "Error", "Fehlgeschlagen", "Failed", "Problem", "Issue", "Nicht möglich", "Not possible", "Bitte versuchen Sie es erneut", "Please try again", "Konnte nicht", "Could not", "Timeout" ] def run(self): """Führt die Account-Erstellung aus.""" try: self.log_signal.emit("TikTok-Account-Erstellung gestartet...") self.progress_signal.emit(10) # TikTok-Automation initialisieren automation = TikTokAutomation( headless=self.params.get("headless", False), use_proxy=self.params.get("use_proxy", False), proxy_type=self.params.get("proxy_type"), save_screenshots=True, debug=self.params.get("debug", False), email_domain=self.params.get("email_domain", "z5m7q9dk3ah2v1plx6ju.com") ) self.update_signal.emit("TikTok-Automation initialisiert") self.progress_signal.emit(20) # Account registrieren self.log_signal.emit(f"Registriere Account für: {self.params['full_name']}") registration_method = self.params.get("registration_method", "email") phone_number = self.params.get("phone_number") # Account registrieren result = automation.register_account( full_name=self.params["full_name"], age=self.params["age"], registration_method=registration_method, phone_number=phone_number, **self.params.get("additional_params", {}) ) self.progress_signal.emit(100) if result["success"]: self.log_signal.emit("Account erfolgreich erstellt!") self.finished_signal.emit(result) else: # Robuste Fehlerbehandlung mit TextSimilarity error_msg = result.get("error", "Unbekannter Fehler") # Versuche, Fehler nutzerfreundlicher zu interpretieren user_friendly_error = self._interpret_error(error_msg) self.log_signal.emit(f"Fehler bei der Account-Erstellung: {user_friendly_error}") self.error_signal.emit(user_friendly_error) except Exception as e: logger.error(f"Fehler im Worker-Thread: {e}") self.log_signal.emit(f"Schwerwiegender Fehler: {str(e)}") self.error_signal.emit(str(e)) self.progress_signal.emit(0) def _interpret_error(self, error_msg: str) -> str: """ Interpretiert Fehlermeldungen und gibt eine benutzerfreundlichere Version zurück. Verwendet TextSimilarity für robusteres Fehler-Matching. Args: error_msg: Die ursprüngliche Fehlermeldung Returns: str: Benutzerfreundliche Fehlermeldung """ # Bekannte Fehlermuster und deren Interpretationen error_interpretations = { "captcha": "TikTok hat einen Captcha-Test angefordert. Versuchen Sie es später erneut oder nutzen Sie einen anderen Proxy.", "verification": "Es gab ein Problem mit der Verifizierung des Accounts. Bitte prüfen Sie die E-Mail-Einstellungen.", "proxy": "Problem mit der Proxy-Verbindung. Bitte prüfen Sie Ihre Proxy-Einstellungen.", "timeout": "Zeitüberschreitung bei der Verbindung. Bitte überprüfen Sie Ihre Internetverbindung.", "username": "Der gewählte Benutzername ist bereits vergeben oder nicht zulässig.", "password": "Das Passwort erfüllt nicht die Anforderungen von TikTok.", "email": "Die E-Mail-Adresse konnte nicht verwendet werden. Bitte nutzen Sie eine andere E-Mail-Domain.", "phone": "Die Telefonnummer konnte nicht für die Registrierung verwendet werden.", "age": "Das eingegebene Alter erfüllt nicht die Anforderungen von TikTok.", "too_many_attempts": "Zu viele Registrierungsversuche. Bitte warten Sie und versuchen Sie es später erneut." } # Versuche, den Fehler zu kategorisieren for pattern, interpretation in error_interpretations.items(): for error_term in self.error_patterns: if (pattern in error_msg.lower() or self.text_similarity.is_similar(error_term, error_msg, threshold=0.7)): return interpretation # Fallback: Originale Fehlermeldung zurückgeben return error_msg def stop(self): """Stoppt den Thread.""" self.running = False self.terminate() class TikTokController(BasePlatformController): """Controller für TikTok-spezifische Funktionalität.""" def __init__(self, db_manager, proxy_rotator, email_handler, language_manager=None): super().__init__("TikTok", db_manager, proxy_rotator, email_handler, language_manager) self.worker_thread = None # TextSimilarity für robustes UI-Element-Matching self.text_similarity = TextSimilarity(default_threshold=0.75) def create_generator_tab(self): """Erstellt den TikTok-Generator-Tab.""" generator_tab = GeneratorTab(self.platform_name, self.language_manager) # TikTok-spezifische Anpassungen # Diese Methode überschreiben, wenn spezifische Anpassungen benötigt werden # Signale verbinden generator_tab.start_requested.connect(self.start_account_creation) generator_tab.stop_requested.connect(self.stop_account_creation) return generator_tab def start_account_creation(self, params): """Startet die TikTok-Account-Erstellung.""" super().start_account_creation(params) # Validiere Eingaben is_valid, error_msg = self.validate_inputs(params) if not is_valid: self.get_generator_tab().show_error(error_msg) return # UI aktualisieren generator_tab = self.get_generator_tab() generator_tab.set_running(True) generator_tab.clear_log() generator_tab.set_progress(0) # Worker-Thread starten self.worker_thread = TikTokWorkerThread(params) self.worker_thread.update_signal.connect(lambda msg: generator_tab.set_status(msg)) self.worker_thread.log_signal.connect(lambda msg: generator_tab.add_log(msg)) self.worker_thread.error_signal.connect(lambda msg: (generator_tab.show_error(msg), generator_tab.set_running(False))) self.worker_thread.finished_signal.connect(lambda result: self.handle_account_created(result)) self.worker_thread.progress_signal.connect(lambda value: generator_tab.set_progress(value)) self.worker_thread.start() def stop_account_creation(self): """Stoppt die TikTok-Account-Erstellung.""" if self.worker_thread and self.worker_thread.isRunning(): self.worker_thread.stop() generator_tab = self.get_generator_tab() generator_tab.add_log("Account-Erstellung wurde abgebrochen") generator_tab.set_running(False) generator_tab.set_progress(0) def handle_account_created(self, result): """Verarbeitet erfolgreich erstellte Accounts.""" generator_tab = self.get_generator_tab() generator_tab.set_running(False) # Account-Daten aus dem Ergebnis holen account_data = result.get("account_data", {}) # Account-Erfolgsereignis auslösen generator_tab.account_created.emit(self.platform_name, account_data) # Account in der Datenbank speichern self.save_account_to_db(account_data) def save_account_to_db(self, account_data): """Speichert einen erstellten Account in der Datenbank.""" account = { "platform": self.platform_name.lower(), "username": account_data.get("username", ""), "password": account_data.get("password", ""), "email": account_data.get("email", ""), "phone": account_data.get("phone", ""), "full_name": account_data.get("full_name", ""), "created_at": time.strftime("%Y-%m-%d %H:%M:%S") } self.db_manager.add_account(account) logger.info(f"Account in Datenbank gespeichert: {account['username']}") def validate_inputs(self, inputs): """ Validiert die Eingaben für die Account-Erstellung. Verwendet TextSimilarity für robustere Validierung. """ # Basis-Validierungen von BasePlatformController verwenden valid, error_msg = super().validate_inputs(inputs) if not valid: return valid, error_msg # TikTok-spezifische Validierungen age = inputs.get("age", 0) if age < 13: return False, "Das Alter muss mindestens 13 sein (TikTok-Anforderung)." # E-Mail-Domain-Validierung if inputs.get("registration_method") == "email": email_domain = inputs.get("email_domain", "") # Blacklist von bekannten problematischen Domains blacklisted_domains = ["temp-mail.org", "guerrillamail.com", "maildrop.cc"] # Prüfe mit TextSimilarity auf Ähnlichkeit mit Blacklist for domain in blacklisted_domains: if self.text_similarity.is_similar(email_domain, domain, threshold=0.8): return False, f"Die E-Mail-Domain '{email_domain}' kann problematisch für die TikTok-Registrierung sein. Bitte verwenden Sie eine andere Domain." return True, "" def get_form_field_label(self, field_type: str) -> str: """ Gibt einen Label-Text für ein Formularfeld basierend auf dem Feldtyp zurück. Args: field_type: Typ des Formularfelds Returns: str: Label-Text für das Formularfeld """ # Mapping von Feldtypen zu Labels field_labels = { "full_name": "Vollständiger Name", "username": "Benutzername", "password": "Passwort", "email": "E-Mail-Adresse", "phone": "Telefonnummer", "age": "Alter", "birthday": "Geburtsdatum" } return field_labels.get(field_type, field_type.capitalize())