Dieser Commit ist enthalten in:
Claude Project Manager
2025-08-01 23:50:28 +02:00
Commit 04585e95b6
290 geänderte Dateien mit 64086 neuen und 0 gelöschten Zeilen

Datei anzeigen

@ -0,0 +1,7 @@
"""
OK.ru (Odnoklassniki) automation package.
"""
from .ok_ru_automation import OkRuAutomation
__all__ = ['OkRuAutomation']

Datei anzeigen

@ -0,0 +1,303 @@
"""
OK.ru (Odnoklassniki) Automatisierung - Hauptklasse für OK.ru-Automatisierungsfunktionalität
"""
import time
import random
from typing import Dict, List, Any, Optional, Tuple
from browser.playwright_manager import PlaywrightManager
from browser.playwright_extensions import PlaywrightExtensions
from social_networks.base_automation import BaseAutomation
from utils.password_generator import PasswordGenerator
from utils.username_generator import UsernameGenerator
from utils.birthday_generator import BirthdayGenerator
from utils.human_behavior import HumanBehavior
from utils.logger import setup_logger
# Importiere Helferklassen
from .ok_ru_registration import OkRuRegistration
from .ok_ru_login import OkRuLogin
from .ok_ru_verification import OkRuVerification
from .ok_ru_ui_helper import OkRuUIHelper
from .ok_ru_utils import OkRuUtils
# Konfiguriere Logger
logger = setup_logger("ok_ru_automation")
class OkRuAutomation(BaseAutomation):
"""
Hauptklasse für die OK.ru (Odnoklassniki) Automatisierung.
Implementiert die Registrierung und Anmeldung bei OK.ru.
"""
def __init__(self,
headless: bool = False,
use_proxy: bool = False,
proxy_type: str = None,
save_screenshots: bool = True,
screenshots_dir: str = None,
slowmo: int = 0,
debug: bool = False,
email_domain: str = "z5m7q9dk3ah2v1plx6ju.com",
enhanced_stealth: bool = True,
fingerprint_noise: float = 0.5,
window_position = None,
fingerprint = None,
auto_close_browser: bool = False):
"""
Initialisiert die OK.ru-Automatisierung.
Args:
headless: Ob der Browser im Headless-Modus ausgeführt werden soll
use_proxy: Ob ein Proxy verwendet werden soll
proxy_type: Proxy-Typ ("ipv4", "ipv6", "mobile") oder None für zufälligen Typ
save_screenshots: Ob Screenshots gespeichert werden sollen
screenshots_dir: Verzeichnis für Screenshots
slowmo: Verzögerung zwischen Aktionen in Millisekunden (nützlich für Debugging)
debug: Ob Debug-Informationen angezeigt werden sollen
email_domain: Domain für generierte E-Mail-Adressen
enhanced_stealth: Ob erweiterter Stealth-Modus aktiviert werden soll
fingerprint_noise: Menge an Rauschen für Fingerprint-Verschleierung (0.0-1.0)
window_position: Optional - Fensterposition als Tuple (x, y)
fingerprint: Optional - Vordefinierter Browser-Fingerprint
auto_close_browser: Ob Browser automatisch geschlossen werden soll (Standard: False)
"""
# Initialisiere die Basisklasse
super().__init__(
headless=headless,
use_proxy=use_proxy,
proxy_type=proxy_type,
save_screenshots=save_screenshots,
screenshots_dir=screenshots_dir,
slowmo=slowmo,
debug=debug,
email_domain=email_domain,
window_position=window_position,
auto_close_browser=auto_close_browser
)
# Stealth-Modus-Einstellungen
self.enhanced_stealth = enhanced_stealth
self.fingerprint_noise = max(0.0, min(1.0, fingerprint_noise))
# Initialisiere Helferklassen
self.registration = OkRuRegistration(self)
self.login = OkRuLogin(self)
self.verification = OkRuVerification(self)
self.ui_helper = OkRuUIHelper(self)
self.utils = OkRuUtils(self)
# Zusätzliche Hilfsklassen
self.password_generator = PasswordGenerator()
self.username_generator = UsernameGenerator()
self.birthday_generator = BirthdayGenerator()
self.human_behavior = HumanBehavior(speed_factor=0.8, randomness=0.6)
# Nutze übergebenen Fingerprint wenn vorhanden
self.provided_fingerprint = fingerprint
logger.info("OK.ru-Automatisierung initialisiert")
def _initialize_browser(self) -> bool:
"""
Initialisiert den Browser mit den entsprechenden Einstellungen.
Returns:
bool: True bei Erfolg, False bei Fehler
"""
try:
# Proxy-Konfiguration, falls aktiviert
proxy_config = None
if self.use_proxy:
proxy_config = self.proxy_rotator.get_proxy(self.proxy_type)
if not proxy_config:
logger.warning(f"Kein Proxy vom Typ '{self.proxy_type}' verfügbar, verwende direkten Zugriff")
# Browser initialisieren
self.browser = PlaywrightManager(
headless=self.headless,
proxy=proxy_config,
browser_type="chromium",
screenshots_dir=self.screenshots_dir,
slowmo=self.slowmo
)
# Browser starten
self.browser.start()
# Erweiterten Fingerprint-Schutz aktivieren, wenn gewünscht
if self.enhanced_stealth:
# Erstelle Extensions-Objekt
extensions = PlaywrightExtensions(self.browser)
# Methoden anhängen
extensions.hook_into_playwright_manager()
# Fingerprint-Schutz aktivieren mit angepasster Konfiguration
if self.provided_fingerprint:
# Nutze den bereitgestellten Fingerprint
logger.info("Verwende bereitgestellten Fingerprint für Account-Erstellung")
# Konvertiere Dict zu BrowserFingerprint wenn nötig
if isinstance(self.provided_fingerprint, dict):
from domain.entities.browser_fingerprint import BrowserFingerprint
fingerprint_obj = BrowserFingerprint.from_dict(self.provided_fingerprint)
else:
fingerprint_obj = self.provided_fingerprint
# Wende Fingerprint über FingerprintProtection an
from browser.fingerprint_protection import FingerprintProtection
protection = FingerprintProtection(
context=self.browser.context,
fingerprint_config=fingerprint_obj
)
protection.apply_to_context(self.browser.context)
logger.info(f"Fingerprint {fingerprint_obj.fingerprint_id} angewendet")
else:
# Fallback: Zufällige Fingerprint-Konfiguration
fingerprint_config = {
"noise_level": self.fingerprint_noise,
"canvas_noise": True,
"audio_noise": True,
"webgl_noise": True,
"hardware_concurrency": random.choice([4, 6, 8]),
"device_memory": random.choice([4, 8]),
"timezone_id": "Europe/Moscow" # Russische Zeitzone für OK.ru
}
success = self.browser.enable_enhanced_fingerprint_protection(fingerprint_config)
if success:
logger.info("Erweiterter Fingerprint-Schutz erfolgreich aktiviert")
else:
logger.warning("Erweiterter Fingerprint-Schutz konnte nicht aktiviert werden")
logger.info("Browser erfolgreich initialisiert")
return True
except Exception as e:
logger.error(f"Fehler bei der Browser-Initialisierung: {e}")
self.status["error"] = f"Browser-Initialisierungsfehler: {str(e)}"
return False
def register_account(self, full_name: str, age: int, registration_method: str = "phone",
phone_number: str = None, **kwargs) -> Dict[str, Any]:
"""
Registriert einen neuen OK.ru-Account.
Args:
full_name: Vollständiger Name für den Account
age: Alter des Benutzers
registration_method: "phone" (OK.ru unterstützt hauptsächlich Telefon-Registrierung)
phone_number: Telefonnummer (erforderlich)
**kwargs: Weitere optionale Parameter
Returns:
Dict[str, Any]: Ergebnis der Registrierung mit Status und Account-Daten
"""
logger.info(f"Starte OK.ru-Account-Registrierung für '{full_name}'")
self._emit_customer_log(f"📱 OK.ru-Account wird erstellt für: {full_name}")
try:
# 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"}
# Rotiere Fingerprint vor der Registrierung
if self.enhanced_stealth and hasattr(self.browser, 'rotate_fingerprint'):
self.browser.rotate_fingerprint()
logger.info("Browser-Fingerprint vor der Registrierung rotiert")
# Delegiere die Hauptregistrierungslogik an die Registration-Klasse
result = self.registration.register_account(
full_name=full_name,
age=age,
registration_method=registration_method,
phone_number=phone_number,
**kwargs
)
# Nehme Abschlussfoto auf
self._take_screenshot(f"registration_finished_{int(time.time())}")
# Aktualisiere Status
self.status.update(result)
return result
except Exception as e:
error_msg = f"Unerwarteter Fehler bei der Registrierung: {str(e)}"
logger.error(error_msg, exc_info=True)
# Fehler-Screenshot
self._take_screenshot(f"registration_error_{int(time.time())}")
# Aktualisiere Status
self.status.update({
"success": False,
"error": error_msg,
"stage": "exception"
})
return self.status
finally:
# Browser schließen
self._close_browser()
def login_account(self, username_or_email: str, password: str, **kwargs) -> Dict[str, Any]:
"""
Meldet sich bei einem bestehenden OK.ru-Account an.
Args:
username_or_email: Benutzername, E-Mail oder Telefonnummer
password: Passwort
**kwargs: Weitere optionale Parameter
Returns:
Dict[str, Any]: Ergebnis der Anmeldung mit Status
"""
logger.info(f"Starte OK.ru-Login für '{username_or_email}'")
try:
# 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"}
# Rotiere Fingerprint vor dem Login
if self.enhanced_stealth and hasattr(self.browser, 'rotate_fingerprint'):
self.browser.rotate_fingerprint()
logger.info("Browser-Fingerprint vor dem Login rotiert")
# Delegiere die Hauptlogin-Logik an die Login-Klasse
result = self.login.login_account(username_or_email, password, **kwargs)
# Nehme Abschlussfoto auf
self._take_screenshot(f"login_finished_{int(time.time())}")
# Aktualisiere Status
self.status.update(result)
return result
except Exception as e:
error_msg = f"Unerwarteter Fehler beim Login: {str(e)}"
logger.error(error_msg, exc_info=True)
# Fehler-Screenshot
self._take_screenshot(f"login_error_{int(time.time())}")
# Aktualisiere Status
self.status.update({
"success": False,
"error": error_msg,
"stage": "exception"
})
return self.status
finally:
# Browser schließen wenn auto_close aktiviert
if self.auto_close_browser:
self._close_browser()

