Initial commit
Dieser Commit ist enthalten in:
336
social_networks/gmail/gmail_automation.py
Normale Datei
336
social_networks/gmail/gmail_automation.py
Normale Datei
@ -0,0 +1,336 @@
|
||||
"""
|
||||
Gmail Automatisierung - Hauptklasse
|
||||
"""
|
||||
|
||||
import logging
|
||||
import time
|
||||
import random
|
||||
from typing import Dict, Optional, Tuple, Any
|
||||
from playwright.sync_api import Page
|
||||
|
||||
from social_networks.base_automation import BaseAutomation
|
||||
from social_networks.gmail import gmail_selectors as selectors
|
||||
from social_networks.gmail.gmail_ui_helper import GmailUIHelper
|
||||
from social_networks.gmail.gmail_registration import GmailRegistration
|
||||
from social_networks.gmail.gmail_login import GmailLogin
|
||||
from social_networks.gmail.gmail_verification import GmailVerification
|
||||
from social_networks.gmail.gmail_utils import GmailUtils
|
||||
|
||||
logger = logging.getLogger("gmail_automation")
|
||||
|
||||
class GmailAutomation(BaseAutomation):
|
||||
"""
|
||||
Gmail/Google Account-spezifische Automatisierung
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
"""
|
||||
Initialisiert die Gmail-Automatisierung
|
||||
"""
|
||||
super().__init__(**kwargs)
|
||||
self.platform_name = "gmail"
|
||||
self.ui_helper = None
|
||||
self.registration = None
|
||||
self.login_helper = None
|
||||
self.verification = None
|
||||
self.utils = None
|
||||
|
||||
def _initialize_helpers(self, page: Page):
|
||||
"""
|
||||
Initialisiert die Hilfsklassen
|
||||
"""
|
||||
self.ui_helper = GmailUIHelper(page, self.screenshots_dir, self.save_screenshots)
|
||||
self.registration = GmailRegistration(page, self.ui_helper, self.screenshots_dir, self.save_screenshots)
|
||||
self.login_helper = GmailLogin(page, self.ui_helper, self.screenshots_dir, self.save_screenshots)
|
||||
self.verification = GmailVerification(page, self.ui_helper, self.email_handler, self.screenshots_dir, self.save_screenshots)
|
||||
self.utils = GmailUtils()
|
||||
|
||||
def register_account(self, full_name: str, age: int, registration_method: str = "email",
|
||||
phone_number: str = None, **kwargs) -> Dict[str, any]:
|
||||
"""
|
||||
Erstellt einen neuen Gmail/Google Account
|
||||
|
||||
Args:
|
||||
full_name: Vollständiger Name für den Account
|
||||
age: Alter des Benutzers
|
||||
registration_method: Registrierungsmethode (nur "email" für Gmail)
|
||||
phone_number: Telefonnummer (optional, aber oft erforderlich)
|
||||
**kwargs: Weitere optionale Parameter
|
||||
"""
|
||||
try:
|
||||
logger.info(f"[GMAIL AUTOMATION] register_account aufgerufen")
|
||||
logger.info(f"[GMAIL AUTOMATION] full_name: {full_name}")
|
||||
logger.info(f"[GMAIL AUTOMATION] age: {age}")
|
||||
logger.info(f"[GMAIL AUTOMATION] phone_number: {phone_number}")
|
||||
logger.info(f"[GMAIL AUTOMATION] kwargs: {kwargs}")
|
||||
|
||||
# Erstelle account_data aus den Parametern
|
||||
account_data = {
|
||||
"full_name": full_name,
|
||||
"first_name": kwargs.get("first_name", full_name.split()[0] if full_name else ""),
|
||||
"last_name": kwargs.get("last_name", full_name.split()[-1] if full_name and len(full_name.split()) > 1 else ""),
|
||||
"age": age,
|
||||
"birthday": kwargs.get("birthday", self._generate_birthday(age)),
|
||||
"gender": kwargs.get("gender", random.choice(["male", "female"])),
|
||||
"username": kwargs.get("username", ""),
|
||||
"password": kwargs.get("password", ""),
|
||||
"phone": phone_number,
|
||||
"recovery_email": kwargs.get("recovery_email", "")
|
||||
}
|
||||
|
||||
# Initialisiere Browser, falls noch nicht geschehen
|
||||
logger.info(f"[GMAIL AUTOMATION] Prüfe Browser-Status...")
|
||||
logger.info(f"[GMAIL AUTOMATION] self.browser: {self.browser}")
|
||||
if self.browser:
|
||||
logger.info(f"[GMAIL AUTOMATION] hasattr(self.browser, 'page'): {hasattr(self.browser, 'page')}")
|
||||
|
||||
if not self.browser or not hasattr(self.browser, 'page'):
|
||||
logger.info(f"[GMAIL AUTOMATION] Browser muss initialisiert werden")
|
||||
if not self._initialize_browser():
|
||||
logger.error(f"[GMAIL AUTOMATION] Browser-Initialisierung fehlgeschlagen!")
|
||||
return {
|
||||
"success": False,
|
||||
"error": "Browser konnte nicht initialisiert werden",
|
||||
"message": "Browser-Initialisierung fehlgeschlagen"
|
||||
}
|
||||
logger.info(f"[GMAIL AUTOMATION] Browser erfolgreich initialisiert")
|
||||
|
||||
# Page-Objekt holen
|
||||
page = self.browser.page
|
||||
self._initialize_helpers(page)
|
||||
|
||||
# Direkt zur Registrierungs-URL navigieren
|
||||
logger.info("Navigiere zur Gmail Registrierungsseite")
|
||||
page.goto(selectors.REGISTRATION_URL, wait_until="networkidle")
|
||||
|
||||
# Warte auf vollständiges Laden der Seite
|
||||
logger.info("Warte auf vollständiges Laden der Seite...")
|
||||
time.sleep(random.uniform(5, 7))
|
||||
|
||||
# Prüfe ob wir auf der richtigen Seite sind
|
||||
current_url = page.url
|
||||
logger.info(f"Aktuelle URL nach Navigation: {current_url}")
|
||||
|
||||
# Screenshot der Startseite
|
||||
self.ui_helper.take_screenshot("gmail_start_page")
|
||||
|
||||
# Finde und klicke auf "Konto erstellen" Button (Dropdown)
|
||||
try:
|
||||
# Warte bis die Seite interaktiv ist
|
||||
logger.info("Warte auf vollständiges Laden der Gmail Workspace Seite...")
|
||||
page.wait_for_load_state("networkidle")
|
||||
time.sleep(2)
|
||||
|
||||
# Debug: Alle sichtbaren Links/Buttons mit "Konto" ausgeben
|
||||
try:
|
||||
konto_elements = page.locator("*:has-text('Konto')").all()
|
||||
logger.info(f"Gefundene Elemente mit 'Konto': {len(konto_elements)}")
|
||||
for i, elem in enumerate(konto_elements[:5]): # Erste 5 Elemente
|
||||
try:
|
||||
tag = elem.evaluate("el => el.tagName")
|
||||
text = elem.inner_text()
|
||||
logger.info(f"Element {i}: <{tag}> - {text}")
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
logger.debug(f"Debug-Ausgabe fehlgeschlagen: {e}")
|
||||
|
||||
# Schritt 1: Klicke auf "Konto erstellen" Dropdown
|
||||
create_account_selectors = [
|
||||
"[aria-label='Konto erstellen']",
|
||||
"div[aria-label='Konto erstellen']",
|
||||
"[data-g-action='create an account']",
|
||||
"button:has-text('Konto erstellen')",
|
||||
"a:has-text('Konto erstellen')",
|
||||
"*:has-text('Konto erstellen')", # Beliebiges Element mit dem Text
|
||||
"[slot='label']:has-text('Konto erstellen')" # Spezifisch für Web Components
|
||||
]
|
||||
|
||||
clicked_dropdown = False
|
||||
for selector in create_account_selectors:
|
||||
try:
|
||||
elements = page.locator(selector).all()
|
||||
logger.info(f"Selector {selector}: {len(elements)} Elemente gefunden")
|
||||
|
||||
if page.locator(selector).is_visible(timeout=3000):
|
||||
# Versuche normale Klick-Methode
|
||||
try:
|
||||
page.locator(selector).first.click()
|
||||
logger.info(f"Dropdown 'Konto erstellen' geklickt mit: {selector}")
|
||||
clicked_dropdown = True
|
||||
break
|
||||
except:
|
||||
# Versuche JavaScript-Klick als Fallback
|
||||
page.locator(selector).first.evaluate("el => el.click()")
|
||||
logger.info(f"Dropdown 'Konto erstellen' via JS geklickt mit: {selector}")
|
||||
clicked_dropdown = True
|
||||
break
|
||||
except Exception as e:
|
||||
logger.debug(f"Fehler mit Selector {selector}: {e}")
|
||||
continue
|
||||
|
||||
if not clicked_dropdown:
|
||||
logger.error("Konnte 'Konto erstellen' Dropdown nicht finden")
|
||||
self.ui_helper.take_screenshot("konto_erstellen_not_found")
|
||||
return {
|
||||
"success": False,
|
||||
"error": "Konto erstellen Dropdown nicht gefunden",
|
||||
"message": "Navigation fehlgeschlagen"
|
||||
}
|
||||
|
||||
# Kurz warten bis Dropdown geöffnet ist
|
||||
time.sleep(1)
|
||||
|
||||
# Schritt 2: Klicke auf "Für die private Nutzung"
|
||||
private_use_selectors = [
|
||||
"a[aria-label='Gmail - Für die private Nutzung']",
|
||||
"a:has-text('Für die private Nutzung')",
|
||||
"[data-g-action='für die private nutzung']",
|
||||
"span:has-text('Für die private Nutzung')"
|
||||
]
|
||||
|
||||
clicked_private = False
|
||||
for selector in private_use_selectors:
|
||||
try:
|
||||
if page.locator(selector).is_visible(timeout=2000):
|
||||
page.locator(selector).click()
|
||||
logger.info(f"'Für die private Nutzung' geklickt mit: {selector}")
|
||||
clicked_private = True
|
||||
break
|
||||
except:
|
||||
continue
|
||||
|
||||
if not clicked_private:
|
||||
logger.error("Konnte 'Für die private Nutzung' nicht finden")
|
||||
self.ui_helper.take_screenshot("private_nutzung_not_found")
|
||||
return {
|
||||
"success": False,
|
||||
"error": "Für die private Nutzung Option nicht gefunden",
|
||||
"message": "Navigation fehlgeschlagen"
|
||||
}
|
||||
|
||||
# Warte auf die Registrierungsseite
|
||||
time.sleep(random.uniform(3, 5))
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Fehler beim Navigieren zur Registrierung: {e}")
|
||||
|
||||
# Screenshot der Registrierungsseite
|
||||
self.ui_helper.take_screenshot("gmail_registration_page")
|
||||
|
||||
# Registrierungsprozess starten
|
||||
registration_result = self.registration.start_registration_flow(account_data)
|
||||
if not registration_result["success"]:
|
||||
return registration_result
|
||||
|
||||
# Nach erfolgreicher Registrierung
|
||||
logger.info("Gmail Account-Registrierung erfolgreich abgeschlossen")
|
||||
return {
|
||||
"success": True,
|
||||
"username": registration_result.get("username"),
|
||||
"password": account_data.get("password"),
|
||||
"email": registration_result.get("email"),
|
||||
"phone": account_data.get("phone"),
|
||||
"recovery_email": account_data.get("recovery_email"),
|
||||
"message": "Account erfolgreich erstellt"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Fehler bei der Gmail-Registrierung: {str(e)}")
|
||||
return {
|
||||
"success": False,
|
||||
"error": str(e),
|
||||
"message": f"Registrierung fehlgeschlagen: {str(e)}"
|
||||
}
|
||||
finally:
|
||||
self._close_browser()
|
||||
|
||||
def login(self, username: str, password: str) -> Dict[str, any]:
|
||||
"""
|
||||
Meldet sich bei einem bestehenden Gmail/Google Account an
|
||||
"""
|
||||
try:
|
||||
logger.info(f"Starte Gmail Login für {username}")
|
||||
|
||||
# Initialisiere Browser, falls noch nicht geschehen
|
||||
if not self.browser or not hasattr(self.browser, 'page'):
|
||||
if not self._initialize_browser():
|
||||
return {
|
||||
"success": False,
|
||||
"error": "Browser konnte nicht initialisiert werden",
|
||||
"message": "Browser-Initialisierung fehlgeschlagen"
|
||||
}
|
||||
|
||||
# Page-Objekt holen
|
||||
page = self.browser.page
|
||||
self._initialize_helpers(page)
|
||||
|
||||
# Login durchführen
|
||||
return self.login_helper.login(username, password)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Fehler beim Gmail Login: {str(e)}")
|
||||
return {
|
||||
"success": False,
|
||||
"error": str(e),
|
||||
"message": f"Login fehlgeschlagen: {str(e)}"
|
||||
}
|
||||
finally:
|
||||
self._close_browser()
|
||||
|
||||
def get_account_info(self) -> Dict[str, any]:
|
||||
"""
|
||||
Ruft Informationen über den aktuellen Account ab
|
||||
"""
|
||||
# TODO: Implementierung
|
||||
return {
|
||||
"success": False,
|
||||
"message": "Noch nicht implementiert"
|
||||
}
|
||||
|
||||
def logout(self) -> bool:
|
||||
"""
|
||||
Meldet sich vom aktuellen Account ab
|
||||
"""
|
||||
# TODO: Implementierung
|
||||
return False
|
||||
|
||||
def login_account(self, username_or_email: str, password: str, **kwargs) -> Dict[str, Any]:
|
||||
"""
|
||||
Meldet sich bei einem bestehenden Gmail Account an.
|
||||
Implementiert die abstrakte Methode aus BaseAutomation.
|
||||
"""
|
||||
return self.login(username_or_email, password)
|
||||
|
||||
def verify_account(self, verification_code: str, **kwargs) -> Dict[str, Any]:
|
||||
"""
|
||||
Verifiziert einen Gmail Account mit einem Bestätigungscode.
|
||||
Implementiert die abstrakte Methode aus BaseAutomation.
|
||||
"""
|
||||
try:
|
||||
if self.verification:
|
||||
return self.verification.verify_with_code(verification_code)
|
||||
else:
|
||||
return {
|
||||
"success": False,
|
||||
"error": "Verification helper nicht initialisiert",
|
||||
"message": "Verifizierung kann nicht durchgeführt werden"
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
"success": False,
|
||||
"error": str(e),
|
||||
"message": f"Verifizierung fehlgeschlagen: {str(e)}"
|
||||
}
|
||||
|
||||
def _generate_birthday(self, age: int) -> str:
|
||||
"""
|
||||
Generiert ein Geburtsdatum basierend auf dem Alter
|
||||
"""
|
||||
from datetime import datetime, timedelta
|
||||
today = datetime.now()
|
||||
birth_year = today.year - age
|
||||
# Zufälliger Tag im Jahr
|
||||
random_days = random.randint(0, 364)
|
||||
birthday = datetime(birth_year, 1, 1) + timedelta(days=random_days)
|
||||
return birthday.strftime("%Y-%m-%d")
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren