# social_networks/facebook/facebook_registration.py """ Facebook-Registrierung - Klasse für die Registrierungsfunktionalität bei Facebook """ import logging import time import re from typing import Dict, List, Any, Optional, Tuple from .facebook_selectors import FacebookSelectors from .facebook_workflow import FacebookWorkflow from utils.logger import setup_logger # Konfiguriere Logger logger = setup_logger("facebook_registration") class FacebookRegistration: """ Klasse für die Registrierung neuer Facebook-Konten. Enthält alle Methoden für den Registrierungsprozess. """ def __init__(self, automation): """ Initialisiert die Facebook-Registrierungs-Funktionalität. Args: automation: Referenz auf die Hauptautomatisierungsklasse """ self.automation = automation self.selectors = FacebookSelectors() self.workflow = FacebookWorkflow.get_registration_workflow() logger.debug("Facebook-Registrierung initialisiert") def register_account(self, account_data: Dict[str, Any]) -> Dict[str, Any]: """ Führt den Registrierungsprozess für einen neuen Facebook-Account durch. Args: account_data: Dictionary mit Account-Daten Returns: Dict[str, Any]: Ergebnis der Registrierung """ logger.info(f"Starte Facebook-Registrierung für {account_data['first_name']} {account_data['last_name']}") try: # 1. Zur Facebook-Hauptseite navigieren self.automation._send_status_update("Öffne Facebook-Webseite") self.automation._send_log_update("Navigiere zu Facebook...") if not self._navigate_to_facebook(): return { "success": False, "error": "Konnte nicht zu Facebook navigieren", "stage": "navigation" } # 2. Cookie-Consent behandeln self.automation._send_status_update("Behandle Cookie-Einstellungen") self.automation._send_log_update("Lehne optionale Cookies ab...") if not self._handle_cookie_consent(): logger.warning("Cookie-Consent konnte nicht behandelt werden, fahre trotzdem fort") # 3. Registrierungsformular öffnen self.automation._send_status_update("Öffne Registrierungsformular") self.automation._send_log_update("Klicke auf 'Neues Konto erstellen'...") if not self._open_registration_form(): return { "success": False, "error": "Konnte Registrierungsformular nicht öffnen", "stage": "open_form" } # 4. Registrierungsformular ausfüllen self.automation._send_status_update("Fülle Registrierungsformular aus") self.automation._send_log_update("Gebe persönliche Daten ein...") if not self._fill_registration_form(account_data): return { "success": False, "error": "Fehler beim Ausfüllen des Registrierungsformulars", "stage": "fill_form" } # 5. Formular absenden self.automation._send_status_update("Sende Registrierung ab") self.automation._send_log_update("Klicke auf 'Registrieren'...") if not self._submit_registration(): return { "success": False, "error": "Fehler beim Absenden der Registrierung", "stage": "submit" } # 6. E-Mail-Verifikation behandeln needs_verification = self._check_needs_verification() if needs_verification: self.automation._send_status_update("E-Mail-Verifikation erforderlich") self.automation._send_log_update("Warte auf Verifikationscode...") # Warte auf Verifikationscode verification_code = self._wait_for_verification_code(account_data.get("email")) if verification_code: if not self._enter_verification_code(verification_code): return { "success": False, "error": "Fehler bei der E-Mail-Verifikation", "stage": "verification" } else: return { "success": False, "error": "Verifikationscode nicht erhalten", "stage": "verification_timeout" } # 7. Erfolgreiche Registrierung überprüfen if not self._check_registration_success(): return { "success": False, "error": "Registrierung fehlgeschlagen", "stage": "final_check" } # Registrierung erfolgreich logger.info(f"Facebook-Account erfolgreich erstellt") self.automation._send_status_update("Registrierung erfolgreich!") self.automation._send_log_update("Account wurde erfolgreich erstellt") # Account-Daten für Rückgabe vorbereiten account_data["platform"] = "facebook" account_data["created_at"] = time.time() return { "success": True, "stage": "completed", "account_data": account_data } except Exception as e: error_msg = f"Unerwarteter Fehler bei der Facebook-Registrierung: {str(e)}" logger.error(error_msg, exc_info=True) return { "success": False, "error": error_msg, "stage": "exception", "account_data": account_data } def _navigate_to_facebook(self) -> bool: """ Navigiert zur Facebook-Hauptseite. Returns: bool: True bei Erfolg """ try: logger.info(f"Navigiere zu {self.automation.base_url}") # Navigiere zur Facebook-Seite self.automation.browser.navigate_to(self.automation.base_url) # Warte auf Seitenladung self.automation.human_behavior.wait_for_page_load(multiplier=1.5) # Screenshot self.automation._take_screenshot("facebook_homepage") # Prüfe ob wir auf Facebook sind current_url = self.automation.browser.page.url if "facebook.com" in current_url: logger.info("Erfolgreich zu Facebook navigiert") return True else: logger.error(f"Nicht auf Facebook gelandet: {current_url}") return False except Exception as e: logger.error(f"Fehler bei Navigation zu Facebook: {e}") return False def _handle_cookie_consent(self) -> bool: """ Behandelt den Cookie-Consent-Dialog. Returns: bool: True wenn behandelt """ try: logger.info("Prüfe auf Cookie-Consent-Dialog") # Warte kurz auf möglichen Cookie-Dialog self.automation.human_behavior.random_delay(1.0, 2.0) # Versuche "Optionale Cookies ablehnen" zu klicken decline_clicked = False # Methode 1: Direkter Selektor if self.automation.browser.is_element_visible(self.selectors.COOKIE_DECLINE_BUTTON, timeout=2000): if self.automation.browser.click_element(self.selectors.COOKIE_DECLINE_BUTTON): logger.info("Cookie-Consent abgelehnt (Methode 1)") decline_clicked = True # Methode 2: Alternative Selektoren if not decline_clicked: for selector in [self.selectors.COOKIE_DECLINE_BUTTON_ALT, "button:has-text('Optionale Cookies ablehnen')", "//button[contains(., 'Optionale Cookies ablehnen')]"]: try: if self.automation.browser.click_element(selector, timeout=1000): logger.info(f"Cookie-Consent abgelehnt mit Selektor: {selector}") decline_clicked = True break except: continue # Methode 3: Fuzzy Button Click if not decline_clicked: if self.automation.ui_helper.click_button_fuzzy( self.selectors.get_button_texts("decline_cookies"), fallback_selector="button" ): logger.info("Cookie-Consent abgelehnt (Fuzzy Match)") decline_clicked = True if decline_clicked: # Warte auf Dialog-Schließung self.automation.human_behavior.random_delay(1.0, 2.0) self.automation._take_screenshot("after_cookie_consent") return True else: logger.debug("Kein Cookie-Consent-Dialog gefunden oder bereits behandelt") return False except Exception as e: logger.error(f"Fehler bei Cookie-Consent-Behandlung: {e}") return False def _open_registration_form(self) -> bool: """ Öffnet das Registrierungsformular. Returns: bool: True bei Erfolg """ try: logger.info("Öffne Registrierungsformular") # Versuche "Neues Konto erstellen" zu klicken button_clicked = False # Methode 1: data-testid Selektor if self.automation.browser.is_element_visible(self.selectors.CREATE_ACCOUNT_BUTTON, timeout=3000): if self.automation.browser.click_element(self.selectors.CREATE_ACCOUNT_BUTTON): logger.info("Registrierungsformular geöffnet (data-testid)") button_clicked = True # Methode 2: Alternative Selektoren if not button_clicked: for selector in [self.selectors.CREATE_ACCOUNT_BUTTON_ALT, "a:has-text('Neues Konto erstellen')", "a[href*='/r.php']"]: try: if self.automation.browser.click_element(selector, timeout=2000): logger.info(f"Registrierungsformular geöffnet mit: {selector}") button_clicked = True break except: continue # Methode 3: Fuzzy Button Click if not button_clicked: if self.automation.ui_helper.click_button_fuzzy( self.selectors.get_button_texts("create_account") ): logger.info("Registrierungsformular geöffnet (Fuzzy Match)") button_clicked = True if button_clicked: # Warte auf Formular-Ladung self.automation.human_behavior.wait_for_page_load() self.automation._take_screenshot("registration_form") # Prüfe ob wir auf der Registrierungsseite sind current_url = self.automation.browser.page.url if "/r.php" in current_url or "registration" in current_url: logger.info("Registrierungsformular erfolgreich geöffnet") return True logger.error("Konnte Registrierungsformular nicht öffnen") return False except Exception as e: logger.error(f"Fehler beim Öffnen des Registrierungsformulars: {e}") return False def _fill_registration_form(self, account_data: Dict[str, Any]) -> bool: """ Füllt das Registrierungsformular aus. Args: account_data: Account-Daten Returns: bool: True bei Erfolg """ try: logger.info("Fülle Registrierungsformular aus") # Vorname if not self.automation.ui_helper.type_text_human_like( self.selectors.REG_FIRSTNAME_FIELD, account_data["first_name"] ): logger.error("Fehler beim Eingeben des Vornamens") return False # Nachname if not self.automation.ui_helper.type_text_human_like( self.selectors.REG_LASTNAME_FIELD, account_data["last_name"] ): logger.error("Fehler beim Eingeben des Nachnamens") return False # Geburtsdatum birth_date = account_data["birth_date"] # Tag auswählen if not self.automation.browser.select_option( self.selectors.REG_BIRTHDAY_DAY, str(birth_date["day"]) ): logger.error("Fehler beim Auswählen des Geburtstags") return False # Monat auswählen if not self.automation.browser.select_option( self.selectors.REG_BIRTHDAY_MONTH, str(birth_date["month"]) ): logger.error("Fehler beim Auswählen des Geburtsmonats") return False # Jahr auswählen if not self.automation.browser.select_option( self.selectors.REG_BIRTHDAY_YEAR, str(birth_date["year"]) ): logger.error("Fehler beim Auswählen des Geburtsjahrs") return False self.automation.human_behavior.random_delay(0.5, 1.0) # Geschlecht auswählen gender_selector = self.selectors.get_gender_selector(account_data["gender"]) if not self.automation.browser.click_element(gender_selector): logger.error(f"Fehler beim Auswählen des Geschlechts: {account_data['gender']}") return False self.automation.human_behavior.random_delay(0.5, 1.0) # E-Mail oder Telefonnummer contact_field = account_data.get("email") or account_data.get("phone_number") if not contact_field: logger.error("Keine E-Mail oder Telefonnummer angegeben") return False if not self.automation.ui_helper.type_text_human_like( self.selectors.REG_EMAIL_OR_PHONE, contact_field ): logger.error("Fehler beim Eingeben der Kontaktdaten") return False # Warte auf mögliches E-Mail-Bestätigungsfeld self.automation.human_behavior.random_delay(1.0, 2.0) # Wenn E-Mail eingegeben wurde, könnte ein Bestätigungsfeld erscheinen if account_data.get("email"): if self.automation.browser.is_element_visible(self.selectors.REG_EMAIL_CONFIRM, timeout=2000): logger.info("E-Mail-Bestätigungsfeld erkannt") if not self.automation.ui_helper.type_text_human_like( self.selectors.REG_EMAIL_CONFIRM, account_data["email"] ): logger.warning("Fehler beim Bestätigen der E-Mail") # Passwort if not self.automation.ui_helper.type_text_human_like( self.selectors.REG_PASSWORD, account_data["password"] ): logger.error("Fehler beim Eingeben des Passworts") return False # Screenshot des ausgefüllten Formulars self.automation._take_screenshot("filled_registration_form") logger.info("Registrierungsformular erfolgreich ausgefüllt") return True except Exception as e: logger.error(f"Fehler beim Ausfüllen des Registrierungsformulars: {e}") return False def _submit_registration(self) -> bool: """ Sendet das Registrierungsformular ab. Returns: bool: True bei Erfolg """ try: logger.info("Sende Registrierungsformular ab") # Versuche Submit-Button zu klicken submit_clicked = False # Methode 1: Name-Attribut if self.automation.browser.is_element_visible(self.selectors.REG_SUBMIT_BUTTON, timeout=2000): if self.automation.browser.click_element(self.selectors.REG_SUBMIT_BUTTON): logger.info("Registrierung abgesendet (name-Attribut)") submit_clicked = True # Methode 2: Text-basiert if not submit_clicked: for text in self.selectors.get_button_texts("register"): selector = f"button:has-text('{text}')" try: if self.automation.browser.click_element(selector, timeout=1000): logger.info(f"Registrierung abgesendet mit: {selector}") submit_clicked = True break except: continue # Methode 3: Fuzzy Match if not submit_clicked: if self.automation.ui_helper.click_button_fuzzy( self.selectors.get_button_texts("register") ): logger.info("Registrierung abgesendet (Fuzzy Match)") submit_clicked = True if submit_clicked: # Warte auf Navigation self.automation.human_behavior.wait_for_page_load(multiplier=2.0) self.automation._take_screenshot("after_submit") return True else: logger.error("Konnte Registrierung nicht absenden") return False except Exception as e: logger.error(f"Fehler beim Absenden der Registrierung: {e}") return False def _check_needs_verification(self) -> bool: """ Prüft ob eine E-Mail-Verifikation erforderlich ist. Returns: bool: True wenn Verifikation erforderlich """ try: # Warte kurz self.automation.human_behavior.random_delay(2.0, 3.0) # Prüfe URL current_url = self.automation.browser.page.url if "confirmemail" in current_url or "confirm" in current_url: logger.info("E-Mail-Verifikation erforderlich (URL-Check)") return True # Prüfe auf Verifikations-Input if self.automation.browser.is_element_visible(self.selectors.VERIFICATION_CODE_INPUT, timeout=2000): logger.info("E-Mail-Verifikation erforderlich (Input-Field)") return True # Prüfe auf Verifikations-Text page_content = self.automation.browser.page.content().lower() verification_keywords = ["bestätigungscode", "verification code", "confirm email", "code eingeben"] for keyword in verification_keywords: if keyword in page_content: logger.info(f"E-Mail-Verifikation erforderlich (Keyword: {keyword})") return True logger.info("Keine E-Mail-Verifikation erforderlich") return False except Exception as e: logger.error(f"Fehler bei Verifikations-Check: {e}") return False def _wait_for_verification_code(self, email: str) -> Optional[str]: """ Wartet auf den Verifikationscode aus der E-Mail. Args: email: E-Mail-Adresse Returns: Optional[str]: Verifikationscode oder None """ logger.info(f"Warte auf Verifikationscode für {email}") # Delegiere an Verification-Klasse return self.automation.verification.wait_for_email_code(email, timeout=120) def _enter_verification_code(self, code: str) -> bool: """ Gibt den Verifikationscode ein. Args: code: Verifikationscode Returns: bool: True bei Erfolg """ try: logger.info(f"Gebe Verifikationscode ein: {code}") # Code eingeben if not self.automation.ui_helper.type_text_human_like( self.selectors.VERIFICATION_CODE_INPUT, code ): logger.error("Fehler beim Eingeben des Verifikationscodes") return False # Weiter-Button klicken continue_clicked = False # Versuche verschiedene Selektoren for text in self.selectors.get_button_texts("continue"): selector = f"button:has-text('{text}')" try: if self.automation.browser.click_element(selector, timeout=1000): logger.info(f"Verifikation fortgesetzt mit: {selector}") continue_clicked = True break except: continue # Oder Enter drücken if not continue_clicked: self.automation.browser.page.keyboard.press("Enter") logger.info("Verifikation mit Enter fortgesetzt") # Warte auf Navigation self.automation.human_behavior.wait_for_page_load() # Prüfe auf OK-Button (Popup nach erfolgreicher Verifikation) if self.automation.browser.is_element_visible(self.selectors.VERIFICATION_OK_BUTTON, timeout=3000): self.automation.browser.click_element(self.selectors.VERIFICATION_OK_BUTTON) logger.info("OK-Button nach Verifikation geklickt") return True except Exception as e: logger.error(f"Fehler beim Eingeben des Verifikationscodes: {e}") return False def _check_registration_success(self) -> bool: """ Überprüft ob die Registrierung erfolgreich war. Returns: bool: True bei Erfolg """ try: # Warte auf finale Navigation self.automation.human_behavior.wait_for_page_load(multiplier=2.0) # Screenshot self.automation._take_screenshot("registration_final") # Prüfe URL current_url = self.automation.browser.page.url logger.info(f"Finale URL: {current_url}") # Erfolgs-URLs success_patterns = [ "facebook.com/?", "facebook.com/home", "facebook.com/feed", "welcome", "onboarding" ] for pattern in success_patterns: if pattern in current_url: logger.info(f"Registrierung erfolgreich (URL-Pattern: {pattern})") return True # Prüfe auf Erfolgs-Indikatoren for indicator in self.selectors.SUCCESS_INDICATORS: if self.automation.browser.is_element_visible(indicator, timeout=2000): logger.info(f"Registrierung erfolgreich (Indikator: {indicator})") return True # Prüfe auf Fehler if self.automation.browser.is_element_visible(self.selectors.ERROR_MESSAGE, timeout=1000): error_text = self.automation.browser.get_text(self.selectors.ERROR_MESSAGE) logger.error(f"Registrierungsfehler: {error_text}") return False # Bei Unsicherheit als erfolgreich werten wenn keine Login-Form mehr da ist if not self.automation.browser.is_element_visible(self.selectors.REG_FIRSTNAME_FIELD, timeout=1000): logger.info("Registrierung wahrscheinlich erfolgreich (kein Formular mehr sichtbar)") return True logger.warning("Registrierungsstatus unklar") return False except Exception as e: logger.error(f"Fehler bei Erfolgs-Check: {e}") return False