# social_networks/tiktok/tiktok_registration.py """ TikTok-Registrierung - Klasse für die Kontoerstellung bei TikTok """ import logging import time import random import re from typing import Dict, List, Any, Optional, Tuple from .tiktok_selectors import TikTokSelectors from .tiktok_workflow import TikTokWorkflow # Konfiguriere Logger logger = logging.getLogger("tiktok_registration") class TikTokRegistration: """ Klasse für die Registrierung von TikTok-Konten. Enthält alle Methoden zur Kontoerstellung. """ def __init__(self, automation): """ Initialisiert die TikTok-Registrierung. Args: automation: Referenz auf die Hauptautomatisierungsklasse """ self.automation = automation self.browser = None # Wird zur Laufzeit auf automation.browser gesetzt self.selectors = TikTokSelectors() self.workflow = TikTokWorkflow.get_registration_workflow() logger.debug("TikTok-Registrierung initialisiert") def register_account(self, full_name: str, age: int, registration_method: str = "email", phone_number: str = None, **kwargs) -> Dict[str, Any]: """ Führt den vollständigen Registrierungsprozess für einen TikTok-Account durch. Args: full_name: Vollständiger Name für den Account age: Alter des Benutzers registration_method: "email" oder "phone" phone_number: Telefonnummer (nur bei registration_method="phone") **kwargs: Weitere optionale Parameter Returns: Dict[str, Any]: Ergebnis der Registrierung mit Status und Account-Daten """ # Hole Browser-Referenz von der Hauptklasse self.browser = self.automation.browser # Validiere die Eingaben if not self._validate_registration_inputs(full_name, age, registration_method, phone_number): return { "success": False, "error": "Ungültige Eingabeparameter", "stage": "input_validation" } # Account-Daten generieren account_data = self._generate_account_data(full_name, age, registration_method, phone_number, **kwargs) # Starte den Registrierungsprozess logger.info(f"Starte TikTok-Registrierung für {account_data['username']} via {registration_method}") try: # 1. Zur Startseite navigieren if not self._navigate_to_homepage(): return { "success": False, "error": "Konnte nicht zur TikTok-Startseite navigieren", "stage": "navigation", "account_data": account_data } # 2. Cookie-Banner behandeln self._handle_cookie_banner() # 3. Anmelden-Button klicken if not self._click_login_button(): return { "success": False, "error": "Konnte nicht auf Anmelden-Button klicken", "stage": "login_button", "account_data": account_data } # 4. Registrieren-Link klicken if not self._click_register_link(): return { "success": False, "error": "Konnte nicht auf Registrieren-Link klicken", "stage": "register_link", "account_data": account_data } # 5. Telefon/E-Mail-Option auswählen if not self._click_phone_email_option(): return { "success": False, "error": "Konnte nicht auf Telefon/E-Mail-Option klicken", "stage": "phone_email_option", "account_data": account_data } # 6. E-Mail oder Telefon als Registrierungsmethode wählen if not self._select_registration_method(registration_method): return { "success": False, "error": f"Konnte Registrierungsmethode '{registration_method}' nicht auswählen", "stage": "registration_method", "account_data": account_data } # 7. Geburtsdatum eingeben if not self._enter_birthday(account_data["birthday"]): return { "success": False, "error": "Fehler beim Eingeben des Geburtsdatums", "stage": "birthday", "account_data": account_data } # 8. Registrierungsformular ausfüllen if not self._fill_registration_form(account_data, registration_method): return { "success": False, "error": "Fehler beim Ausfüllen des Registrierungsformulars", "stage": "registration_form", "account_data": account_data } # 9. Bestätigungscode abrufen und eingeben if not self._handle_verification(account_data, registration_method): return { "success": False, "error": "Fehler bei der Verifizierung", "stage": "verification", "account_data": account_data } # 10. Benutzernamen erstellen if not self._create_username(account_data): return { "success": False, "error": "Fehler beim Erstellen des Benutzernamens", "stage": "username", "account_data": account_data } # 11. Erfolgreiche Registrierung überprüfen if not self._check_registration_success(): return { "success": False, "error": "Registrierung fehlgeschlagen oder konnte nicht verifiziert werden", "stage": "final_check", "account_data": account_data } # Registrierung erfolgreich abgeschlossen logger.info(f"TikTok-Account {account_data['username']} erfolgreich erstellt") return { "success": True, "stage": "completed", "account_data": account_data } except Exception as e: error_msg = f"Unerwarteter Fehler bei der TikTok-Registrierung: {str(e)}" logger.error(error_msg, exc_info=True) return { "success": False, "error": error_msg, "stage": "exception", "account_data": account_data } def _validate_registration_inputs(self, full_name: str, age: int, registration_method: str, phone_number: str) -> bool: """ Validiert die Eingaben für die Registrierung. Args: full_name: Vollständiger Name für den Account age: Alter des Benutzers registration_method: "email" oder "phone" phone_number: Telefonnummer (nur bei registration_method="phone") Returns: bool: True wenn alle Eingaben gültig sind, False sonst """ # Vollständiger Name prüfen if not full_name or len(full_name) < 3: logger.error("Ungültiger vollständiger Name") return False # Alter prüfen if age < 13: logger.error("Benutzer muss mindestens 13 Jahre alt sein") return False # Registrierungsmethode prüfen if registration_method not in ["email", "phone"]: logger.error(f"Ungültige Registrierungsmethode: {registration_method}") return False # Telefonnummer prüfen, falls erforderlich if registration_method == "phone" and not phone_number: logger.error("Telefonnummer erforderlich für Registrierung via Telefon") return False return True def _generate_account_data(self, full_name: str, age: int, registration_method: str, phone_number: str, **kwargs) -> Dict[str, Any]: """ Generiert Account-Daten für die Registrierung. Args: full_name: Vollständiger Name für den Account age: Alter des Benutzers registration_method: "email" oder "phone" phone_number: Telefonnummer (nur bei registration_method="phone") **kwargs: Weitere optionale Parameter Returns: Dict[str, Any]: Generierte Account-Daten """ # Benutzername generieren username = kwargs.get("username") if not username: username = self.automation.username_generator.generate_username("tiktok", full_name) # Passwort generieren password = kwargs.get("password") if not password: password = self.automation.password_generator.generate_password("tiktok") # E-Mail generieren (falls nötig) email = None if registration_method == "email": email_prefix = username.lower().replace(".", "").replace("_", "") email = f"{email_prefix}@{self.automation.email_domain}" # Geburtsdatum generieren birthday = self.automation.birthday_generator.generate_birthday_components("tiktok", age) # Account-Daten zusammenstellen account_data = { "username": username, "password": password, "full_name": full_name, "email": email, "phone": phone_number, "birthday": birthday, "age": age, "registration_method": registration_method } logger.debug(f"Account-Daten generiert: {account_data['username']}") return account_data def _navigate_to_homepage(self) -> bool: """ Navigiert zur TikTok-Startseite. Returns: bool: True bei Erfolg, False bei Fehler """ try: # Zur Startseite navigieren self.browser.navigate_to(TikTokSelectors.BASE_URL) # Warten, bis die Seite geladen ist self.automation.human_behavior.wait_for_page_load() # Screenshot erstellen self.automation._take_screenshot("tiktok_homepage") # Prüfen, ob die Seite korrekt geladen wurde if not self.browser.is_element_visible(TikTokSelectors.LOGIN_BUTTON, timeout=5000): logger.warning("TikTok-Startseite nicht korrekt geladen") return False logger.info("Erfolgreich zur TikTok-Startseite navigiert") return True except Exception as e: logger.error(f"Fehler beim Navigieren zur TikTok-Startseite: {e}") return False def _handle_cookie_banner(self) -> bool: """ Behandelt den Cookie-Banner, falls angezeigt. Returns: bool: True wenn Banner behandelt wurde oder nicht existiert, False bei Fehler """ # Cookie-Dialog-Erkennung if self.browser.is_element_visible(TikTokSelectors.COOKIE_DIALOG, timeout=2000): logger.info("Cookie-Banner erkannt") # Ablehnen-Button suchen und klicken reject_success = self.automation.ui_helper.click_button_fuzzy( TikTokSelectors.get_button_texts("reject_cookies"), TikTokSelectors.COOKIE_REJECT_BUTTON ) if reject_success: logger.info("Cookie-Banner erfolgreich abgelehnt") self.automation.human_behavior.random_delay(0.5, 1.5) return True else: logger.warning("Konnte Cookie-Banner nicht ablehnen, versuche zu akzeptieren") # Akzeptieren-Button als Fallback accept_success = self.browser.click_element(TikTokSelectors.COOKIE_ACCEPT_BUTTON) if accept_success: logger.info("Cookie-Banner erfolgreich akzeptiert") self.automation.human_behavior.random_delay(0.5, 1.5) return True else: logger.error("Konnte Cookie-Banner weder ablehnen noch akzeptieren") return False else: logger.debug("Kein Cookie-Banner erkannt") return True def _click_login_button(self) -> bool: """ Klickt auf den Anmelden-Button auf der Startseite. Returns: bool: True bei Erfolg, False bei Fehler """ try: # Versuche zuerst den Hauptbutton if self.browser.is_element_visible(TikTokSelectors.LOGIN_BUTTON, timeout=2000): result = self.browser.click_element(TikTokSelectors.LOGIN_BUTTON) if result: logger.info("Anmelden-Button erfolgreich geklickt") self.automation.human_behavior.random_delay(0.5, 1.5) return True # Versuche alternativ den Button in der oberen rechten Ecke if self.browser.is_element_visible(TikTokSelectors.LOGIN_BUTTON_TOP_RIGHT, timeout=2000): result = self.browser.click_element(TikTokSelectors.LOGIN_BUTTON_TOP_RIGHT) if result: logger.info("Anmelden-Button (oben rechts) erfolgreich geklickt") self.automation.human_behavior.random_delay(0.5, 1.5) return True # Versuche es mit Fuzzy-Button-Matching result = self.automation.ui_helper.click_button_fuzzy( ["Anmelden", "Log in", "Login"], TikTokSelectors.LOGIN_BUTTON_FALLBACK ) if result: logger.info("Anmelden-Button über Fuzzy-Matching erfolgreich geklickt") self.automation.human_behavior.random_delay(0.5, 1.5) return True logger.error("Konnte keinen Anmelden-Button finden") return False except Exception as e: logger.error(f"Fehler beim Klicken auf den Anmelden-Button: {e}") return False def _click_register_link(self) -> bool: """ Klickt auf den Registrieren-Link im Login-Dialog. Returns: bool: True bei Erfolg, False bei Fehler """ try: # Warten, bis der Login-Dialog angezeigt wird self.automation.human_behavior.random_delay(1.0, 2.0) # Prüfen, ob wir bereits im Registrierungsdialog sind if self.browser.is_element_visible(TikTokSelectors.REGISTER_DIALOG_TITLE, timeout=2000): logger.info("Bereits im Registrierungsdialog") return True # Versuche, den Registrieren-Link zu finden und zu klicken if self.browser.is_element_visible(TikTokSelectors.REGISTER_LINK, timeout=2000): result = self.browser.click_element(TikTokSelectors.REGISTER_LINK) if result: logger.info("Registrieren-Link erfolgreich geklickt") self.automation.human_behavior.random_delay(0.5, 1.5) return True # Versuche es mit Fuzzy-Button-Matching result = self.automation.ui_helper.click_button_fuzzy( ["Registrieren", "Sign up", "Konto erstellen", "Register"], TikTokSelectors.REGISTER_LINK_FALLBACK ) if result: logger.info("Registrieren-Link über Fuzzy-Matching erfolgreich geklickt") self.automation.human_behavior.random_delay(0.5, 1.5) return True # Prüfe, ob der Text "Du hast noch kein Konto? Registrieren" vorhanden ist register_link_text = "Du hast noch kein Konto? Registrieren" elements = self.browser.page.query_selector_all("*") for element in elements: if register_link_text in element.inner_text(): # Finde das "Registrieren"-Wort und klicke darauf matches = re.search(r"(.*?)(Registrieren)$", element.inner_text()) if matches: # Versuche, nur auf das Wort "Registrieren" zu klicken element.click() logger.info("Auf 'Registrieren' Text geklickt") self.automation.human_behavior.random_delay(0.5, 1.5) return True logger.error("Konnte keinen Registrieren-Link finden") return False except Exception as e: logger.error(f"Fehler beim Klicken auf den Registrieren-Link: {e}") return False def _click_phone_email_option(self) -> bool: """ Klickt auf die Telefon/E-Mail-Option im Registrierungsdialog. Returns: bool: True bei Erfolg, False bei Fehler """ try: # Warten, bis der Registrierungsdialog angezeigt wird self.automation.human_behavior.random_delay(1.0, 2.0) # Prüfen, ob wir bereits die Optionen für Telefon/E-Mail sehen if self.browser.is_element_visible(TikTokSelectors.EMAIL_FIELD, timeout=2000) or \ self.browser.is_element_visible(TikTokSelectors.PHONE_FIELD, timeout=2000): logger.info("Bereits auf der Telefon/E-Mail-Registrierungsseite") return True # Versuche, die Telefon/E-Mail-Option zu finden und zu klicken if self.browser.is_element_visible(TikTokSelectors.PHONE_EMAIL_OPTION, timeout=2000): result = self.browser.click_element(TikTokSelectors.PHONE_EMAIL_OPTION) if result: logger.info("Telefon/E-Mail-Option erfolgreich geklickt") self.automation.human_behavior.random_delay(0.5, 1.5) return True # Versuche es mit Fuzzy-Button-Matching result = self.automation.ui_helper.click_button_fuzzy( ["Telefonnummer oder E-Mail-Adresse nutzen", "Use phone or email", "Phone or email"], TikTokSelectors.PHONE_EMAIL_OPTION_FALLBACK ) if result: logger.info("Telefon/E-Mail-Option über Fuzzy-Matching erfolgreich geklickt") self.automation.human_behavior.random_delay(0.5, 1.5) return True logger.error("Konnte keine Telefon/E-Mail-Option finden") return False except Exception as e: logger.error(f"Fehler beim Klicken auf die Telefon/E-Mail-Option: {e}") return False def _select_registration_method(self, registration_method: str) -> bool: """ Wählt die Registrierungsmethode (E-Mail oder Telefon). Args: registration_method: "email" oder "phone" Returns: bool: True bei Erfolg, False bei Fehler """ try: # Warten, bis die Registrierungsmethoden-Seite geladen ist self.automation.human_behavior.random_delay(1.0, 2.0) if registration_method == "email": # Wenn bereits das E-Mail-Feld sichtbar ist, sind wir schon auf der richtigen Seite if self.browser.is_element_visible(TikTokSelectors.EMAIL_FIELD, timeout=1000): logger.info("Bereits auf der E-Mail-Registrierungsseite") return True # Suche nach dem "Mit E-Mail-Adresse registrieren" Link if self.browser.is_element_visible(TikTokSelectors.EMAIL_OPTION, timeout=2000): result = self.browser.click_element(TikTokSelectors.EMAIL_OPTION) if result: logger.info("E-Mail-Registrierungsmethode erfolgreich ausgewählt") self.automation.human_behavior.random_delay(0.5, 1.5) return True # Versuche es mit Fuzzy-Button-Matching result = self.automation.ui_helper.click_button_fuzzy( ["Mit E-Mail-Adresse registrieren", "Register with email", "E-Mail-Adresse"], TikTokSelectors.EMAIL_OPTION_FALLBACK ) if result: logger.info("E-Mail-Option über Fuzzy-Matching erfolgreich geklickt") self.automation.human_behavior.random_delay(0.5, 1.5) return True elif registration_method == "phone": # Wenn bereits das Telefon-Feld sichtbar ist, sind wir schon auf der richtigen Seite if self.browser.is_element_visible(TikTokSelectors.PHONE_FIELD, timeout=1000): logger.info("Bereits auf der Telefon-Registrierungsseite") return True # Suche nach dem "Mit Telefonnummer registrieren" Link if self.browser.is_element_visible(TikTokSelectors.PHONE_OPTION, timeout=2000): result = self.browser.click_element(TikTokSelectors.PHONE_OPTION) if result: logger.info("Telefon-Registrierungsmethode erfolgreich ausgewählt") self.automation.human_behavior.random_delay(0.5, 1.5) return True # Versuche es mit Fuzzy-Button-Matching result = self.automation.ui_helper.click_button_fuzzy( ["Mit Telefonnummer registrieren", "Register with phone", "Telefonnummer"], TikTokSelectors.PHONE_OPTION_FALLBACK ) if result: logger.info("Telefon-Option über Fuzzy-Matching erfolgreich geklickt") self.automation.human_behavior.random_delay(0.5, 1.5) return True logger.error(f"Konnte Registrierungsmethode '{registration_method}' nicht auswählen") return False except Exception as e: logger.error(f"Fehler beim Auswählen der Registrierungsmethode: {e}") return False def _enter_birthday(self, birthday: Dict[str, int]) -> bool: """ Gibt das Geburtsdatum ein. Args: birthday: Dictionary mit 'year', 'month', 'day' Schlüsseln Returns: bool: True bei Erfolg, False bei Fehler """ try: # Warten, bis die Geburtstagsauswahl angezeigt wird self.automation.human_behavior.random_delay(1.0, 2.0) # Monat auswählen month_dropdown = self.browser.wait_for_selector(TikTokSelectors.BIRTHDAY_MONTH_DROPDOWN, timeout=5000) if not month_dropdown: logger.error("Monat-Dropdown nicht gefunden") return False month_dropdown.click() self.automation.human_behavior.random_delay(0.3, 0.8) # Monat-Option auswählen month_option = self.browser.wait_for_selector( TikTokSelectors.get_month_option_selector(birthday["month"]), timeout=3000 ) if month_option: month_option.click() logger.info(f"Monat {birthday['month']} ausgewählt") else: # Fallback: Monat über Select-Funktion auswählen month_success = self.browser.select_option( TikTokSelectors.BIRTHDAY_MONTH_DROPDOWN, str(birthday["month"]) ) if not month_success: logger.error(f"Konnte Monat {birthday['month']} nicht auswählen") return False self.automation.human_behavior.random_delay(0.3, 0.8) # Tag auswählen day_dropdown = self.browser.wait_for_selector(TikTokSelectors.BIRTHDAY_DAY_DROPDOWN, timeout=3000) if not day_dropdown: logger.error("Tag-Dropdown nicht gefunden") return False day_dropdown.click() self.automation.human_behavior.random_delay(0.3, 0.8) # Tag-Option auswählen day_option = self.browser.wait_for_selector( TikTokSelectors.get_day_option_selector(birthday["day"]), timeout=3000 ) if day_option: day_option.click() logger.info(f"Tag {birthday['day']} ausgewählt") else: # Fallback: Tag über Select-Funktion auswählen day_success = self.browser.select_option( TikTokSelectors.BIRTHDAY_DAY_DROPDOWN, str(birthday["day"]) ) if not day_success: logger.error(f"Konnte Tag {birthday['day']} nicht auswählen") return False self.automation.human_behavior.random_delay(0.3, 0.8) # Jahr auswählen year_dropdown = self.browser.wait_for_selector(TikTokSelectors.BIRTHDAY_YEAR_DROPDOWN, timeout=3000) if not year_dropdown: logger.error("Jahr-Dropdown nicht gefunden") return False year_dropdown.click() self.automation.human_behavior.random_delay(0.3, 0.8) # Jahr-Option auswählen year_option = self.browser.wait_for_selector( TikTokSelectors.get_year_option_selector(birthday["year"]), timeout=3000 ) if year_option: year_option.click() logger.info(f"Jahr {birthday['year']} ausgewählt") else: # Fallback: Jahr über Select-Funktion auswählen year_success = self.browser.select_option( TikTokSelectors.BIRTHDAY_YEAR_DROPDOWN, str(birthday["year"]) ) if not year_success: logger.error(f"Konnte Jahr {birthday['year']} nicht auswählen") return False logger.info(f"Geburtsdatum {birthday['month']}/{birthday['day']}/{birthday['year']} erfolgreich eingegeben") return True except Exception as e: logger.error(f"Fehler beim Eingeben des Geburtsdatums: {e}") return False def _fill_registration_form(self, account_data: Dict[str, Any], registration_method: str) -> bool: """ Füllt das Registrierungsformular aus. Args: account_data: Account-Daten für die Registrierung registration_method: "email" oder "phone" Returns: bool: True bei Erfolg, False bei Fehler """ try: # Je nach Registrierungsmethode das entsprechende Feld ausfüllen if registration_method == "email": # E-Mail-Feld ausfüllen email_success = self.automation.ui_helper.fill_field_fuzzy( ["E-Mail-Adresse", "Email", "E-Mail"], account_data["email"], TikTokSelectors.EMAIL_FIELD ) if not email_success: logger.error("Konnte E-Mail-Feld nicht ausfüllen") return False logger.info(f"E-Mail-Feld ausgefüllt: {account_data['email']}") elif registration_method == "phone": # Telefonnummer-Feld ausfüllen (ohne Ländervorwahl) phone_number = account_data["phone"] if phone_number.startswith("+"): # Entferne Ländervorwahl, wenn vorhanden parts = phone_number.split(" ", 1) if len(parts) > 1: phone_number = parts[1] phone_success = self.automation.ui_helper.fill_field_fuzzy( ["Telefonnummer", "Phone number", "Phone"], phone_number, TikTokSelectors.PHONE_FIELD ) if not phone_success: logger.error("Konnte Telefonnummer-Feld nicht ausfüllen") return False logger.info(f"Telefonnummer-Feld ausgefüllt: {phone_number}") self.automation.human_behavior.random_delay(0.5, 1.5) # Bei E-Mail-Registrierung auch das Passwort-Feld ausfüllen if registration_method == "email": password_success = self.automation.ui_helper.fill_field_fuzzy( ["Passwort", "Password"], account_data["password"], TikTokSelectors.PASSWORD_FIELD ) if not password_success: logger.error("Konnte Passwort-Feld nicht ausfüllen") return False logger.info("Passwort-Feld ausgefüllt") self.automation.human_behavior.random_delay(0.5, 1.5) # Code senden Button klicken send_code_success = self.automation.ui_helper.click_button_fuzzy( ["Code senden", "Send code", "Send verification code"], TikTokSelectors.SEND_CODE_BUTTON ) if not send_code_success: logger.error("Konnte 'Code senden'-Button nicht klicken") return False logger.info("'Code senden'-Button erfolgreich geklickt") return True except Exception as e: logger.error(f"Fehler beim Ausfüllen des Registrierungsformulars: {e}") return False def _handle_verification(self, account_data: Dict[str, Any], registration_method: str) -> bool: """ Behandelt den Verifizierungsprozess (E-Mail/SMS). Args: account_data: Account-Daten mit E-Mail/Telefon registration_method: "email" oder "phone" Returns: bool: True bei Erfolg, False bei Fehler """ try: # Warten, bis der Bestätigungscode gesendet wurde self.automation.human_behavior.wait_for_page_load() self.automation.human_behavior.random_delay(2.0, 4.0) # Verifizierungscode je nach Methode abrufen if registration_method == "email": # Verifizierungscode von E-Mail abrufen verification_code = self._get_email_confirmation_code(account_data["email"]) else: # Verifizierungscode von SMS abrufen verification_code = self._get_sms_confirmation_code(account_data["phone"]) if not verification_code: logger.error("Konnte keinen Verifizierungscode abrufen") return False logger.info(f"Verifizierungscode erhalten: {verification_code}") # Verifizierungscode-Feld ausfüllen code_success = self.automation.ui_helper.fill_field_fuzzy( ["Gib den sechsstelligen Code ein", "Enter verification code", "Verification code"], verification_code, TikTokSelectors.VERIFICATION_CODE_FIELD ) if not code_success: logger.error("Konnte Verifizierungscode-Feld nicht ausfüllen") return False self.automation.human_behavior.random_delay(1.0, 2.0) # Weiter-Button klicken continue_success = self.automation.ui_helper.click_button_fuzzy( ["Weiter", "Continue", "Next", "Submit"], TikTokSelectors.CONTINUE_BUTTON ) if not continue_success: logger.error("Konnte 'Weiter'-Button nicht klicken") return False logger.info("Verifizierungscode eingegeben und 'Weiter' geklickt") # Warten nach der Verifizierung self.automation.human_behavior.wait_for_page_load() self.automation.human_behavior.random_delay(1.0, 2.0) return True except Exception as e: logger.error(f"Fehler bei der Verifizierung: {e}") return False def _get_email_confirmation_code(self, email: str) -> Optional[str]: """ Ruft den Bestätigungscode von einer E-Mail ab. Args: email: E-Mail-Adresse, an die der Code gesendet wurde Returns: Optional[str]: Der Bestätigungscode oder None, wenn nicht gefunden """ try: # Warte auf die E-Mail verification_code = self.automation.email_handler.get_verification_code( email_domain=self.automation.email_domain, platform="tiktok", timeout=120 # Warte bis zu 2 Minuten auf den Code ) if verification_code: return verification_code # Wenn kein Code gefunden wurde, prüfen, ob der Code vielleicht direkt angezeigt wird verification_code = self._extract_code_from_page() if verification_code: logger.info(f"Verifizierungscode direkt von der Seite extrahiert: {verification_code}") return verification_code logger.warning(f"Konnte keinen Verifizierungscode für {email} finden") return None except Exception as e: logger.error(f"Fehler beim Abrufen des E-Mail-Bestätigungscodes: {e}") return None def _get_sms_confirmation_code(self, phone: str) -> Optional[str]: """ Ruft den Bestätigungscode aus einer SMS ab. Hier müsste ein SMS-Empfangs-Service eingebunden werden. Args: phone: Telefonnummer, an die der Code gesendet wurde Returns: Optional[str]: Der Bestätigungscode oder None, wenn nicht gefunden """ # Diese Implementierung ist ein Platzhalter # In einer echten Implementierung würde hier ein SMS-Empfangs-Service verwendet logger.warning("SMS-Verifizierung ist noch nicht implementiert") # Versuche, den Code trotzdem zu extrahieren, falls er auf der Seite angezeigt wird return self._extract_code_from_page() def _extract_code_from_page(self) -> Optional[str]: """ Versucht, einen Bestätigungscode direkt von der Seite zu extrahieren. Returns: Optional[str]: Der extrahierte Code oder None, wenn nicht gefunden """ try: # Gesamten Seiteninhalt abrufen page_content = self.browser.page.content() # Mögliche Regex-Muster für Bestätigungscodes patterns = [ r"Dein Code ist (\d{6})", r"Your code is (\d{6})", r"Bestätigungscode: (\d{6})", r"Confirmation code: (\d{6})", r"(\d{6}) ist dein TikTok-Code", r"(\d{6}) is your TikTok code" ] for pattern in patterns: match = re.search(pattern, page_content) if match: return match.group(1) return None except Exception as e: logger.error(f"Fehler beim Extrahieren des Codes von der Seite: {e}") return None def _create_username(self, account_data: Dict[str, Any]) -> bool: """ Erstellt einen Benutzernamen. Args: account_data: Account-Daten Returns: bool: True bei Erfolg, False bei Fehler """ try: # Warten, bis die Benutzernamen-Seite geladen ist self.automation.human_behavior.wait_for_page_load() # Prüfen, ob wir auf der Benutzernamen-Seite sind if not self.browser.is_element_visible(TikTokSelectors.USERNAME_FIELD, timeout=5000): logger.warning("Benutzernamen-Feld nicht gefunden, möglicherweise ist dieser Schritt übersprungen worden") # Versuche, den "Überspringen"-Button zu klicken, falls vorhanden skip_visible = self.browser.is_element_visible(TikTokSelectors.SKIP_USERNAME_BUTTON, timeout=2000) if skip_visible: self.browser.click_element(TikTokSelectors.SKIP_USERNAME_BUTTON) logger.info("Benutzernamen-Schritt übersprungen") return True # Möglicherweise wurde der Benutzername automatisch erstellt logger.info("Benutzernamen-Schritt möglicherweise automatisch abgeschlossen") return True # Benutzernamen eingeben username_success = self.automation.ui_helper.fill_field_fuzzy( ["Benutzername", "Username"], account_data["username"], TikTokSelectors.USERNAME_FIELD ) if not username_success: logger.error("Konnte Benutzernamen-Feld nicht ausfüllen") return False logger.info(f"Benutzernamen-Feld ausgefüllt: {account_data['username']}") self.automation.human_behavior.random_delay(1.0, 2.0) # Registrieren-Button klicken register_success = self.automation.ui_helper.click_button_fuzzy( ["Registrieren", "Register", "Sign up", "Submit"], TikTokSelectors.REGISTER_BUTTON ) if not register_success: logger.error("Konnte 'Registrieren'-Button nicht klicken") return False logger.info("'Registrieren'-Button erfolgreich geklickt") # Warten nach der Registrierung self.automation.human_behavior.wait_for_page_load() return True except Exception as e: logger.error(f"Fehler beim Erstellen des Benutzernamens: {e}") return False def _check_registration_success(self) -> bool: """ Überprüft, ob die Registrierung erfolgreich war. Returns: bool: True wenn erfolgreich, False sonst """ try: # Warten nach der Registrierung self.automation.human_behavior.wait_for_page_load(multiplier=2.0) # Screenshot erstellen self.automation._take_screenshot("registration_final") # Erfolg anhand verschiedener Indikatoren prüfen success_indicators = TikTokSelectors.SUCCESS_INDICATORS for indicator in success_indicators: if self.browser.is_element_visible(indicator, timeout=3000): logger.info(f"Erfolgsindikator gefunden: {indicator}") return True # Alternativ prüfen, ob wir auf der TikTok-Startseite sind current_url = self.browser.page.url if "tiktok.com" in current_url and "/signup" not in current_url and "/login" not in current_url: logger.info(f"Erfolg basierend auf URL: {current_url}") return True logger.warning("Keine Erfolgsindikatoren gefunden") return False except Exception as e: logger.error(f"Fehler beim Überprüfen des Registrierungserfolgs: {e}") return False