Datei anzeigen

@ -0,0 +1,53 @@
# social_networks/ok_ru/ok_ru_login.py
"""
OK.ru Login - Klasse für die Anmeldung bei OK.ru-Konten
"""
import time
from typing import Dict, Any, Optional
from .ok_ru_selectors import OkRuSelectors
from utils.logger import setup_logger
# Konfiguriere Logger
logger = setup_logger("ok_ru_login")
class OkRuLogin:
"""
Klasse für die Anmeldung bei OK.ru-Konten.
Behandelt den kompletten Login-Prozess.
"""
def __init__(self, automation):
"""
Initialisiert die OK.ru-Login-Klasse.
Args:
automation: Referenz auf die Hauptautomatisierungsklasse
"""
self.automation = automation
self.selectors = OkRuSelectors()
logger.debug("OK.ru-Login initialisiert")
def login_account(self, username_or_email: str, password: str, **kwargs) -> Dict[str, Any]:
"""
Führt den Login-Prozess für einen OK.ru-Account durch.
Args:
username_or_email: Benutzername, E-Mail oder Telefonnummer
password: Passwort
**kwargs: Weitere optionale Parameter
Returns:
Dict[str, Any]: Ergebnis des Logins mit Status
"""
logger.info(f"Starte OK.ru-Login für '{username_or_email}'")
# Temporäre Implementierung
return {
"success": False,
"error": "OK.ru Login noch nicht implementiert",
"stage": "not_implemented"
}

