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

Datei anzeigen

@ -0,0 +1,240 @@
"""
VK Automatisierung - Hauptklasse
"""
import logging
import time
import random
from typing import Dict, Optional, Tuple
from playwright.sync_api import Page
from social_networks.base_automation import BaseAutomation
from social_networks.vk import vk_selectors as selectors
from social_networks.vk.vk_ui_helper import VKUIHelper
from social_networks.vk.vk_registration import VKRegistration
from social_networks.vk.vk_login import VKLogin
from social_networks.vk.vk_verification import VKVerification
from social_networks.vk.vk_utils import VKUtils
logger = logging.getLogger("vk_automation")
class VKAutomation(BaseAutomation):
"""
VK-spezifische Automatisierung
"""
def __init__(self, **kwargs):
"""
Initialisiert die VK-Automatisierung
"""
super().__init__(**kwargs)
self.platform_name = "vk"
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 = VKUIHelper(page, self.screenshots_dir, self.save_screenshots)
self.registration = VKRegistration(page, self.ui_helper, self.screenshots_dir, self.save_screenshots)
self.login_helper = VKLogin(page, self.ui_helper, self.screenshots_dir, self.save_screenshots)
self.verification = VKVerification(page, self.ui_helper, self.email_handler, self.screenshots_dir, self.save_screenshots)
self.utils = VKUtils()
def register_account(self, full_name: str, age: int, registration_method: str = "phone",
phone_number: str = None, **kwargs) -> Dict[str, any]:
"""
Erstellt einen neuen VK-Account
Args:
full_name: Vollständiger Name für den Account
age: Alter des Benutzers
registration_method: Registrierungsmethode (nur "phone" für VK)
phone_number: Telefonnummer (erforderlich für VK)
**kwargs: Weitere optionale Parameter
"""
try:
logger.info(f"Starte VK Account-Registrierung für {full_name}")
# 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", ""),
"email": kwargs.get("email", ""),
"phone": phone_number or ""
}
# 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)
# VK Homepage öffnen
logger.info("Navigiere zu VK Homepage")
page.goto(selectors.BASE_URL, wait_until="domcontentloaded")
time.sleep(random.uniform(2, 4))
# Screenshot der Startseite
self.ui_helper.take_screenshot("vk_homepage")
# Cookie Banner handhaben
self._handle_cookie_banner(page)
# "Konto erstellen" Button klicken
logger.info("Suche 'Konto erstellen' Button")
try:
# Versuche verschiedene Selektoren
create_button_clicked = False
# Versuche CSS Selektor
if page.locator(selectors.CREATE_ACCOUNT_BUTTON).count() > 0:
page.click(selectors.CREATE_ACCOUNT_BUTTON)
create_button_clicked = True
logger.info("Button mit CSS Selektor gefunden und geklickt")
# Versuche XPath wenn CSS nicht funktioniert
elif page.locator(selectors.CREATE_ACCOUNT_BUTTON_XPATH).count() > 0:
page.click(selectors.CREATE_ACCOUNT_BUTTON_XPATH)
create_button_clicked = True
logger.info("Button mit XPath gefunden und geklickt")
# Versuche alternativen Selektor
elif page.locator(selectors.CREATE_ACCOUNT_BUTTON_ALTERNATE).count() > 0:
page.click(selectors.CREATE_ACCOUNT_BUTTON_ALTERNATE)
create_button_clicked = True
logger.info("Button mit alternativem Selektor gefunden und geklickt")
if not create_button_clicked:
raise Exception("'Konto erstellen' Button nicht gefunden")
time.sleep(random.uniform(2, 3))
except Exception as e:
logger.error(f"Fehler beim Klicken des 'Konto erstellen' Buttons: {e}")
self.ui_helper.take_screenshot("create_account_button_error")
raise
# Registrierungsformular ausfüllen
registration_result = self.registration.fill_registration_form(account_data)
if not registration_result["success"]:
return registration_result
# Telefonnummer-Verifizierung
verification_result = self.verification.handle_phone_verification(account_data)
if not verification_result["success"]:
return verification_result
# Erfolg
logger.info("VK Account-Registrierung erfolgreich abgeschlossen")
return {
"success": True,
"username": account_data.get("username"),
"password": account_data.get("password"),
"email": account_data.get("email"),
"phone": account_data.get("phone"),
"message": "Account erfolgreich erstellt"
}
except Exception as e:
logger.error(f"Fehler bei der VK-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 VK-Account an
"""
try:
logger.info(f"Starte VK 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 VK Login: {str(e)}")
return {
"success": False,
"error": str(e),
"message": f"Login fehlgeschlagen: {str(e)}"
}
finally:
self._close_browser()
def _handle_cookie_banner(self, page: Page):
"""
Handhabt Cookie-Banner falls vorhanden
"""
try:
if page.locator(selectors.COOKIE_BANNER).count() > 0:
logger.info("Cookie Banner gefunden")
if page.locator(selectors.COOKIE_ACCEPT_BUTTON).count() > 0:
page.click(selectors.COOKIE_ACCEPT_BUTTON)
logger.info("Cookie Banner akzeptiert")
time.sleep(random.uniform(1, 2))
except Exception as e:
logger.warning(f"Fehler beim Handhaben des Cookie Banners: {e}")
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 _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")

127
social_networks/vk/vk_login.py Normale Datei
Datei anzeigen

@ -0,0 +1,127 @@
"""
VK Login - Handhabt den Login-Prozess
"""
import logging
import time
import random
from typing import Dict
from playwright.sync_api import Page
from social_networks.vk import vk_selectors as selectors
from social_networks.vk.vk_ui_helper import VKUIHelper
logger = logging.getLogger("vk_login")
class VKLogin:
"""
Handhabt den VK Login-Prozess
"""
def __init__(self, page: Page, ui_helper: VKUIHelper, screenshots_dir: str = None, save_screenshots: bool = True):
"""
Initialisiert den Login Handler
"""
self.page = page
self.ui_helper = ui_helper
self.screenshots_dir = screenshots_dir
self.save_screenshots = save_screenshots
def login(self, username: str, password: str) -> Dict[str, any]:
"""
Führt den Login durch
"""
try:
logger.info(f"Starte VK Login für {username}")
# Navigiere zur Login-Seite
self.page.goto(selectors.LOGIN_URL, wait_until="domcontentloaded")
time.sleep(random.uniform(2, 3))
self.ui_helper.take_screenshot("login_page")
# Email/Telefonnummer eingeben
if self.ui_helper.wait_for_element(selectors.LOGIN_EMAIL_INPUT, timeout=10000):
logger.info("Gebe Benutzernamen ein")
self.ui_helper.type_with_delay(selectors.LOGIN_EMAIL_INPUT, username)
time.sleep(random.uniform(0.5, 1))
# Passwort eingeben
if self.ui_helper.wait_for_element(selectors.LOGIN_PASSWORD_INPUT, timeout=5000):
logger.info("Gebe Passwort ein")
self.ui_helper.type_with_delay(selectors.LOGIN_PASSWORD_INPUT, password)
time.sleep(random.uniform(0.5, 1))
# Screenshot vor dem Login
self.ui_helper.take_screenshot("login_form_filled")
# Login Button klicken
if self.ui_helper.wait_for_element(selectors.LOGIN_SUBMIT_BUTTON, timeout=5000):
logger.info("Klicke auf Login Button")
self.ui_helper.click_with_retry(selectors.LOGIN_SUBMIT_BUTTON)
# Warte auf Navigation
self.ui_helper.wait_for_navigation()
time.sleep(random.uniform(2, 3))
# Prüfe ob Login erfolgreich war
if self._check_login_success():
logger.info("Login erfolgreich")
self.ui_helper.take_screenshot("login_success")
return {
"success": True,
"message": "Login erfolgreich"
}
else:
error_msg = self._get_error_message()
logger.error(f"Login fehlgeschlagen: {error_msg}")
self.ui_helper.take_screenshot("login_failed")
return {
"success": False,
"error": error_msg,
"message": f"Login fehlgeschlagen: {error_msg}"
}
except Exception as e:
logger.error(f"Fehler beim Login: {e}")
self.ui_helper.take_screenshot("login_error")
return {
"success": False,
"error": str(e),
"message": f"Login fehlgeschlagen: {str(e)}"
}
def _check_login_success(self) -> bool:
"""
Prüft ob der Login erfolgreich war
"""
try:
# Prüfe ob wir auf der Hauptseite sind
current_url = self.page.url
if "feed" in current_url or "id" in current_url:
return True
# Prüfe ob Login-Formular noch sichtbar ist
if self.ui_helper.is_element_visible(selectors.LOGIN_EMAIL_INPUT):
return False
# Prüfe auf Fehlermeldung
if self.ui_helper.is_element_visible(selectors.ERROR_MESSAGE):
return False
return True
except Exception as e:
logger.warning(f"Fehler bei der Login-Prüfung: {e}")
return False
def _get_error_message(self) -> str:
"""
Holt die Fehlermeldung falls vorhanden
"""
try:
if self.ui_helper.is_element_visible(selectors.ERROR_MESSAGE):
return self.ui_helper.get_element_text(selectors.ERROR_MESSAGE) or "Unbekannter Fehler"
return "Login fehlgeschlagen"
except:
return "Unbekannter Fehler"

Datei anzeigen

@ -0,0 +1,132 @@
"""
VK Registrierung - Handhabt den Registrierungsprozess
"""
import logging
import time
import random
from typing import Dict
from playwright.sync_api import Page
from social_networks.vk import vk_selectors as selectors
from social_networks.vk.vk_ui_helper import VKUIHelper
logger = logging.getLogger("vk_registration")
class VKRegistration:
"""
Handhabt den VK Registrierungsprozess
"""
def __init__(self, page: Page, ui_helper: VKUIHelper, screenshots_dir: str = None, save_screenshots: bool = True):
"""
Initialisiert die Registrierung
"""
self.page = page
self.ui_helper = ui_helper
self.screenshots_dir = screenshots_dir
self.save_screenshots = save_screenshots
def fill_registration_form(self, account_data: Dict[str, str]) -> Dict[str, any]:
"""
Füllt das Registrierungsformular aus
"""
try:
logger.info("Fülle VK Registrierungsformular aus")
# Warte auf Registrierungsseite
time.sleep(random.uniform(2, 3))
self.ui_helper.take_screenshot("registration_form")
# Vorname eingeben
if self.ui_helper.wait_for_element(selectors.REGISTRATION_FIRST_NAME, timeout=10000):
first_name = account_data.get("first_name", "")
logger.info(f"Gebe Vorname ein: {first_name}")
self.ui_helper.type_with_delay(selectors.REGISTRATION_FIRST_NAME, first_name)
time.sleep(random.uniform(0.5, 1))
# Nachname eingeben
if self.ui_helper.wait_for_element(selectors.REGISTRATION_LAST_NAME, timeout=5000):
last_name = account_data.get("last_name", "")
logger.info(f"Gebe Nachname ein: {last_name}")
self.ui_helper.type_with_delay(selectors.REGISTRATION_LAST_NAME, last_name)
time.sleep(random.uniform(0.5, 1))
# Geburtstag auswählen
self._select_birthday(account_data)
# Geschlecht auswählen
self._select_gender(account_data)
# Screenshot vor dem Fortfahren
self.ui_helper.take_screenshot("registration_form_filled")
# Fortfahren Button klicken
if self.ui_helper.wait_for_element(selectors.REGISTRATION_CONTINUE_BUTTON, timeout=5000):
logger.info("Klicke auf Fortfahren")
self.ui_helper.click_with_retry(selectors.REGISTRATION_CONTINUE_BUTTON)
time.sleep(random.uniform(2, 3))
return {
"success": True,
"message": "Registrierungsformular ausgefüllt"
}
except Exception as e:
logger.error(f"Fehler beim Ausfüllen des Registrierungsformulars: {e}")
self.ui_helper.take_screenshot("registration_form_error")
return {
"success": False,
"error": str(e),
"message": f"Fehler beim Ausfüllen des Formulars: {str(e)}"
}
def _select_birthday(self, account_data: Dict[str, str]):
"""
Wählt das Geburtsdatum aus
"""
try:
birthday = account_data.get("birthday", "1990-01-15")
year, month, day = birthday.split("-")
# Tag auswählen
if self.ui_helper.wait_for_element(selectors.REGISTRATION_BIRTHDAY_DAY, timeout=5000):
logger.info(f"Wähle Geburtstag: {day}")
self.ui_helper.select_dropdown_option(selectors.REGISTRATION_BIRTHDAY_DAY, day.lstrip("0"))
time.sleep(random.uniform(0.3, 0.6))
# Monat auswählen
if self.ui_helper.wait_for_element(selectors.REGISTRATION_BIRTHDAY_MONTH, timeout=5000):
logger.info(f"Wähle Geburtsmonat: {month}")
self.ui_helper.select_dropdown_option(selectors.REGISTRATION_BIRTHDAY_MONTH, month.lstrip("0"))
time.sleep(random.uniform(0.3, 0.6))
# Jahr auswählen
if self.ui_helper.wait_for_element(selectors.REGISTRATION_BIRTHDAY_YEAR, timeout=5000):
logger.info(f"Wähle Geburtsjahr: {year}")
self.ui_helper.select_dropdown_option(selectors.REGISTRATION_BIRTHDAY_YEAR, year)
time.sleep(random.uniform(0.3, 0.6))
except Exception as e:
logger.warning(f"Fehler bei der Geburtsdatum-Auswahl: {e}")
def _select_gender(self, account_data: Dict[str, str]):
"""
Wählt das Geschlecht aus
"""
try:
gender = account_data.get("gender", "male").lower()
if gender == "female":
if self.ui_helper.wait_for_element(selectors.REGISTRATION_GENDER_FEMALE, timeout=5000):
logger.info("Wähle Geschlecht: Weiblich")
self.ui_helper.check_radio_button(selectors.REGISTRATION_GENDER_FEMALE)
else:
if self.ui_helper.wait_for_element(selectors.REGISTRATION_GENDER_MALE, timeout=5000):
logger.info("Wähle Geschlecht: Männlich")
self.ui_helper.check_radio_button(selectors.REGISTRATION_GENDER_MALE)
time.sleep(random.uniform(0.3, 0.6))
except Exception as e:
logger.warning(f"Fehler bei der Geschlechtsauswahl: {e}")

Datei anzeigen

@ -0,0 +1,51 @@
"""
VK UI Selektoren und URLs
"""
# URLs
BASE_URL = "https://vk.com/"
REGISTRATION_URL = "https://vk.com/join"
LOGIN_URL = "https://vk.com/login"
# Startseite
CREATE_ACCOUNT_BUTTON = "span.vkuiButton__content:has-text('Konto erstellen')"
CREATE_ACCOUNT_BUTTON_XPATH = "//span[@class='vkuiButton__content' and text()='Konto erstellen']"
CREATE_ACCOUNT_BUTTON_ALTERNATE = "button:has-text('Konto erstellen')"
# Login Seite
LOGIN_EMAIL_INPUT = "input[name='email']"
LOGIN_PASSWORD_INPUT = "input[name='password']"
LOGIN_SUBMIT_BUTTON = "button[type='submit']"
# Registrierungsformular
REGISTRATION_FIRST_NAME = "input[name='first_name']"
REGISTRATION_LAST_NAME = "input[name='last_name']"
REGISTRATION_BIRTHDAY_DAY = "select[name='bday']"
REGISTRATION_BIRTHDAY_MONTH = "select[name='bmonth']"
REGISTRATION_BIRTHDAY_YEAR = "select[name='byear']"
REGISTRATION_GENDER_MALE = "input[value='2']"
REGISTRATION_GENDER_FEMALE = "input[value='1']"
REGISTRATION_CONTINUE_BUTTON = "button[type='submit']"
# Telefonnummer Verifizierung
PHONE_INPUT = "input[name='phone']"
PHONE_COUNTRY_CODE = "div.PhoneInput__countryCode"
PHONE_SUBMIT_BUTTON = "button[type='submit']"
# SMS Verifizierung
SMS_CODE_INPUT = "input[name='code']"
SMS_SUBMIT_BUTTON = "button[type='submit']"
SMS_RESEND_LINK = "a:has-text('Code erneut senden')"
# Captcha
CAPTCHA_IMAGE = "img.vkc__Captcha__image"
CAPTCHA_INPUT = "input[name='captcha']"
# Fehler- und Erfolgsmeldungen
ERROR_MESSAGE = "div.error"
SUCCESS_MESSAGE = "div.success"
PHONE_ERROR = "div.phone_error"
# Cookies Banner
COOKIE_ACCEPT_BUTTON = "button:has-text('Akzeptieren')"
COOKIE_BANNER = "div[class*='cookie']"

Datei anzeigen

@ -0,0 +1,149 @@
"""
VK UI Helper - Hilfsfunktionen für UI-Interaktionen
"""
import logging
import time
import random
import os
from typing import Optional
from playwright.sync_api import Page, ElementHandle
logger = logging.getLogger("vk_ui_helper")
class VKUIHelper:
"""
Hilfsklasse für VK UI-Interaktionen
"""
def __init__(self, page: Page, screenshots_dir: str = None, save_screenshots: bool = True):
"""
Initialisiert den UI Helper
"""
self.page = page
self.screenshots_dir = screenshots_dir or "logs/screenshots"
self.save_screenshots = save_screenshots
# Screenshot-Verzeichnis erstellen falls nötig
if self.save_screenshots and not os.path.exists(self.screenshots_dir):
os.makedirs(self.screenshots_dir)
def take_screenshot(self, name: str) -> Optional[str]:
"""
Erstellt einen Screenshot
"""
if not self.save_screenshots:
return None
try:
timestamp = int(time.time())
filename = f"{name}_{timestamp}.png"
filepath = os.path.join(self.screenshots_dir, filename)
self.page.screenshot(path=filepath)
logger.debug(f"Screenshot gespeichert: {filepath}")
return filepath
except Exception as e:
logger.warning(f"Fehler beim Erstellen des Screenshots: {e}")
return None
def wait_for_element(self, selector: str, timeout: int = 30000) -> bool:
"""
Wartet auf ein Element
"""
try:
self.page.wait_for_selector(selector, timeout=timeout)
return True
except Exception as e:
logger.error(f"Element {selector} nicht gefunden nach {timeout}ms")
return False
def type_with_delay(self, selector: str, text: str, delay_min: float = 0.05, delay_max: float = 0.15):
"""
Tippt Text mit menschenähnlicher Verzögerung
"""
try:
element = self.page.locator(selector)
element.click()
for char in text:
element.type(char)
time.sleep(random.uniform(delay_min, delay_max))
except Exception as e:
logger.error(f"Fehler beim Tippen in {selector}: {e}")
raise
def click_with_retry(self, selector: str, max_attempts: int = 3) -> bool:
"""
Klickt auf ein Element mit Wiederholungsversuchen
"""
for attempt in range(max_attempts):
try:
self.page.click(selector)
return True
except Exception as e:
logger.warning(f"Klick-Versuch {attempt + 1} fehlgeschlagen: {e}")
if attempt < max_attempts - 1:
time.sleep(random.uniform(1, 2))
return False
def scroll_to_element(self, selector: str):
"""
Scrollt zu einem Element
"""
try:
self.page.locator(selector).scroll_into_view_if_needed()
time.sleep(random.uniform(0.5, 1))
except Exception as e:
logger.warning(f"Fehler beim Scrollen zu {selector}: {e}")
def is_element_visible(self, selector: str) -> bool:
"""
Prüft ob ein Element sichtbar ist
"""
try:
return self.page.locator(selector).is_visible()
except:
return False
def get_element_text(self, selector: str) -> Optional[str]:
"""
Holt den Text eines Elements
"""
try:
return self.page.locator(selector).text_content()
except Exception as e:
logger.warning(f"Fehler beim Lesen des Texts von {selector}: {e}")
return None
def select_dropdown_option(self, selector: str, value: str):
"""
Wählt eine Option aus einem Dropdown
"""
try:
self.page.select_option(selector, value)
time.sleep(random.uniform(0.3, 0.6))
except Exception as e:
logger.error(f"Fehler beim Auswählen von {value} in {selector}: {e}")
raise
def check_radio_button(self, selector: str):
"""
Wählt einen Radio Button aus
"""
try:
self.page.check(selector)
time.sleep(random.uniform(0.2, 0.4))
except Exception as e:
logger.error(f"Fehler beim Auswählen des Radio Buttons {selector}: {e}")
raise
def wait_for_navigation(self, timeout: int = 30000):
"""
Wartet auf Navigation
"""
try:
self.page.wait_for_load_state("networkidle", timeout=timeout)
except Exception as e:
logger.warning(f"Navigation-Timeout nach {timeout}ms: {e}")

Datei anzeigen

@ -0,0 +1,89 @@
"""
VK Utils - Utility-Funktionen für VK
"""
import logging
import random
import string
from typing import Optional
logger = logging.getLogger("vk_utils")
class VKUtils:
"""
Utility-Funktionen für VK
"""
@staticmethod
def generate_vk_username(first_name: str, last_name: str) -> str:
"""
Generiert einen VK-kompatiblen Benutzernamen
"""
# VK verwendet normalerweise id123456789 Format
# Aber für die URL kann man einen benutzerdefinierten Namen verwenden
base = f"{first_name.lower()}{last_name.lower()}"
# Entferne Sonderzeichen
base = ''.join(c for c in base if c.isalnum())
# Füge zufällige Zahlen hinzu
random_suffix = ''.join(random.choices(string.digits, k=random.randint(2, 4)))
return f"{base}{random_suffix}"
@staticmethod
def format_phone_number(phone: str, country_code: str = "+7") -> str:
"""
Formatiert eine Telefonnummer für VK
VK ist primär in Russland, daher Standard +7
"""
# Entferne alle nicht-numerischen Zeichen
phone_digits = ''.join(c for c in phone if c.isdigit())
# Wenn die Nummer bereits mit Ländercode beginnt
if phone.startswith("+"):
return phone
# Füge Ländercode hinzu
return f"{country_code}{phone_digits}"
@staticmethod
def is_valid_vk_password(password: str) -> bool:
"""
Prüft ob ein Passwort den VK-Anforderungen entspricht
- Mindestens 6 Zeichen
- Enthält Buchstaben und Zahlen
"""
if len(password) < 6:
return False
has_letter = any(c.isalpha() for c in password)
has_digit = any(c.isdigit() for c in password)
return has_letter and has_digit
@staticmethod
def generate_vk_password(length: int = 12) -> str:
"""
Generiert ein VK-kompatibles Passwort
"""
# Stelle sicher dass Buchstaben und Zahlen enthalten sind
password_chars = []
# Mindestens 2 Kleinbuchstaben
password_chars.extend(random.choices(string.ascii_lowercase, k=2))
# Mindestens 2 Großbuchstaben
password_chars.extend(random.choices(string.ascii_uppercase, k=2))
# Mindestens 2 Zahlen
password_chars.extend(random.choices(string.digits, k=2))
# Fülle mit zufälligen Zeichen auf
remaining_length = length - len(password_chars)
all_chars = string.ascii_letters + string.digits
password_chars.extend(random.choices(all_chars, k=remaining_length))
# Mische die Zeichen
random.shuffle(password_chars)
return ''.join(password_chars)

Datei anzeigen

@ -0,0 +1,186 @@
"""
VK Verification - Handhabt die Telefon-Verifizierung
"""
import logging
import time
import random
from typing import Dict, Optional
from playwright.sync_api import Page
from social_networks.vk import vk_selectors as selectors
from social_networks.vk.vk_ui_helper import VKUIHelper
from utils.email_handler import EmailHandler
logger = logging.getLogger("vk_verification")
class VKVerification:
"""
Handhabt die VK Telefon-Verifizierung
"""
def __init__(self, page: Page, ui_helper: VKUIHelper, email_handler: EmailHandler = None,
screenshots_dir: str = None, save_screenshots: bool = True):
"""
Initialisiert den Verification Handler
"""
self.page = page
self.ui_helper = ui_helper
self.email_handler = email_handler
self.screenshots_dir = screenshots_dir
self.save_screenshots = save_screenshots
def handle_phone_verification(self, account_data: Dict[str, str]) -> Dict[str, any]:
"""
Handhabt die Telefonnummer-Verifizierung
"""
try:
logger.info("Starte Telefon-Verifizierung")
# Warte auf Telefonnummer-Eingabefeld
if not self.ui_helper.wait_for_element(selectors.PHONE_INPUT, timeout=10000):
logger.error("Telefonnummer-Eingabefeld nicht gefunden")
return {
"success": False,
"error": "Telefonnummer-Eingabefeld nicht gefunden",
"message": "Verifizierung fehlgeschlagen"
}
self.ui_helper.take_screenshot("phone_verification_page")
# Telefonnummer eingeben
phone = account_data.get("phone", "")
if not phone:
logger.error("Keine Telefonnummer in account_data vorhanden")
return {
"success": False,
"error": "Keine Telefonnummer angegeben",
"message": "Telefonnummer erforderlich"
}
logger.info(f"Gebe Telefonnummer ein: {phone}")
# Prüfe ob Ländercode-Auswahl vorhanden ist
if self.ui_helper.is_element_visible(selectors.PHONE_COUNTRY_CODE):
# TODO: Ländercode auswählen falls nötig
pass
# Telefonnummer eingeben
self.ui_helper.type_with_delay(selectors.PHONE_INPUT, phone)
time.sleep(random.uniform(1, 2))
# Screenshot vor dem Absenden
self.ui_helper.take_screenshot("phone_entered")
# Absenden
if self.ui_helper.wait_for_element(selectors.PHONE_SUBMIT_BUTTON, timeout=5000):
logger.info("Sende Telefonnummer ab")
self.ui_helper.click_with_retry(selectors.PHONE_SUBMIT_BUTTON)
time.sleep(random.uniform(3, 5))
# Warte auf SMS-Code Eingabefeld
if self.ui_helper.wait_for_element(selectors.SMS_CODE_INPUT, timeout=15000):
logger.info("SMS-Code Eingabefeld gefunden")
self.ui_helper.take_screenshot("sms_code_page")
# Hier würde normalerweise der SMS-Code abgerufen werden
# Für Demo-Zwecke verwenden wir einen Platzhalter
sms_code = self._get_sms_code(phone)
if not sms_code:
logger.error("Kein SMS-Code erhalten")
return {
"success": False,
"error": "Kein SMS-Code erhalten",
"message": "SMS-Verifizierung fehlgeschlagen"
}
# SMS-Code eingeben
logger.info(f"Gebe SMS-Code ein: {sms_code}")
self.ui_helper.type_with_delay(selectors.SMS_CODE_INPUT, sms_code)
time.sleep(random.uniform(1, 2))
# Code absenden
if self.ui_helper.wait_for_element(selectors.SMS_SUBMIT_BUTTON, timeout=5000):
logger.info("Sende SMS-Code ab")
self.ui_helper.click_with_retry(selectors.SMS_SUBMIT_BUTTON)
time.sleep(random.uniform(3, 5))
# Prüfe auf Erfolg
if self._check_verification_success():
logger.info("Telefon-Verifizierung erfolgreich")
self.ui_helper.take_screenshot("verification_success")
return {
"success": True,
"message": "Verifizierung erfolgreich"
}
else:
error_msg = self._get_verification_error()
logger.error(f"Verifizierung fehlgeschlagen: {error_msg}")
return {
"success": False,
"error": error_msg,
"message": f"Verifizierung fehlgeschlagen: {error_msg}"
}
else:
logger.error("SMS-Code Eingabefeld nicht gefunden")
return {
"success": False,
"error": "SMS-Code Eingabefeld nicht gefunden",
"message": "Verifizierung fehlgeschlagen"
}
except Exception as e:
logger.error(f"Fehler bei der Telefon-Verifizierung: {e}")
self.ui_helper.take_screenshot("verification_error")
return {
"success": False,
"error": str(e),
"message": f"Verifizierung fehlgeschlagen: {str(e)}"
}
def _get_sms_code(self, phone: str) -> Optional[str]:
"""
Ruft den SMS-Code ab
TODO: Implementierung für echte SMS-Code Abfrage
"""
logger.warning("SMS-Code Abruf noch nicht implementiert - verwende Platzhalter")
# In einer echten Implementierung würde hier der SMS-Code
# von einem SMS-Service abgerufen werden
return "123456" # Platzhalter
def _check_verification_success(self) -> bool:
"""
Prüft ob die Verifizierung erfolgreich war
"""
try:
# Prüfe ob wir weitergeleitet wurden
current_url = self.page.url
if "welcome" in current_url or "feed" in current_url:
return True
# Prüfe ob SMS-Code Feld noch sichtbar ist
if self.ui_helper.is_element_visible(selectors.SMS_CODE_INPUT):
return False
# Prüfe auf Fehlermeldung
if self.ui_helper.is_element_visible(selectors.PHONE_ERROR):
return False
return True
except Exception as e:
logger.warning(f"Fehler bei der Verifizierungs-Prüfung: {e}")
return False
def _get_verification_error(self) -> str:
"""
Holt die Fehlermeldung falls vorhanden
"""
try:
if self.ui_helper.is_element_visible(selectors.PHONE_ERROR):
return self.ui_helper.get_element_text(selectors.PHONE_ERROR) or "Verifizierung fehlgeschlagen"
return "Verifizierung fehlgeschlagen"
except:
return "Unbekannter Fehler"

Datei anzeigen

@ -0,0 +1,37 @@
"""
VK Workflow - Workflow-Definitionen für VK
"""
# Workflow-Schritte für VK
REGISTRATION_WORKFLOW = [
"navigate_to_homepage",
"click_create_account",
"fill_registration_form",
"handle_phone_verification",
"complete_profile",
"verify_account_creation"
]
LOGIN_WORKFLOW = [
"navigate_to_login",
"enter_credentials",
"handle_2fa_if_needed",
"verify_login_success"
]
# Timeouts in Sekunden
TIMEOUTS = {
"page_load": 30,
"element_wait": 10,
"verification_wait": 60,
"sms_wait": 120
}
# Fehler-Nachrichten
ERROR_MESSAGES = {
"phone_already_used": "Diese Telefonnummer wird bereits verwendet",
"invalid_phone": "Ungültige Telefonnummer",
"invalid_code": "Ungültiger Verifizierungscode",
"too_many_attempts": "Zu viele Versuche",
"account_blocked": "Account wurde blockiert"
}