Update changes
Dieser Commit ist enthalten in:
@ -255,21 +255,7 @@ class BasePlatformController(QObject):
|
||||
|
||||
# Normale Verarbeitung
|
||||
self.handle_account_created(result)
|
||||
|
||||
def stop_account_creation(self):
|
||||
"""Stoppt die 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(f"{self.platform_name}-Account-Erstellung wurde abgebrochen")
|
||||
generator_tab.set_running(False)
|
||||
generator_tab.set_progress(0)
|
||||
|
||||
# Forge-Dialog schließen falls vorhanden
|
||||
if hasattr(self, 'forge_dialog') and self.forge_dialog:
|
||||
self.forge_dialog.close()
|
||||
self.forge_dialog = None
|
||||
|
||||
|
||||
def handle_account_created(self, result):
|
||||
"""
|
||||
Verarbeitet erfolgreich erstellte Accounts.
|
||||
@ -287,19 +273,14 @@ class BasePlatformController(QObject):
|
||||
|
||||
Diese Methode kann von Unterklassen überschrieben werden für spezielle Anforderungen.
|
||||
Sie stellt sicher dass:
|
||||
1. Der Process Guard freigegeben wird
|
||||
2. Der Worker-Thread gestoppt wird
|
||||
3. Die UI zurückgesetzt wird
|
||||
4. Dialoge geschlossen werden
|
||||
"""
|
||||
# Guard-Freigabe (wichtig: VOR Worker-Stop)
|
||||
from utils.process_guard import get_guard
|
||||
guard = get_guard()
|
||||
if guard.is_locked():
|
||||
guard.end(success=False)
|
||||
self.logger.info("Guard freigegeben bei Stop (BaseController)")
|
||||
1. Der Worker-Thread gestoppt wird (Worker gibt Guard frei mit release())
|
||||
2. Die UI zurückgesetzt wird
|
||||
3. Dialoge geschlossen werden
|
||||
|
||||
# Worker stoppen falls vorhanden
|
||||
WICHTIG: Guard-Freigabe erfolgt im Worker.stop() mit release().
|
||||
User-Abbruch zählt NICHT als Failure.
|
||||
"""
|
||||
# Worker stoppen falls vorhanden (Worker.stop() gibt Guard frei)
|
||||
if self.worker_thread and self.worker_thread.isRunning():
|
||||
self.worker_thread.stop()
|
||||
generator_tab = self.get_generator_tab()
|
||||
|
||||
@ -8,19 +8,23 @@ from typing import Dict, Any, Optional
|
||||
from utils.text_similarity import TextSimilarity
|
||||
from domain.value_objects.browser_protection_style import BrowserProtectionStyle, ProtectionLevel
|
||||
import traceback
|
||||
import logging
|
||||
import threading
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class BaseAccountCreationWorkerThread(QThread):
|
||||
"""Basis-Klasse für alle Platform Worker Threads"""
|
||||
|
||||
|
||||
# Signals MÜSSEN identisch zu bestehenden sein
|
||||
update_signal = pyqtSignal(str)
|
||||
log_signal = pyqtSignal(str)
|
||||
progress_signal = pyqtSignal(int)
|
||||
finished_signal = pyqtSignal(dict)
|
||||
error_signal = pyqtSignal(str)
|
||||
|
||||
def __init__(self, params: Dict[str, Any], platform_name: str,
|
||||
|
||||
def __init__(self, params: Dict[str, Any], platform_name: str,
|
||||
session_controller: Optional[Any] = None,
|
||||
generator_tab: Optional[Any] = None):
|
||||
super().__init__()
|
||||
@ -29,10 +33,19 @@ class BaseAccountCreationWorkerThread(QThread):
|
||||
self.session_controller = session_controller
|
||||
self.generator_tab = generator_tab
|
||||
self.running = True
|
||||
|
||||
|
||||
# Thread-Safety Lock für Guard-Flags
|
||||
self._guard_lock = threading.Lock()
|
||||
|
||||
# Flag: Wurde der Worker durch User-Abbruch gestoppt?
|
||||
self._was_cancelled = False
|
||||
|
||||
# Flag: Wurde Guard bereits vom Worker freigegeben?
|
||||
self._guard_released = False
|
||||
|
||||
# TextSimilarity für robustes Fehler-Matching
|
||||
self.text_similarity = TextSimilarity(default_threshold=0.8)
|
||||
|
||||
|
||||
# Platform-spezifische Error-Patterns (überschreibbar)
|
||||
self.error_interpretations = self.get_error_interpretations()
|
||||
|
||||
@ -209,10 +222,8 @@ class BaseAccountCreationWorkerThread(QThread):
|
||||
self.progress_signal.emit(0) # Reset progress on error
|
||||
|
||||
finally:
|
||||
# Feature 5: Process Guard freigeben
|
||||
from utils.process_guard import get_guard
|
||||
guard = get_guard()
|
||||
guard.end(success)
|
||||
# Process Guard freigeben (thread-safe)
|
||||
self._release_guard_if_needed(success)
|
||||
|
||||
def _interpret_error(self, error_message: str) -> str:
|
||||
"""Interpretiert Fehler mit Fuzzy-Matching"""
|
||||
@ -282,24 +293,47 @@ class BaseAccountCreationWorkerThread(QThread):
|
||||
|
||||
return save_result
|
||||
|
||||
def _release_guard_if_needed(self, success: bool = False, is_cancel: bool = False):
|
||||
"""
|
||||
Thread-safe Guard-Freigabe.
|
||||
|
||||
Args:
|
||||
success: War der Prozess erfolgreich? (nur relevant bei end())
|
||||
is_cancel: Wird von stop() aufgerufen? (erzwingt release())
|
||||
"""
|
||||
with self._guard_lock:
|
||||
if self._guard_released:
|
||||
# Bereits freigegeben - nichts zu tun
|
||||
return
|
||||
|
||||
# Wenn von stop() aufgerufen, IMMER als Cancel markieren
|
||||
if is_cancel:
|
||||
self._was_cancelled = True
|
||||
|
||||
from utils.process_guard import get_guard
|
||||
guard = get_guard()
|
||||
|
||||
if self._was_cancelled:
|
||||
# User-Abbruch: release() zählt nicht als Failure
|
||||
guard.release()
|
||||
logger.info(f"{self.platform_name}: Guard released (User-Abbruch)")
|
||||
else:
|
||||
# Normale Beendigung: end() mit Erfolgs-Status
|
||||
guard.end(success)
|
||||
logger.info(f"{self.platform_name}: Guard ended (success={success})")
|
||||
|
||||
self._guard_released = True
|
||||
|
||||
def stop(self):
|
||||
"""
|
||||
Stoppt den Thread sauber mit Guard-Freigabe.
|
||||
|
||||
WICHTIG: Guard wird SOFORT freigegeben, da terminate() den finally-Block überspringt.
|
||||
User-Abbruch wird mit release() behandelt (zählt NICHT als Failure).
|
||||
"""
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
self.running = False
|
||||
|
||||
# Guard SOFORT freigeben bevor terminate()
|
||||
# Grund: terminate() überspringt den finally-Block in run()
|
||||
from utils.process_guard import get_guard
|
||||
guard = get_guard()
|
||||
if guard.is_locked():
|
||||
guard.end(success=False)
|
||||
logger.info("Guard freigegeben bei Worker-Stop (vor terminate)")
|
||||
# Guard thread-safe freigeben (is_cancel=True setzt _was_cancelled im Lock)
|
||||
self._release_guard_if_needed(is_cancel=True)
|
||||
|
||||
# Jetzt Thread beenden
|
||||
self.terminate()
|
||||
|
||||
@ -307,15 +307,13 @@ class FacebookController(BasePlatformController):
|
||||
self.forge_dialog = None
|
||||
|
||||
def stop_account_creation(self):
|
||||
"""Stoppt die Facebook-Account-Erstellung mit Guard-Freigabe."""
|
||||
# Guard-Freigabe (wichtig: VOR Worker-Stop)
|
||||
from utils.process_guard import get_guard
|
||||
guard = get_guard()
|
||||
if guard.is_locked():
|
||||
guard.end(success=False)
|
||||
self.logger.info("Guard freigegeben bei Facebook Stop")
|
||||
"""
|
||||
Stoppt die Facebook-Account-Erstellung.
|
||||
|
||||
# Worker stoppen
|
||||
WICHTIG: Guard-Freigabe erfolgt im Worker.stop() mit release().
|
||||
User-Abbruch zählt NICHT als Failure.
|
||||
"""
|
||||
# Worker stoppen (Worker.stop() gibt Guard frei mit release())
|
||||
if self.worker_thread and self.worker_thread.isRunning():
|
||||
self.worker_thread.stop()
|
||||
generator_tab = self.get_generator_tab()
|
||||
|
||||
@ -198,17 +198,15 @@ class GmailController(BasePlatformController):
|
||||
logger.info(f"[GMAIL] start_account_creation abgeschlossen")
|
||||
|
||||
def stop_account_creation(self):
|
||||
"""Stoppt die laufende Account-Erstellung mit Guard-Freigabe"""
|
||||
"""
|
||||
Stoppt die Gmail-Account-Erstellung.
|
||||
|
||||
WICHTIG: Guard-Freigabe erfolgt im Worker.stop() mit release().
|
||||
User-Abbruch zählt NICHT als Failure.
|
||||
"""
|
||||
logger.info("[GMAIL] Stoppe Account-Erstellung")
|
||||
|
||||
# Guard-Freigabe (wichtig: VOR Worker-Stop)
|
||||
from utils.process_guard import get_guard
|
||||
guard = get_guard()
|
||||
if guard.is_locked():
|
||||
guard.end(success=False)
|
||||
logger.info("Guard freigegeben bei Gmail Stop")
|
||||
|
||||
# Worker stoppen
|
||||
# Worker stoppen (Worker.stop() gibt Guard frei mit release())
|
||||
if self.worker_thread and self.worker_thread.isRunning():
|
||||
self.worker_thread.stop()
|
||||
self.worker_thread.wait()
|
||||
|
||||
@ -198,8 +198,9 @@ class InstagramController(BasePlatformController):
|
||||
is_valid, error_msg = self.validate_inputs(params)
|
||||
if not is_valid:
|
||||
# Guard freigeben da Worker nicht gestartet wird
|
||||
# release() statt end() - Validierungsfehler ist kein "echter" Failure
|
||||
from utils.process_guard import get_guard
|
||||
get_guard().end(success=False)
|
||||
get_guard().release()
|
||||
self.get_generator_tab().show_error(error_msg)
|
||||
return
|
||||
|
||||
@ -213,8 +214,10 @@ class InstagramController(BasePlatformController):
|
||||
# Schmiedeanimation-Dialog erstellen und anzeigen
|
||||
parent_widget = generator_tab.window() # Hauptfenster als Parent
|
||||
self.forge_dialog = ForgeAnimationDialog(parent_widget, "Instagram")
|
||||
self.forge_dialog.cancel_clicked.connect(self.stop_account_creation)
|
||||
self.forge_dialog.closed.connect(self.stop_account_creation)
|
||||
|
||||
# NUR cancel_clicked verbinden - closed wird durch close() in stop_account_creation
|
||||
# getriggert und würde sonst zu Doppelaufrufen führen
|
||||
self.forge_dialog.cancel_clicked.connect(self._on_user_cancel)
|
||||
|
||||
# Fensterposition vom Hauptfenster holen
|
||||
if parent_widget:
|
||||
@ -276,28 +279,35 @@ class InstagramController(BasePlatformController):
|
||||
# Kritischer Fehler VOR Worker-Start → Guard freigeben!
|
||||
logger.error(f"Fehler beim Start der Account-Erstellung: {e}", exc_info=True)
|
||||
|
||||
# release() - technischer Fehler vor Start ist kein User-Failure
|
||||
from utils.process_guard import get_guard
|
||||
get_guard().end(success=False)
|
||||
get_guard().release()
|
||||
|
||||
# Dialog schließen falls vorhanden
|
||||
if hasattr(self, 'forge_dialog') and self.forge_dialog:
|
||||
self.forge_dialog.close()
|
||||
self.forge_dialog = None
|
||||
|
||||
# UI zurücksetzen
|
||||
generator_tab = self.get_generator_tab()
|
||||
generator_tab.set_running(False)
|
||||
generator_tab.show_error(f"Fehler beim Start: {str(e)}")
|
||||
|
||||
def stop_account_creation(self):
|
||||
"""Stoppt die Instagram-Account-Erstellung mit Guard-Freigabe."""
|
||||
# Guard-Freigabe (wichtig: VOR Worker-Stop)
|
||||
from utils.process_guard import get_guard
|
||||
guard = get_guard()
|
||||
if guard.is_locked():
|
||||
guard.end(success=False)
|
||||
self.logger.info("Guard freigegeben bei Instagram Stop")
|
||||
def _on_user_cancel(self):
|
||||
"""
|
||||
Handler für User-Abbruch (Cancel-Button im Dialog).
|
||||
Ruft stop_account_creation auf und verhindert Doppelaufrufe.
|
||||
"""
|
||||
self.stop_account_creation()
|
||||
|
||||
# Worker stoppen
|
||||
def stop_account_creation(self):
|
||||
"""
|
||||
Stoppt die Instagram-Account-Erstellung.
|
||||
|
||||
WICHTIG: Guard-Freigabe erfolgt im Worker.stop() mit release().
|
||||
Der Controller macht KEINE eigene Guard-Freigabe mehr.
|
||||
"""
|
||||
# Worker stoppen (Worker.stop() gibt Guard frei mit release())
|
||||
if self.worker_thread and self.worker_thread.isRunning():
|
||||
self.worker_thread.stop()
|
||||
generator_tab = self.get_generator_tab()
|
||||
|
||||
@ -267,17 +267,28 @@ class MethodRotationMixin:
|
||||
def _create_rotation_context(self, params: Dict[str, Any]) -> RotationContext:
|
||||
"""
|
||||
Create rotation context from account creation parameters.
|
||||
|
||||
|
||||
Args:
|
||||
params: Account creation parameters
|
||||
|
||||
|
||||
Returns:
|
||||
RotationContext for method selection
|
||||
"""
|
||||
# Handle both BrowserFingerprint objects and dictionaries
|
||||
fingerprint_data = params.get('fingerprint')
|
||||
fingerprint_id = None
|
||||
if fingerprint_data:
|
||||
if hasattr(fingerprint_data, 'fingerprint_id'):
|
||||
# BrowserFingerprint object
|
||||
fingerprint_id = fingerprint_data.fingerprint_id
|
||||
elif isinstance(fingerprint_data, dict):
|
||||
# Dictionary
|
||||
fingerprint_id = fingerprint_data.get('fingerprint_id')
|
||||
|
||||
return RotationContext(
|
||||
platform=self.platform_name.lower(),
|
||||
account_id=params.get('account_id'),
|
||||
fingerprint_id=params.get('fingerprint', {}).get('fingerprint_id'),
|
||||
fingerprint_id=fingerprint_id,
|
||||
excluded_methods=params.get('_excluded_methods', []),
|
||||
max_risk_level=RiskLevel(params.get('_max_risk_level', 'HIGH')),
|
||||
emergency_mode=params.get('_emergency_mode', False),
|
||||
|
||||
@ -131,15 +131,13 @@ class OkRuController(BasePlatformController):
|
||||
self.forge_dialog.show()
|
||||
|
||||
def stop_account_creation(self):
|
||||
"""Stoppt die OK.ru-Account-Erstellung mit Guard-Freigabe."""
|
||||
# Guard-Freigabe (wichtig: VOR Worker-Stop)
|
||||
from utils.process_guard import get_guard
|
||||
guard = get_guard()
|
||||
if guard.is_locked():
|
||||
guard.end(success=False)
|
||||
self.logger.info("Guard freigegeben bei OK.ru Stop")
|
||||
"""
|
||||
Stoppt die OK.ru-Account-Erstellung.
|
||||
|
||||
# Worker stoppen
|
||||
WICHTIG: Guard-Freigabe erfolgt im Worker.stop() mit release().
|
||||
User-Abbruch zählt NICHT als Failure.
|
||||
"""
|
||||
# Worker stoppen (Worker.stop() gibt Guard frei mit release())
|
||||
if self.worker_thread and self.worker_thread.isRunning():
|
||||
self.worker_thread.stop()
|
||||
generator_tab = self.get_generator_tab()
|
||||
|
||||
@ -273,15 +273,13 @@ class TikTokController(BasePlatformController):
|
||||
self.forge_dialog.show()
|
||||
|
||||
def stop_account_creation(self):
|
||||
"""Stoppt die TikTok-Account-Erstellung mit Guard-Freigabe."""
|
||||
# Guard-Freigabe (wichtig: VOR Worker-Stop)
|
||||
from utils.process_guard import get_guard
|
||||
guard = get_guard()
|
||||
if guard.is_locked():
|
||||
guard.end(success=False)
|
||||
self.logger.info("Guard freigegeben bei TikTok Stop")
|
||||
"""
|
||||
Stoppt die TikTok-Account-Erstellung.
|
||||
|
||||
# Worker stoppen
|
||||
WICHTIG: Guard-Freigabe erfolgt im Worker.stop() mit release().
|
||||
User-Abbruch zählt NICHT als Failure.
|
||||
"""
|
||||
# Worker stoppen (Worker.stop() gibt Guard frei mit release())
|
||||
if self.worker_thread and self.worker_thread.isRunning():
|
||||
self.worker_thread.stop()
|
||||
generator_tab = self.get_generator_tab()
|
||||
|
||||
@ -271,15 +271,13 @@ class XController(BasePlatformController):
|
||||
self.forge_dialog.show()
|
||||
|
||||
def stop_account_creation(self):
|
||||
"""Stoppt die X-Account-Erstellung mit Guard-Freigabe."""
|
||||
# Guard-Freigabe (wichtig: VOR Worker-Stop)
|
||||
from utils.process_guard import get_guard
|
||||
guard = get_guard()
|
||||
if guard.is_locked():
|
||||
guard.end(success=False)
|
||||
self.logger.info("Guard freigegeben bei X Stop")
|
||||
"""
|
||||
Stoppt die X-Account-Erstellung.
|
||||
|
||||
# Worker stoppen
|
||||
WICHTIG: Guard-Freigabe erfolgt im Worker.stop() mit release().
|
||||
User-Abbruch zählt NICHT als Failure.
|
||||
"""
|
||||
# Worker stoppen (Worker.stop() gibt Guard frei mit release())
|
||||
if self.worker_thread and self.worker_thread.isRunning():
|
||||
self.worker_thread.stop()
|
||||
generator_tab = self.get_generator_tab()
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren