Initial commit
Dieser Commit ist enthalten in:
7
social_networks/ok_ru/__init__.py
Normale Datei
7
social_networks/ok_ru/__init__.py
Normale Datei
@ -0,0 +1,7 @@
|
||||
"""
|
||||
OK.ru (Odnoklassniki) automation package.
|
||||
"""
|
||||
|
||||
from .ok_ru_automation import OkRuAutomation
|
||||
|
||||
__all__ = ['OkRuAutomation']
|
||||
303
social_networks/ok_ru/ok_ru_automation.py
Normale Datei
303
social_networks/ok_ru/ok_ru_automation.py
Normale Datei
@ -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()
|
||||
53
social_networks/ok_ru/ok_ru_login.py
Normale Datei
53
social_networks/ok_ru/ok_ru_login.py
Normale Datei
@ -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"
|
||||
}
|
||||
178
social_networks/ok_ru/ok_ru_registration.py
Normale Datei
178
social_networks/ok_ru/ok_ru_registration.py
Normale Datei
@ -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
|
||||
168
social_networks/ok_ru/ok_ru_selectors.py
Normale Datei
168
social_networks/ok_ru/ok_ru_selectors.py
Normale Datei
@ -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(), {})
|
||||
14
social_networks/ok_ru/ok_ru_ui_helper.py
Normale Datei
14
social_networks/ok_ru/ok_ru_ui_helper.py
Normale Datei
@ -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")
|
||||
14
social_networks/ok_ru/ok_ru_utils.py
Normale Datei
14
social_networks/ok_ru/ok_ru_utils.py
Normale Datei
@ -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")
|
||||
14
social_networks/ok_ru/ok_ru_verification.py
Normale Datei
14
social_networks/ok_ru/ok_ru_verification.py
Normale Datei
@ -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")
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren