# Pfad: views/tabs/generator_tab.py """ Tab zur Erstellung von Social-Media-Accounts. """ import logging from PyQt5.QtWidgets import ( QWidget, QVBoxLayout, QHBoxLayout, QFormLayout, QGroupBox, QLabel, QLineEdit, QSpinBox, QRadioButton, QCheckBox, QComboBox, QPushButton, QTextEdit, QProgressBar, QMessageBox ) from PyQt5.QtCore import Qt, pyqtSignal from utils.logger import add_gui_handler logger = logging.getLogger("generator_tab") class GeneratorTab(QWidget): """Widget für den Account-Generator-Tab.""" # Signale start_requested = pyqtSignal(dict) stop_requested = pyqtSignal() account_created = pyqtSignal(str, dict) # (platform, account_data) def __init__(self, platform_name, language_manager=None): super().__init__() self.platform_name = platform_name self.language_manager = language_manager self.init_ui() if self.language_manager: self.language_manager.language_changed.connect(self.update_texts) self.update_texts() def init_ui(self): """Initialisiert die Benutzeroberfläche.""" layout = QVBoxLayout(self) # Formularbereich self.form_group = QGroupBox() form_layout = QFormLayout() self.form_group.setLayout(form_layout) # Vorname und Nachname statt vollständigem Namen self.first_name_label = QLabel() self.first_name_input = QLineEdit() form_layout.addRow(self.first_name_label, self.first_name_input) self.last_name_label = QLabel() self.last_name_input = QLineEdit() form_layout.addRow(self.last_name_label, self.last_name_input) # Alter (jetzt mit QLineEdit statt QSpinBox) self.age_label = QLabel() self.age_input = QLineEdit() form_layout.addRow(self.age_label, self.age_input) # Registrierungsmethode self.reg_method_group = QWidget() reg_method_layout = QHBoxLayout(self.reg_method_group) reg_method_layout.setContentsMargins(0, 0, 0, 0) self.email_radio = QRadioButton() self.phone_radio = QRadioButton() self.email_radio.setChecked(True) reg_method_layout.addWidget(self.email_radio) reg_method_layout.addWidget(self.phone_radio) self.reg_method_label = QLabel() form_layout.addRow(self.reg_method_label, self.reg_method_group) # Telefonnummer (nur sichtbar, wenn Telefon ausgewählt) self.phone_label = QLabel() self.phone_input = QLineEdit() self.phone_input.setEnabled(False) form_layout.addRow(self.phone_label, self.phone_input) # E-Mail-Domain self.email_domain_label = QLabel() self.email_domain_input = QLineEdit("z5m7q9dk3ah2v1plx6ju.com") form_layout.addRow(self.email_domain_label, self.email_domain_input) # Proxy verwenden self.use_proxy_check = QCheckBox() self.use_proxy_check.setChecked(True) # Proxy-Typ self.proxy_type_combo = QComboBox() proxy_widget = QWidget() proxy_layout = QHBoxLayout(proxy_widget) proxy_layout.setContentsMargins(0, 0, 0, 0) proxy_layout.addWidget(self.use_proxy_check) self.proxy_type_label = QLabel() proxy_layout.addWidget(self.proxy_type_label) proxy_layout.addWidget(self.proxy_type_combo) proxy_layout.addStretch() self.proxy_label = QLabel() form_layout.addRow(self.proxy_label, proxy_widget) # Headless-Modus self.headless_check = QCheckBox() form_layout.addRow("", self.headless_check) # Debug-Modus self.debug_check = QCheckBox() form_layout.addRow("", self.debug_check) # Plattformspezifische Parameter hinzufügen self.add_platform_specific_fields(form_layout) # Formular zum Layout hinzufügen layout.addWidget(self.form_group) # Fortschrittsanzeige self.progress_bar = QProgressBar() self.progress_bar.setRange(0, 100) self.progress_bar.setValue(0) layout.addWidget(self.progress_bar) # Log-Bereich self.log_group = QGroupBox() log_layout = QVBoxLayout(self.log_group) self.log_text = QTextEdit() self.log_text.setReadOnly(True) log_layout.addWidget(self.log_text) # Log-Handler für das TextEdit add_gui_handler(logger, self.log_text) layout.addWidget(self.log_group) # Buttons button_layout = QHBoxLayout() self.start_button = QPushButton() self.start_button.clicked.connect(self.on_start_clicked) self.stop_button = QPushButton() self.stop_button.clicked.connect(self.on_stop_clicked) self.stop_button.setEnabled(False) button_layout.addWidget(self.start_button) button_layout.addWidget(self.stop_button) layout.addLayout(button_layout) # Event-Verbindungen self.email_radio.toggled.connect(self.toggle_phone_input) self.phone_radio.toggled.connect(self.toggle_phone_input) self.use_proxy_check.toggled.connect(self.toggle_proxy_combo) def add_platform_specific_fields(self, form_layout): """ Fügt plattformspezifische Felder hinzu. Diese Methode kann in abgeleiteten Klassen überschrieben werden. Args: form_layout: Das Formular-Layout, zu dem die Felder hinzugefügt werden sollen """ # In plattformspezifischen Unterklassen überschreiben platform = self.platform_name.lower() if platform == "tiktok": # Beispiel: Kategorie/Nische für TikTok self.category_label = QLabel() self.category_combo = QComboBox() categories = [ "Allgemein", "Gaming", "Mode", "Fitness", "Reisen", "Kochen", "Technologie", "Bildung", ] if self.language_manager: categories = [ self.language_manager.get_text( "generator_tab.tiktok_category_general", "Allgemein" ), self.language_manager.get_text( "generator_tab.tiktok_category_gaming", "Gaming" ), self.language_manager.get_text( "generator_tab.tiktok_category_fashion", "Mode" ), self.language_manager.get_text( "generator_tab.tiktok_category_fitness", "Fitness" ), self.language_manager.get_text( "generator_tab.tiktok_category_travel", "Reisen" ), self.language_manager.get_text( "generator_tab.tiktok_category_cooking", "Kochen" ), self.language_manager.get_text( "generator_tab.tiktok_category_technology", "Technologie" ), self.language_manager.get_text( "generator_tab.tiktok_category_education", "Bildung" ), ] self.category_label.setText( self.language_manager.get_text( "generator_tab.tiktok_category_label", "Kategorie/Nische:" ) ) else: self.category_label.setText("Kategorie/Nische:") self.category_combo.addItems(categories) form_layout.addRow(self.category_label, self.category_combo) elif platform == "twitter": # Beispiel: Interessen für Twitter self.interests_combo = QComboBox() interests = ["Allgemein", "Politik", "Technologie", "Wirtschaft", "Sport", "Unterhaltung", "Wissenschaft"] self.interests_combo.addItems(interests) form_layout.addRow("Interessen:", self.interests_combo) elif platform == "facebook": # Beispiel: Datenschutzeinstellungen für Facebook self.privacy_combo = QComboBox() privacy_options = ["Öffentlich", "Nur Freunde", "Freunde außer...", "Nur ich"] self.privacy_combo.addItems(privacy_options) form_layout.addRow("Datenschutz:", self.privacy_combo) def toggle_phone_input(self): """Aktiviert/Deaktiviert das Telefoneingabefeld basierend auf der Radiobutton-Auswahl.""" self.phone_input.setEnabled(self.phone_radio.isChecked()) def toggle_proxy_combo(self): """Aktiviert/Deaktiviert die Proxy-Typ-Combobox basierend auf der Checkbox.""" self.proxy_type_combo.setEnabled(self.use_proxy_check.isChecked()) def on_start_clicked(self): """Wird aufgerufen, wenn der Start-Button geklickt wird.""" # Parameter sammeln params = self.get_params() # Eingaben validieren valid, error_msg = self.validate_inputs(params) if not valid: self.show_error(error_msg) return # Signal auslösen self.start_requested.emit(params) def on_stop_clicked(self): """Wird aufgerufen, wenn der Stop-Button geklickt wird.""" self.stop_requested.emit() def get_params(self): """Sammelt alle Parameter für die Account-Erstellung.""" # Vorname und Nachname kombinieren für den vollständigen Namen first_name = self.first_name_input.text().strip() last_name = self.last_name_input.text().strip() full_name = f"{first_name} {last_name}" params = { "first_name": first_name, "last_name": last_name, "full_name": full_name, "age_text": self.age_input.text().strip(), # Speichere den Rohtext "registration_method": "email" if self.email_radio.isChecked() else "phone", "headless": self.headless_check.isChecked(), "debug": self.debug_check.isChecked(), "email_domain": self.email_domain_input.text().strip() } # Telefonnummer (wenn ausgewählt) if self.phone_radio.isChecked(): params["phone_number"] = self.phone_input.text().strip() # Proxy (wenn aktiviert) if self.use_proxy_check.isChecked(): proxy_type = self.proxy_type_combo.currentText().lower() params["use_proxy"] = True params["proxy_type"] = proxy_type else: params["use_proxy"] = False # Plattformspezifische Parameter additional_params = self.get_platform_specific_params() if additional_params: params["additional_params"] = additional_params return params def validate_inputs(self, params): """ Validiert die Eingaben für die Account-Erstellung. Args: params: Die gesammelten Parameter Returns: tuple: (gültig, Fehlermeldung) """ # Namen prüfen if not params.get("first_name"): msg = "Bitte geben Sie einen Vornamen ein." if self.language_manager: msg = self.language_manager.get_text( "generator_tab.first_name_error", "Bitte geben Sie einen Vornamen ein.", ) return False, msg if not params.get("last_name"): msg = "Bitte geben Sie einen Nachnamen ein." if self.language_manager: msg = self.language_manager.get_text( "generator_tab.last_name_error", "Bitte geben Sie einen Nachnamen ein.", ) return False, msg # Alter prüfen age_text = params.get("age_text", "") if not age_text: msg = "Bitte geben Sie ein Alter ein." if self.language_manager: msg = self.language_manager.get_text( "generator_tab.age_empty_error", "Bitte geben Sie ein Alter ein.", ) return False, msg # Alter muss eine Zahl sein try: age = int(age_text) params["age"] = age # Füge das konvertierte Alter zu den Parametern hinzu except ValueError: msg = "Das Alter muss eine ganze Zahl sein." if self.language_manager: msg = self.language_manager.get_text( "generator_tab.age_int_error", "Das Alter muss eine ganze Zahl sein.", ) return False, msg # Alter-Bereich prüfen - hier ist die allgemeine Prüfung für 13-99 # Die plattformspezifische Validierung kann später in den Controllern erfolgen if age < 13 or age > 99: msg = "Das Alter muss zwischen 13 und 99 liegen." if self.language_manager: msg = self.language_manager.get_text( "generator_tab.age_range_error", "Das Alter muss zwischen 13 und 99 liegen.", ) return False, msg # Telefonnummer prüfen, falls erforderlich if params.get("registration_method") == "phone" and not params.get("phone_number"): msg = "Bitte geben Sie eine Telefonnummer ein." if self.language_manager: msg = self.language_manager.get_text( "generator_tab.phone_error", "Bitte geben Sie eine Telefonnummer ein.", ) return False, msg return True, "" def get_platform_specific_params(self): """ Gibt plattformspezifische Parameter zurück. Diese Methode kann in abgeleiteten Klassen überschrieben werden. Returns: dict: Plattformspezifische Parameter """ # In plattformspezifischen Unterklassen überschreiben platform = self.platform_name.lower() additional_params = {} if platform == "tiktok" and hasattr(self, "category_combo"): additional_params["category"] = self.category_combo.currentText() elif platform == "twitter" and hasattr(self, "interests_combo"): additional_params["interests"] = self.interests_combo.currentText() elif platform == "facebook" and hasattr(self, "privacy_combo"): additional_params["privacy"] = self.privacy_combo.currentText() return additional_params def set_running(self, running: bool): """Setzt den Status auf 'Wird ausgeführt' oder 'Bereit'.""" self.start_button.setEnabled(not running) self.stop_button.setEnabled(running) def clear_log(self): """Löscht den Log-Bereich.""" self.log_text.clear() def add_log(self, message: str): """Fügt eine Nachricht zum Log-Bereich hinzu.""" self.log_text.append(message) # Scrolle nach unten # Korrigierter Code für die Qt-Version try: self.log_text.moveCursor(Qt.MoveOperation.MoveEnd) except AttributeError: # Fallback für ältere Qt-Versionen try: self.log_text.moveCursor(Qt.MoveEnd) except AttributeError: # Weitere Fallbacks try: from PyQt5.QtGui import QTextCursor self.log_text.moveCursor(QTextCursor.End) except: pass # Im Notfall einfach ignorieren def set_progress(self, value: int): """Setzt den Fortschritt der Fortschrittsanzeige.""" self.progress_bar.setValue(value) def set_status(self, message: str): """Setzt die Statusnachricht.""" # Diese Methode könnte später um eine Statusleiste erweitert werden self.add_log(message) def show_error(self, message: str): """Zeigt eine Fehlermeldung an.""" title = "Fehler" if self.language_manager: title = self.language_manager.get_text( "generator_tab.error_title", "Fehler" ) QMessageBox.critical(self, title, message) def update_texts(self): """Aktualisiert UI-Texte gemäß der aktuellen Sprache.""" if not self.language_manager: return lm = self.language_manager self.form_group.setTitle(lm.get_text("generator_tab.form_title", "Account-Informationen")) self.first_name_label.setText(lm.get_text("generator_tab.first_name_label", "Vorname:")) self.first_name_input.setPlaceholderText(lm.get_text("generator_tab.first_name_placeholder", "z.B. Max")) self.last_name_label.setText(lm.get_text("generator_tab.last_name_label", "Nachname:")) self.last_name_input.setPlaceholderText(lm.get_text("generator_tab.last_name_placeholder", "z.B. Mustermann")) self.age_label.setText(lm.get_text("generator_tab.age_label", "Alter:")) self.age_input.setPlaceholderText(lm.get_text("generator_tab.age_placeholder", "Alter zwischen 13 und 99")) self.reg_method_label.setText(lm.get_text("generator_tab.registration_method_label", "Registrierungsmethode:")) self.email_radio.setText(lm.get_text("generator_tab.email_radio", "E-Mail")) self.phone_radio.setText(lm.get_text("generator_tab.phone_radio", "Telefon")) self.phone_label.setText(lm.get_text("generator_tab.phone_label", "Telefonnummer:")) self.phone_input.setPlaceholderText(lm.get_text("generator_tab.phone_placeholder", "z.B. +49123456789")) self.email_domain_label.setText(lm.get_text("generator_tab.email_domain_label", "E-Mail-Domain:")) self.use_proxy_check.setText(lm.get_text("generator_tab.proxy_use", "Proxy verwenden")) self.proxy_type_label.setText(lm.get_text("generator_tab.proxy_type_label", "Typ:")) self.proxy_type_combo.clear() self.proxy_type_combo.addItems([ lm.get_text("generator_tab.proxy_type_ipv4", "IPv4"), lm.get_text("generator_tab.proxy_type_ipv6", "IPv6"), lm.get_text("generator_tab.proxy_type_mobile", "Mobile"), ]) self.proxy_label.setText(lm.get_text("generator_tab.proxy_label", "Proxy:")) self.headless_check.setText(lm.get_text("generator_tab.headless", "Browser im Hintergrund ausführen")) self.debug_check.setText(lm.get_text("generator_tab.debug", "Debug-Modus (detaillierte Protokollierung)")) platform = self.platform_name.lower() if platform == "tiktok" and hasattr(self, "category_combo"): self.category_label.setText( lm.get_text("generator_tab.tiktok_category_label", "Kategorie/Nische:") ) categories = [ lm.get_text("generator_tab.tiktok_category_general", "Allgemein"), lm.get_text("generator_tab.tiktok_category_gaming", "Gaming"), lm.get_text("generator_tab.tiktok_category_fashion", "Mode"), lm.get_text("generator_tab.tiktok_category_fitness", "Fitness"), lm.get_text("generator_tab.tiktok_category_travel", "Reisen"), lm.get_text("generator_tab.tiktok_category_cooking", "Kochen"), lm.get_text("generator_tab.tiktok_category_technology", "Technologie"), lm.get_text("generator_tab.tiktok_category_education", "Bildung"), ] current = self.category_combo.currentText() self.category_combo.clear() self.category_combo.addItems(categories) if current in categories: self.category_combo.setCurrentIndex(categories.index(current)) self.log_group.setTitle(lm.get_text("generator_tab.log_title", "Log")) self.start_button.setText(lm.get_text("buttons.create", "Account erstellen")) self.stop_button.setText(lm.get_text("buttons.cancel", "Abbrechen"))