Dieser Commit ist enthalten in:
Claude Project Manager
2025-07-03 21:11:05 +02:00
Commit 08ed938105
239 geänderte Dateien mit 21554 neuen und 0 gelöschten Zeilen

Datei anzeigen

@ -0,0 +1,132 @@
"""
Basis-Controller für Plattform-spezifische Funktionalität.
"""
import logging
from PyQt5.QtCore import QObject
from views.tabs.generator_tab import GeneratorTab
from views.tabs.accounts_tab import AccountsTab
from views.tabs.settings_tab import SettingsTab
class BasePlatformController(QObject):
"""Basis-Controller-Klasse für Plattformspezifische Logik."""
def __init__(self, platform_name, db_manager, proxy_rotator, email_handler, language_manager=None):
super().__init__()
self.platform_name = platform_name
self.logger = logging.getLogger(f"{platform_name.lower()}_controller")
# Modelle
self.db_manager = db_manager
self.proxy_rotator = proxy_rotator
self.email_handler = email_handler
self.language_manager = language_manager
# Tabs
self._generator_tab = None
self._accounts_tab = None
self._settings_tab = None
# Plattformspezifische Initialisierungen
self.init_platform()
def init_platform(self):
"""
Initialisiert plattformspezifische Komponenten.
Diese Methode sollte von Unterklassen überschrieben werden.
"""
pass
def get_generator_tab(self):
"""Gibt den Generator-Tab zurück oder erstellt ihn bei Bedarf."""
if not self._generator_tab:
self._generator_tab = self.create_generator_tab()
return self._generator_tab
def get_accounts_tab(self):
"""Gibt den Accounts-Tab zurück oder erstellt ihn bei Bedarf."""
if not self._accounts_tab:
self._accounts_tab = self.create_accounts_tab()
return self._accounts_tab
def get_settings_tab(self):
"""Gibt den Settings-Tab zurück oder erstellt ihn bei Bedarf."""
if not self._settings_tab:
self._settings_tab = self.create_settings_tab()
return self._settings_tab
def create_generator_tab(self):
"""
Erstellt den Generator-Tab.
Diese Methode sollte von Unterklassen überschrieben werden.
"""
return GeneratorTab(self.platform_name, self.language_manager)
def create_accounts_tab(self):
"""
Erstellt den Accounts-Tab.
Diese Methode sollte von Unterklassen überschrieben werden.
"""
return AccountsTab(self.platform_name, self.db_manager, self.language_manager)
def create_settings_tab(self):
"""
Erstellt den Settings-Tab.
Diese Methode sollte von Unterklassen überschrieben werden.
"""
return SettingsTab(
self.platform_name,
self.proxy_rotator,
self.email_handler,
self.language_manager
)
def start_account_creation(self, params):
"""
Startet die Account-Erstellung.
Diese Methode sollte von Unterklassen überschrieben werden.
Args:
params: Parameter für die Account-Erstellung
"""
self.logger.info(f"Account-Erstellung für {self.platform_name} gestartet")
# In Unterklassen implementieren
def validate_inputs(self, inputs):
"""
Validiert die Eingaben für die Account-Erstellung.
Args:
inputs: Eingaben für die Account-Erstellung
Returns:
(bool, str): (Ist gültig, Fehlermeldung falls nicht gültig)
"""
# Basis-Validierungen
if not inputs.get("full_name"):
return False, "Bitte geben Sie einen vollständigen Namen ein."
# Alter prüfen
age_text = inputs.get("age_text", "")
if not age_text:
return False, "Bitte geben Sie ein Alter ein."
# Alter muss eine Zahl sein
try:
age = int(age_text)
inputs["age"] = age # Füge das konvertierte Alter zu den Parametern hinzu
except ValueError:
return False, "Das Alter muss eine ganze Zahl sein."
# Alter-Bereich prüfen
if age < 13 or age > 99:
return False, "Das Alter muss zwischen 13 und 99 liegen."
# Telefonnummer prüfen, falls erforderlich
if inputs.get("registration_method") == "phone" and not inputs.get("phone_number"):
return False, "Telefonnummer erforderlich für Registrierung via Telefon."
return True, ""