Datei anzeigen

@ -0,0 +1,178 @@
# social_networks/ok_ru/ok_ru_registration.py
"""
OK.ru Registration - Klasse für die Registrierung bei OK.ru
"""
import time
from typing import Dict, Any, Optional
from .ok_ru_selectors import OkRuSelectors
from utils.logger import setup_logger
# Konfiguriere Logger
logger = setup_logger("ok_ru_registration")
class OkRuRegistration:
"""
Klasse für die Registrierung bei OK.ru.
Behandelt den kompletten Registrierungsprozess.
"""
def __init__(self, automation):
"""
Initialisiert die OK.ru-Registration-Klasse.
Args:
automation: Referenz auf die Hauptautomatisierungsklasse
"""
self.automation = automation
self.selectors = OkRuSelectors()
logger.debug("OK.ru-Registration initialisiert")
def register_account(self, full_name: str, age: int, registration_method: str = "phone",
phone_number: str = None, **kwargs) -> Dict[str, Any]:
"""
Führt den Registrierungsprozess für einen OK.ru-Account durch.
Args:
full_name: Vollständiger Name
age: Alter
registration_method: Registrierungsmethode (normalerweise "phone")
phone_number: Telefonnummer
**kwargs: Weitere optionale Parameter
Returns:
Dict[str, Any]: Ergebnis der Registrierung mit Status
"""
logger.info(f"Starte OK.ru-Registrierung für '{full_name}'")
try:
# 1. Zur OK.ru mobilen Seite navigieren
self.automation._emit_customer_log("🌐 Verbinde mit OK.ru...")
if not self._navigate_to_homepage():
return {
"success": False,
"error": "Konnte nicht zur OK.ru-Startseite navigieren",
"stage": "navigation"
}
# 2. Cookie-Banner behandeln (falls vorhanden)
self._handle_cookie_banner()
# 3. Registrieren-Button klicken
self.automation._emit_customer_log("📝 Öffne Registrierungsformular...")
if not self._click_register_button():
return {
"success": False,
"error": "Konnte Registrieren-Button nicht finden oder klicken",
"stage": "register_button"
}
# Weitere Schritte müssen noch implementiert werden
return {
"success": False,
"error": "OK.ru Registrierung in Entwicklung - weitere Schritte folgen",
"stage": "in_development"
}
except Exception as e:
error_msg = f"Unerwarteter Fehler bei OK.ru-Registrierung: {str(e)}"
logger.error(error_msg, exc_info=True)
return {
"success": False,
"error": error_msg,
"stage": "exception"
}
def _navigate_to_homepage(self) -> bool:
"""
Navigiert zur OK.ru Startseite.
Returns:
bool: True bei Erfolg, False bei Fehler
"""
try:
page = self.automation.browser.page
logger.info("Navigiere zur OK.ru Startseite")
page.goto("https://m.ok.ru/", wait_until="domcontentloaded", timeout=30000)
# Warte auf Seitenladung
self.automation.human_behavior.random_delay(2, 4)
# Screenshot
self.automation._take_screenshot("ok_ru_homepage")
return True
except Exception as e:
logger.error(f"Fehler beim Navigieren zur OK.ru Startseite: {e}")
return False
def _handle_cookie_banner(self):
"""
Behandelt eventuelle Cookie-Banner.
"""
try:
page = self.automation.browser.page
for selector in self.selectors.COOKIE_ACCEPT_BUTTONS:
try:
if page.is_visible(selector):
logger.info(f"Cookie-Banner gefunden: {selector}")
page.wait_for_selector(selector, timeout=2000).click()
self.automation.human_behavior.random_delay(1, 2)
break
except:
continue
except Exception as e:
logger.debug(f"Kein Cookie-Banner gefunden oder Fehler: {e}")
def _click_register_button(self) -> bool:
"""
Klickt auf den Registrieren-Button.
Returns:
bool: True bei Erfolg, False bei Fehler
"""
try:
page = self.automation.browser.page
# Warte kurz
self.automation.human_behavior.random_delay(1, 2)
# Versuche verschiedene Registrieren-Button-Selektoren
register_selectors = [
self.selectors.REGISTRATION["register_button"],
self.selectors.REGISTRATION["register_button_alt"],
self.selectors.REGISTRATION["register_button_data"]
]
for selector in register_selectors:
try:
if page.is_visible(selector, timeout=3000):
logger.info(f"Registrieren-Button gefunden: {selector}")
self.automation.human_behavior.random_delay(0.5, 1.5)
page.click(selector)
self.automation.human_behavior.random_delay(2, 3)
# Screenshot nach Klick
self.automation._take_screenshot("after_register_click")
return True
except Exception as e:
logger.debug(f"Selektor {selector} nicht gefunden: {e}")
continue
# Screenshot für Debugging
self.automation._take_screenshot("register_button_not_found")
logger.error("Keinen Registrieren-Button gefunden")
return False
except Exception as e:
logger.error(f"Fehler beim Klicken auf Registrieren-Button: {e}")
return False

