""" Gmail Registrierung - Handhabt den Registrierungsprozess """ import logging import time import random from typing import Dict, Optional, Any from playwright.sync_api import Page from social_networks.gmail import gmail_selectors as selectors from social_networks.gmail.gmail_ui_helper import GmailUIHelper logger = logging.getLogger("gmail_registration") class GmailRegistration: """ Handhabt den Gmail/Google Account Registrierungsprozess """ def __init__(self, page: Page, ui_helper: GmailUIHelper, screenshots_dir: str = None, save_screenshots: bool = True, phone_service: Optional[Any] = None): """ Initialisiert die Registrierung """ self.page = page self.ui_helper = ui_helper self.screenshots_dir = screenshots_dir self.save_screenshots = save_screenshots self.phone_service = phone_service def _click_next_button(self) -> bool: """ Versucht den Weiter-Button mit verschiedenen Selektoren zu klicken """ logger.info("Versuche Weiter-Button zu klicken") # Liste von Selektoren zum Ausprobieren selectors_to_try = [ ("span[jsname='V67aGc']:has-text('Weiter')", "parent_click"), # Der exakte Span mit jsname ("button:has(span.VfPpkd-vQzf8d:has-text('Weiter'))", "click"), # Button der den Span enthält ("button:has(div.VfPpkd-RLmnJb)", "click"), # Button mit dem Material Ripple div (selectors.NEXT_BUTTON, "click"), (selectors.NEXT_BUTTON_MATERIAL, "parent_click"), (selectors.NEXT_BUTTON_SPAN, "click"), ("button:has-text('Weiter')", "click"), ("button:has-text('Next')", "click") ] for selector, method in selectors_to_try: try: if method == "click": if self.ui_helper.wait_for_element(selector, timeout=2000): self.ui_helper.click_with_retry(selector) logger.info(f"Erfolgreich geklickt mit Selektor: {selector}") return True elif method == "parent_click": if self.ui_helper.wait_for_element(selector, timeout=2000): # Versuche verschiedene Parent-Ebenen for parent_level in ['..', '../..', '../../..']: try: self.page.locator(selector).locator(parent_level).click() logger.info(f"Erfolgreich Parent geklickt mit Selektor: {selector} und Level: {parent_level}") return True except: continue except Exception as e: logger.debug(f"Konnte nicht mit Selektor {selector} klicken: {e}") continue # Letzter Versuch mit Playwright's get_by_role try: self.page.get_by_role("button", name="Weiter").click() logger.info("Erfolgreich mit get_by_role geklickt") return True except: pass logger.error("Konnte Weiter-Button nicht finden/klicken") return False def start_registration_flow(self, account_data: Dict[str, str]) -> Dict[str, any]: """ Startet den Registrierungsflow """ try: logger.info("Starte Gmail Registrierungsflow") # Schritt 1: Name eingeben name_result = self._fill_name_form(account_data) if not name_result["success"]: return name_result # Schritt 2: Geburtsdatum und Geschlecht birthday_result = self._fill_birthday_gender(account_data) if not birthday_result["success"]: return birthday_result # Schritt 3: Gmail-Adresse wählen/erstellen gmail_result = self._create_gmail_address(account_data) if not gmail_result["success"]: return gmail_result # Schritt 4: Passwort festlegen password_result = self._set_password(account_data) if not password_result["success"]: return password_result # Schritt 5: Recovery Email (optional, aber hilft, Phone zu vermeiden) recovery_result = self._handle_recovery_email(account_data) if not recovery_result["success"]: return recovery_result # Schritt 6: Telefonnummer (optional/erforderlich) – wird möglichst übersprungen phone_result = self._handle_phone_verification(account_data) if not phone_result["success"]: return phone_result # Schritt 7: Nutzungsbedingungen akzeptieren terms_result = self._accept_terms() if not terms_result["success"]: return terms_result # Schritt 8: Abschluss verifizieren (Weiterleitung/Willkommensseite) verify_ok = self._verify_account_creation() if not verify_ok: return { "success": False, "error": "Verifikation der Kontoerstellung fehlgeschlagen", "message": "Registrierung nicht bestätigt – bitte erneut versuchen" } return { "success": True, "username": gmail_result.get("username"), "email": gmail_result.get("email"), "message": "Registrierung erfolgreich abgeschlossen" } except Exception as e: logger.error(f"Fehler im Registrierungsflow: {e}") self.ui_helper.take_screenshot("registration_error") return { "success": False, "error": str(e), "message": f"Registrierung fehlgeschlagen: {str(e)}" } def _fill_name_form(self, account_data: Dict[str, str]) -> Dict[str, any]: """ Füllt das Namensformular aus """ try: logger.info("Fülle Namensformular aus") # Screenshot der aktuellen Seite self.ui_helper.take_screenshot("before_name_form_search") # Warte kurz, damit die Seite vollständig lädt time.sleep(2) # Debug: Aktuelle URL ausgeben current_url = self.page.url logger.info(f"Aktuelle URL: {current_url}") # Versuche Cookie-Banner zu schließen, falls vorhanden try: # Suche nach typischen Cookie-Akzeptieren-Buttons cookie_selectors = [ "button:has-text('Alle akzeptieren')", "button:has-text('Accept all')", "button:has-text('Akzeptieren')", "button:has-text('Accept')", "[aria-label='Alle akzeptieren']" ] for selector in cookie_selectors: try: if self.page.locator(selector).is_visible(timeout=1000): self.page.locator(selector).click() logger.info(f"Cookie-Banner geschlossen mit: {selector}") time.sleep(1) break except: continue except Exception as e: logger.debug(f"Kein Cookie-Banner gefunden oder Fehler: {e}") # Versuche verschiedene Selektoren für das Vorname-Feld first_name_selectors = [ selectors.FIRST_NAME_INPUT, "input[aria-label='Vorname']", "input[aria-label='First name']", "#firstName", "input[type='text'][autocomplete='given-name']" ] first_name_found = False for selector in first_name_selectors: if self.ui_helper.wait_for_element(selector, timeout=3000): first_name_found = True selectors.FIRST_NAME_INPUT = selector # Update für diesen Durchlauf logger.info(f"Vorname-Feld gefunden mit Selektor: {selector}") break if not first_name_found: # Screenshot bei Fehler self.ui_helper.take_screenshot("name_form_not_found_error") return { "success": False, "error": "Namensformular nicht gefunden", "message": "Registrierungsseite konnte nicht geladen werden" } # Vorname eingeben first_name = account_data.get("first_name", "") logger.info(f"Gebe Vorname ein: {first_name}") self.ui_helper.type_with_delay(selectors.FIRST_NAME_INPUT, first_name) time.sleep(random.uniform(0.5, 1)) # Nachname eingeben - versuche verschiedene Selektoren last_name_selectors = [ selectors.LAST_NAME_INPUT, "input[aria-label='Nachname']", "input[aria-label='Last name']", "#lastName", "input[type='text'][autocomplete='family-name']" ] last_name = account_data.get("last_name", "") logger.info(f"Gebe Nachname ein: {last_name}") for selector in last_name_selectors: try: if self.ui_helper.wait_for_element(selector, timeout=2000): self.ui_helper.type_with_delay(selector, last_name) logger.info(f"Nachname eingegeben mit Selektor: {selector}") break except: continue time.sleep(random.uniform(0.5, 1)) # Screenshot vor dem Weiter-Klick self.ui_helper.take_screenshot("name_form_filled") # Weiter Button klicken if not self._click_next_button(): return { "success": False, "error": "Konnte Weiter-Button nicht klicken", "message": "Navigation fehlgeschlagen" } self.ui_helper.wait_for_loading_to_finish() time.sleep(random.uniform(2, 3)) return { "success": True, "message": "Namensformular ausgefüllt" } except Exception as e: logger.error(f"Fehler beim Ausfüllen des Namensformulars: {e}") return { "success": False, "error": str(e) } def _fill_birthday_gender(self, account_data: Dict[str, str]) -> Dict[str, any]: """ Füllt Geburtsdatum und Geschlecht aus """ try: logger.info("Fülle Geburtsdatum und Geschlecht aus") # Warte auf Formular if not self.ui_helper.wait_for_element(selectors.BIRTHDAY_DAY, timeout=10000): logger.warning("Geburtsdatum-Formular nicht gefunden, überspringe...") return {"success": True} # Geburtsdatum ausfüllen birthday = account_data.get("birthday", "1990-01-15") year, month, day = birthday.split("-") # Tag eingeben (sicheres Füllen) logger.info(f"Gebe Geburtstag ein: {day}") try: self.ui_helper.safe_fill(selectors.BIRTHDAY_DAY, day.lstrip("0")) except Exception: self.ui_helper.type_with_delay(selectors.BIRTHDAY_DAY, day.lstrip("0")) time.sleep(random.uniform(0.3, 0.6)) # Monat auswählen – robust: select_option oder per Label/Text logger.info(f"Wähle Geburtsmonat: {month}") month_index = max(1, min(12, int(month))) month_value = str(month_index) # für if self.ui_helper.select_dropdown_by_selector(selectors.BIRTHDAY_MONTH, month_text_candidates): selected_month = True if not selected_month: logger.warning("Konnte Monat nicht auswählen – fahre trotzdem fort") time.sleep(random.uniform(0.3, 0.6)) # Jahr eingeben (sicheres Füllen) logger.info(f"Gebe Geburtsjahr ein: {year}") try: self.ui_helper.safe_fill(selectors.BIRTHDAY_YEAR, year) except Exception: self.ui_helper.type_with_delay(selectors.BIRTHDAY_YEAR, year) time.sleep(random.uniform(0.3, 0.6)) # Geschlecht auswählen – robust gender = account_data.get("gender", "male").lower() logger.info(f"Wähle Geschlecht: {gender}") gender_value = "1" if gender == "male" else "2" # für