Datei anzeigen

@ -0,0 +1,275 @@
"""
Controller für Instagram-spezifische Funktionalität.
Mit TextSimilarity-Integration für robusteres UI-Element-Matching.
"""
import logging
import time
import random
from PyQt5.QtCore import QThread, pyqtSignal, QObject
from controllers.platform_controllers.base_controller import BasePlatformController
from views.tabs.generator_tab import GeneratorTab
from views.tabs.accounts_tab import AccountsTab
from views.tabs.settings_tab import SettingsTab
from social_networks.instagram.instagram_automation import InstagramAutomation
from utils.text_similarity import TextSimilarity
logger = logging.getLogger("instagram_controller")
class InstagramWorkerThread(QThread):
"""Thread für die Instagram-Account-Erstellung."""
# Signale
update_signal = pyqtSignal(str)
log_signal = pyqtSignal(str)
progress_signal = pyqtSignal(int)
finished_signal = pyqtSignal(dict)
error_signal = pyqtSignal(str)
def __init__(self, params):
super().__init__()
self.params = params
self.running = True
# TextSimilarity für robustes Fehler-Matching
self.text_similarity = TextSimilarity(default_threshold=0.7)
# Fehler-Patterns für robustes Fehler-Matching
self.error_patterns = [
"Fehler", "Error", "Fehlgeschlagen", "Failed", "Problem", "Issue",
"Nicht möglich", "Not possible", "Bitte versuchen Sie es erneut",
"Please try again", "Konnte nicht", "Could not", "Timeout"
]
def run(self):
"""Führt die Account-Erstellung aus."""
try:
self.log_signal.emit("Instagram-Account-Erstellung gestartet...")
self.progress_signal.emit(10)
# Instagram-Automation initialisieren
automation = InstagramAutomation(
headless=self.params.get("headless", False),
use_proxy=self.params.get("use_proxy", False),
proxy_type=self.params.get("proxy_type"),
save_screenshots=True,
debug=self.params.get("debug", False),
email_domain=self.params.get("email_domain", "z5m7q9dk3ah2v1plx6ju.com")
)
self.update_signal.emit("Instagram-Automation initialisiert")
self.progress_signal.emit(20)
# Account registrieren
self.log_signal.emit(f"Registriere Account für: {self.params['full_name']}")
registration_method = self.params.get("registration_method", "email")
phone_number = self.params.get("phone_number")
# Account registrieren
result = automation.register_account(
full_name=self.params["full_name"],
age=self.params["age"],
registration_method=registration_method,
phone_number=phone_number,
**self.params.get("additional_params", {})
)
self.progress_signal.emit(100)
if result["success"]:
self.log_signal.emit("Account erfolgreich erstellt!")
self.finished_signal.emit(result)
else:
# Robuste Fehlerbehandlung mit TextSimilarity
error_msg = result.get("error", "Unbekannter Fehler")
# Versuche, Fehler nutzerfreundlicher zu interpretieren
user_friendly_error = self._interpret_error(error_msg)
self.log_signal.emit(f"Fehler bei der Account-Erstellung: {user_friendly_error}")
self.error_signal.emit(user_friendly_error)
except Exception as e:
logger.error(f"Fehler im Worker-Thread: {e}")
self.log_signal.emit(f"Schwerwiegender Fehler: {str(e)}")
self.error_signal.emit(str(e))
self.progress_signal.emit(0)
def _interpret_error(self, error_msg: str) -> str:
"""
Interpretiert Fehlermeldungen und gibt eine benutzerfreundlichere Version zurück.
Verwendet TextSimilarity für robusteres Fehler-Matching.
Args:
error_msg: Die ursprüngliche Fehlermeldung
Returns:
str: Benutzerfreundliche Fehlermeldung
"""
# Bekannte Fehlermuster und deren Interpretationen
error_interpretations = {
"captcha": "Instagram hat einen Captcha-Test angefordert. Versuchen Sie es später erneut oder nutzen Sie einen anderen Proxy.",
"verification": "Es gab ein Problem mit der Verifizierung des Accounts. Bitte prüfen Sie die E-Mail-Einstellungen.",
"proxy": "Problem mit der Proxy-Verbindung. Bitte prüfen Sie Ihre Proxy-Einstellungen.",
"timeout": "Zeitüberschreitung bei der Verbindung. Bitte überprüfen Sie Ihre Internetverbindung.",
"username": "Der gewählte Benutzername ist bereits vergeben oder nicht zulässig.",
"password": "Das Passwort erfüllt nicht die Anforderungen von Instagram.",
"email": "Die E-Mail-Adresse konnte nicht verwendet werden. Bitte nutzen Sie eine andere E-Mail-Domain.",
"phone": "Die Telefonnummer konnte nicht für die Registrierung verwendet werden."
}
# Versuche, den Fehler zu kategorisieren
for pattern, interpretation in error_interpretations.items():
for error_term in self.error_patterns:
if (pattern in error_msg.lower() or
self.text_similarity.is_similar(error_term, error_msg, threshold=0.7)):
return interpretation
# Fallback: Originale Fehlermeldung zurückgeben
return error_msg
def stop(self):
"""Stoppt den Thread."""
self.running = False
self.terminate()
class InstagramController(BasePlatformController):
"""Controller für Instagram-spezifische Funktionalität."""
def __init__(self, db_manager, proxy_rotator, email_handler, language_manager=None):
super().__init__("Instagram", db_manager, proxy_rotator, email_handler, language_manager)
self.worker_thread = None
# TextSimilarity für robustes UI-Element-Matching
self.text_similarity = TextSimilarity(default_threshold=0.75)
def create_generator_tab(self):
"""Erstellt den Instagram-Generator-Tab."""
generator_tab = GeneratorTab(self.platform_name, self.language_manager)
# Instagram-spezifische Anpassungen
# Diese Methode überschreiben, wenn spezifische Anpassungen benötigt werden
# Signale verbinden
generator_tab.start_requested.connect(self.start_account_creation)
generator_tab.stop_requested.connect(self.stop_account_creation)
return generator_tab
def start_account_creation(self, params):
"""Startet die Instagram-Account-Erstellung."""
super().start_account_creation(params)
# Validiere Eingaben
is_valid, error_msg = self.validate_inputs(params)
if not is_valid:
self.get_generator_tab().show_error(error_msg)
return
# UI aktualisieren
generator_tab = self.get_generator_tab()
generator_tab.set_running(True)
generator_tab.clear_log()
generator_tab.set_progress(0)
# Worker-Thread starten
self.worker_thread = InstagramWorkerThread(params)
self.worker_thread.update_signal.connect(lambda msg: generator_tab.set_status(msg))
self.worker_thread.log_signal.connect(lambda msg: generator_tab.add_log(msg))
self.worker_thread.error_signal.connect(lambda msg: (generator_tab.show_error(msg), generator_tab.set_running(False)))
self.worker_thread.finished_signal.connect(lambda result: self.handle_account_created(result))
self.worker_thread.progress_signal.connect(lambda value: generator_tab.set_progress(value))
self.worker_thread.start()
def stop_account_creation(self):
"""Stoppt die Instagram-Account-Erstellung."""
if self.worker_thread and self.worker_thread.isRunning():
self.worker_thread.stop()
generator_tab = self.get_generator_tab()
generator_tab.add_log("Account-Erstellung wurde abgebrochen")
generator_tab.set_running(False)
generator_tab.set_progress(0)
def handle_account_created(self, result):
"""Verarbeitet erfolgreich erstellte Accounts."""
generator_tab = self.get_generator_tab()
generator_tab.set_running(False)
# Account-Daten aus dem Ergebnis holen
account_data = result.get("account_data", {})
# Account-Erfolgsereignis auslösen
generator_tab.account_created.emit(self.platform_name, account_data)
# Account in der Datenbank speichern
self.save_account_to_db(account_data)
def save_account_to_db(self, account_data):
"""Speichert einen erstellten Account in der Datenbank."""
account = {
"platform": self.platform_name.lower(),
"username": account_data.get("username", ""),
"password": account_data.get("password", ""),
"email": account_data.get("email", ""),
"phone": account_data.get("phone", ""),
"full_name": account_data.get("full_name", ""),
"created_at": time.strftime("%Y-%m-%d %H:%M:%S")
}
self.db_manager.add_account(account)
logger.info(f"Account in Datenbank gespeichert: {account['username']}")
def validate_inputs(self, inputs):
"""
Validiert die Eingaben für die Account-Erstellung.
Verwendet TextSimilarity für robustere Validierung.
"""
# Basis-Validierungen von BasePlatformController verwenden
valid, error_msg = super().validate_inputs(inputs)
if not valid:
return valid, error_msg
# Instagram-spezifische Validierungen
age = inputs.get("age", 0)
if age < 13: # Änderung von 14 auf 13
return False, "Das Alter muss mindestens 13 sein (Instagram-Anforderung)."
# E-Mail-Domain-Validierung
if inputs.get("registration_method") == "email":
email_domain = inputs.get("email_domain", "")
# Blacklist von bekannten problematischen Domains
blacklisted_domains = ["temp-mail.org", "guerrillamail.com", "maildrop.cc"]
# Prüfe mit TextSimilarity auf Ähnlichkeit mit Blacklist
for domain in blacklisted_domains:
if self.text_similarity.is_similar(email_domain, domain, threshold=0.8):
return False, f"Die E-Mail-Domain '{email_domain}' kann problematisch für die Instagram-Registrierung sein. Bitte verwenden Sie eine andere Domain."
return True, ""
def get_form_field_label(self, field_type: str) -> str:
"""
Gibt einen Label-Text für ein Formularfeld basierend auf dem Feldtyp zurück.
Args:
field_type: Typ des Formularfelds
Returns:
str: Label-Text für das Formularfeld
"""
# Mapping von Feldtypen zu Labels
field_labels = {
"full_name": "Vollständiger Name",
"username": "Benutzername",
"password": "Passwort",
"email": "E-Mail-Adresse",
"phone": "Telefonnummer",
"age": "Alter",
"birthday": "Geburtsdatum"
}
return field_labels.get(field_type, field_type.capitalize())