Datei anzeigen

@ -0,0 +1,168 @@
# social_networks/ok_ru/ok_ru_selectors.py
"""
OK.ru (Odnoklassniki) Selektoren - Zentrale Sammlung aller CSS-Selektoren für OK.ru
"""
class OkRuSelectors:
"""
Zentrale Klasse für alle OK.ru-spezifischen CSS-Selektoren.
Optimiert für die mobile Version (m.ok.ru).
"""
# === ALLGEMEINE SELEKTOREN ===
COOKIE_ACCEPT_BUTTONS = [
"button:has-text('Принять')",
"button:has-text('Accept')",
"button:has-text('OK')",
"[class*='cookie'] button"
]
# === REGISTRIERUNG ===
REGISTRATION = {
# Hauptseite
"register_button": 'input[name="registerButton"][value="Registrieren"]',
"register_button_alt": 'input[type="submit"][value="Registrieren"]',
"register_button_data": 'input[data-log-click*="register"]',
# Formularfelder
"phone_input": 'input[name="st.email"]',
"phone_input_alt": 'input[type="tel"]',
"country_code_select": 'select[name="st.countryCode"]',
# Buttons
"get_code_button": 'input[type="submit"][value*="Получить код"]',
"get_code_button_alt": 'button:has-text("Получить код")',
# Verifizierung
"verification_code_input": 'input[name="st.smsCode"]',
"verification_code_inputs": 'input[maxlength="1"]', # Einzelne Ziffern-Inputs
# Profil-Erstellung
"first_name_input": 'input[name="st.firstName"]',
"last_name_input": 'input[name="st.lastName"]',
"password_input": 'input[name="st.password"]',
"password_confirm_input": 'input[name="st.passwordConfirm"]',
# Geburtsdatum
"birth_day_select": 'select[name="st.bday"]',
"birth_month_select": 'select[name="st.bmonth"]',
"birth_year_select": 'select[name="st.byear"]',
# Geschlecht
"gender_male": 'input[name="st.gender"][value="1"]',
"gender_female": 'input[name="st.gender"][value="2"]',
# Submit
"register_submit": 'input[type="submit"][value*="Зарегистрироваться"]',
"register_submit_alt": 'button:has-text("Зарегистрироваться")'
}
# === LOGIN ===
LOGIN = {
# Login-Link
"login_link": 'a[href*="st.cmd=anonymMain&st.login"]',
"login_link_alt": 'a:has-text("Войти")',
"login_link_en": 'a:has-text("Log in")',
# Formularfelder
"username_input": 'input[name="st.email"]',
"username_input_alt": 'input[type="text"][name="st.email"]',
"password_input": 'input[name="st.password"]',
"password_input_alt": 'input[type="password"]',
# Submit
"login_submit": 'input[type="submit"][value*="Войти"]',
"login_submit_alt": 'button:has-text("Войти")',
"login_submit_en": 'button:has-text("Log in")'
}
# === NAVIGATION ===
NAVIGATION = {
# Hauptnavigation
"home_link": 'a[href*="/main"]',
"profile_link": 'a[href*="/profile"]',
"friends_link": 'a[href*="/friends"]',
"messages_link": 'a[href*="/messages"]',
"groups_link": 'a[href*="/groups"]',
# Mobile Menü
"menu_button": '[class*="menu-button"]',
"mobile_menu": '[class*="mobile-menu"]'
}
# === PROFIL ===
PROFILE = {
# Profilbearbeitung
"edit_profile_button": 'a:has-text("Редактировать")',
"edit_profile_button_en": 'a:has-text("Edit")',
# Avatar
"avatar_upload": 'input[type="file"]',
"avatar_container": '[class*="avatar"]'
}
# === VERIFIZIERUNG ===
VERIFICATION = {
# SMS-Verifizierung
"resend_code_link": 'a:has-text("Отправить код еще раз")',
"resend_code_timer": '[class*="timer"]',
# Captcha
"captcha_container": '[class*="captcha"]',
"captcha_input": 'input[name*="captcha"]'
}
# === FEHLER UND WARNUNGEN ===
ERRORS = {
# Fehlermeldungen
"error_message": '[class*="error"]',
"error_text": '[class*="error-text"]',
"validation_error": '[class*="validation-error"]',
# Spezifische Fehler
"phone_taken": 'text="Этот номер уже используется"',
"invalid_code": 'text="Неверный код"',
"weak_password": 'text="Слишком простой пароль"'
}
# === MODALE DIALOGE ===
MODALS = {
# Allgemeine Modale
"modal_container": '[class*="modal"]',
"modal_close": '[class*="modal-close"]',
# Bestätigung
"confirm_button": 'button:has-text("Подтвердить")',
"cancel_button": 'button:has-text("Отмена")'
}
@classmethod
def get_selector(cls, category: str, key: str) -> str:
"""
Holt einen spezifischen Selektor.
Args:
category: Kategorie (z.B. "REGISTRATION", "LOGIN")
key: Schlüssel innerhalb der Kategorie
Returns:
str: CSS-Selektor oder None
"""
category_dict = getattr(cls, category.upper(), {})
if isinstance(category_dict, dict):
return category_dict.get(key)
return None
@classmethod
def get_all_selectors(cls, category: str) -> dict:
"""
Holt alle Selektoren einer Kategorie.
Args:
category: Kategorie
Returns:
dict: Alle Selektoren der Kategorie
"""
return getattr(cls, category.upper(), {})

Datei anzeigen

@ -0,0 +1,14 @@
# social_networks/ok_ru/ok_ru_ui_helper.py
"""
OK.ru UI Helper - Hilfsfunktionen für UI-Interaktionen
"""
from utils.logger import setup_logger
logger = setup_logger("ok_ru_ui_helper")
class OkRuUIHelper:
def __init__(self, automation):
self.automation = automation
logger.debug("OK.ru-UIHelper initialisiert")

Datei anzeigen

@ -0,0 +1,14 @@
# social_networks/ok_ru/ok_ru_utils.py
"""
OK.ru Utils - Hilfsfunktionen für OK.ru
"""
from utils.logger import setup_logger
logger = setup_logger("ok_ru_utils")
class OkRuUtils:
def __init__(self, automation):
self.automation = automation
logger.debug("OK.ru-Utils initialisiert")

Datei anzeigen

@ -0,0 +1,14 @@
# social_networks/ok_ru/ok_ru_verification.py
"""
OK.ru Verification - Klasse für Verifizierungsprozesse
"""
from utils.logger import setup_logger
logger = setup_logger("ok_ru_verification")
class OkRuVerification:
def __init__(self, automation):
self.automation = automation
logger.debug("OK.ru-Verification initialisiert")