Datei anzeigen

@ -0,0 +1,277 @@
"""
Controller für TikTok-spezifische Funktionalität.
Mit TextSimilarity-Integration für robusteres UI-Element-Matching.
"""
import logging
import time
import random
from PyQt5.QtCore import QThread, pyqtSignal, QObject
from controllers.platform_controllers.base_controller import BasePlatformController
from views.tabs.generator_tab import GeneratorTab
from views.tabs.accounts_tab import AccountsTab
from views.tabs.settings_tab import SettingsTab
from social_networks.tiktok.tiktok_automation import TikTokAutomation
from utils.text_similarity import TextSimilarity
logger = logging.getLogger("tiktok_controller")
class TikTokWorkerThread(QThread):
"""Thread für die TikTok-Account-Erstellung."""
# Signale
update_signal = pyqtSignal(str)
log_signal = pyqtSignal(str)
progress_signal = pyqtSignal(int)
finished_signal = pyqtSignal(dict)
error_signal = pyqtSignal(str)
def __init__(self, params):
super().__init__()
self.params = params
self.running = True
# TextSimilarity für robustes Fehler-Matching
self.text_similarity = TextSimilarity(default_threshold=0.7)
# Fehler-Patterns für robustes Fehler-Matching
self.error_patterns = [
"Fehler", "Error", "Fehlgeschlagen", "Failed", "Problem", "Issue",
"Nicht möglich", "Not possible", "Bitte versuchen Sie es erneut",
"Please try again", "Konnte nicht", "Could not", "Timeout"
]
def run(self):
"""Führt die Account-Erstellung aus."""
try:
self.log_signal.emit("TikTok-Account-Erstellung gestartet...")
self.progress_signal.emit(10)
# TikTok-Automation initialisieren
automation = TikTokAutomation(
headless=self.params.get("headless", False),
use_proxy=self.params.get("use_proxy", False),
proxy_type=self.params.get("proxy_type"),
save_screenshots=True,
debug=self.params.get("debug", False),
email_domain=self.params.get("email_domain", "z5m7q9dk3ah2v1plx6ju.com")
)
self.update_signal.emit("TikTok-Automation initialisiert")
self.progress_signal.emit(20)
# Account registrieren
self.log_signal.emit(f"Registriere Account für: {self.params['full_name']}")
registration_method = self.params.get("registration_method", "email")
phone_number = self.params.get("phone_number")
# Account registrieren
result = automation.register_account(
full_name=self.params["full_name"],
age=self.params["age"],
registration_method=registration_method,
phone_number=phone_number,
**self.params.get("additional_params", {})
)
self.progress_signal.emit(100)
if result["success"]:
self.log_signal.emit("Account erfolgreich erstellt!")
self.finished_signal.emit(result)
else:
# Robuste Fehlerbehandlung mit TextSimilarity
error_msg = result.get("error", "Unbekannter Fehler")
# Versuche, Fehler nutzerfreundlicher zu interpretieren
user_friendly_error = self._interpret_error(error_msg)
self.log_signal.emit(f"Fehler bei der Account-Erstellung: {user_friendly_error}")
self.error_signal.emit(user_friendly_error)
except Exception as e:
logger.error(f"Fehler im Worker-Thread: {e}")
self.log_signal.emit(f"Schwerwiegender Fehler: {str(e)}")
self.error_signal.emit(str(e))
self.progress_signal.emit(0)
def _interpret_error(self, error_msg: str) -> str:
"""
Interpretiert Fehlermeldungen und gibt eine benutzerfreundlichere Version zurück.
Verwendet TextSimilarity für robusteres Fehler-Matching.
Args:
error_msg: Die ursprüngliche Fehlermeldung
Returns:
str: Benutzerfreundliche Fehlermeldung
"""
# Bekannte Fehlermuster und deren Interpretationen
error_interpretations = {
"captcha": "TikTok hat einen Captcha-Test angefordert. Versuchen Sie es später erneut oder nutzen Sie einen anderen Proxy.",
"verification": "Es gab ein Problem mit der Verifizierung des Accounts. Bitte prüfen Sie die E-Mail-Einstellungen.",
"proxy": "Problem mit der Proxy-Verbindung. Bitte prüfen Sie Ihre Proxy-Einstellungen.",
"timeout": "Zeitüberschreitung bei der Verbindung. Bitte überprüfen Sie Ihre Internetverbindung.",
"username": "Der gewählte Benutzername ist bereits vergeben oder nicht zulässig.",
"password": "Das Passwort erfüllt nicht die Anforderungen von TikTok.",
"email": "Die E-Mail-Adresse konnte nicht verwendet werden. Bitte nutzen Sie eine andere E-Mail-Domain.",
"phone": "Die Telefonnummer konnte nicht für die Registrierung verwendet werden.",
"age": "Das eingegebene Alter erfüllt nicht die Anforderungen von TikTok.",
"too_many_attempts": "Zu viele Registrierungsversuche. Bitte warten Sie und versuchen Sie es später erneut."
}
# Versuche, den Fehler zu kategorisieren
for pattern, interpretation in error_interpretations.items():
for error_term in self.error_patterns:
if (pattern in error_msg.lower() or
self.text_similarity.is_similar(error_term, error_msg, threshold=0.7)):
return interpretation
# Fallback: Originale Fehlermeldung zurückgeben
return error_msg
def stop(self):
"""Stoppt den Thread."""
self.running = False
self.terminate()
class TikTokController(BasePlatformController):
"""Controller für TikTok-spezifische Funktionalität."""
def __init__(self, db_manager, proxy_rotator, email_handler, language_manager=None):
super().__init__("TikTok", db_manager, proxy_rotator, email_handler, language_manager)
self.worker_thread = None
# TextSimilarity für robustes UI-Element-Matching
self.text_similarity = TextSimilarity(default_threshold=0.75)
def create_generator_tab(self):
"""Erstellt den TikTok-Generator-Tab."""
generator_tab = GeneratorTab(self.platform_name, self.language_manager)
# TikTok-spezifische Anpassungen
# Diese Methode überschreiben, wenn spezifische Anpassungen benötigt werden
# Signale verbinden
generator_tab.start_requested.connect(self.start_account_creation)
generator_tab.stop_requested.connect(self.stop_account_creation)
return generator_tab
def start_account_creation(self, params):
"""Startet die TikTok-Account-Erstellung."""
super().start_account_creation(params)
# Validiere Eingaben
is_valid, error_msg = self.validate_inputs(params)
if not is_valid:
self.get_generator_tab().show_error(error_msg)
return
# UI aktualisieren
generator_tab = self.get_generator_tab()
generator_tab.set_running(True)
generator_tab.clear_log()
generator_tab.set_progress(0)
# Worker-Thread starten
self.worker_thread = TikTokWorkerThread(params)
self.worker_thread.update_signal.connect(lambda msg: generator_tab.set_status(msg))
self.worker_thread.log_signal.connect(lambda msg: generator_tab.add_log(msg))
self.worker_thread.error_signal.connect(lambda msg: (generator_tab.show_error(msg), generator_tab.set_running(False)))
self.worker_thread.finished_signal.connect(lambda result: self.handle_account_created(result))
self.worker_thread.progress_signal.connect(lambda value: generator_tab.set_progress(value))
self.worker_thread.start()
def stop_account_creation(self):
"""Stoppt die TikTok-Account-Erstellung."""
if self.worker_thread and self.worker_thread.isRunning():
self.worker_thread.stop()
generator_tab = self.get_generator_tab()
generator_tab.add_log("Account-Erstellung wurde abgebrochen")
generator_tab.set_running(False)
generator_tab.set_progress(0)
def handle_account_created(self, result):
"""Verarbeitet erfolgreich erstellte Accounts."""
generator_tab = self.get_generator_tab()
generator_tab.set_running(False)
# Account-Daten aus dem Ergebnis holen
account_data = result.get("account_data", {})
# Account-Erfolgsereignis auslösen
generator_tab.account_created.emit(self.platform_name, account_data)
# Account in der Datenbank speichern
self.save_account_to_db(account_data)
def save_account_to_db(self, account_data):
"""Speichert einen erstellten Account in der Datenbank."""
account = {
"platform": self.platform_name.lower(),
"username": account_data.get("username", ""),
"password": account_data.get("password", ""),
"email": account_data.get("email", ""),
"phone": account_data.get("phone", ""),
"full_name": account_data.get("full_name", ""),
"created_at": time.strftime("%Y-%m-%d %H:%M:%S")
}
self.db_manager.add_account(account)
logger.info(f"Account in Datenbank gespeichert: {account['username']}")
def validate_inputs(self, inputs):
"""
Validiert die Eingaben für die Account-Erstellung.
Verwendet TextSimilarity für robustere Validierung.
"""
# Basis-Validierungen von BasePlatformController verwenden
valid, error_msg = super().validate_inputs(inputs)
if not valid:
return valid, error_msg
# TikTok-spezifische Validierungen
age = inputs.get("age", 0)
if age < 13:
return False, "Das Alter muss mindestens 13 sein (TikTok-Anforderung)."
# E-Mail-Domain-Validierung
if inputs.get("registration_method") == "email":
email_domain = inputs.get("email_domain", "")
# Blacklist von bekannten problematischen Domains
blacklisted_domains = ["temp-mail.org", "guerrillamail.com", "maildrop.cc"]
# Prüfe mit TextSimilarity auf Ähnlichkeit mit Blacklist
for domain in blacklisted_domains:
if self.text_similarity.is_similar(email_domain, domain, threshold=0.8):
return False, f"Die E-Mail-Domain '{email_domain}' kann problematisch für die TikTok-Registrierung sein. Bitte verwenden Sie eine andere Domain."
return True, ""
def get_form_field_label(self, field_type: str) -> str:
"""
Gibt einen Label-Text für ein Formularfeld basierend auf dem Feldtyp zurück.
Args:
field_type: Typ des Formularfelds
Returns:
str: Label-Text für das Formularfeld
"""
# Mapping von Feldtypen zu Labels
field_labels = {
"full_name": "Vollständiger Name",
"username": "Benutzername",
"password": "Passwort",
"email": "E-Mail-Adresse",
"phone": "Telefonnummer",
"age": "Alter",
"birthday": "Geburtsdatum"
}
return field_labels.get(field_type, field_type.capitalize())