317 Zeilen
13 KiB
Python
317 Zeilen
13 KiB
Python
"""
|
|
Method rotation mixin for platform controllers.
|
|
Provides method rotation functionality without breaking existing inheritance hierarchy.
|
|
"""
|
|
|
|
import logging
|
|
from datetime import datetime
|
|
from typing import Dict, Any, Optional
|
|
|
|
from application.use_cases.method_rotation_use_case import MethodRotationUseCase, RotationContext
|
|
from infrastructure.repositories.method_strategy_repository import MethodStrategyRepository
|
|
from infrastructure.repositories.rotation_session_repository import RotationSessionRepository
|
|
from infrastructure.repositories.platform_method_state_repository import PlatformMethodStateRepository
|
|
from domain.entities.method_rotation import MethodStrategy, RotationSession, RiskLevel
|
|
|
|
|
|
class MethodRotationMixin:
|
|
"""
|
|
Mixin class that adds method rotation capabilities to platform controllers.
|
|
Can be mixed into existing controller classes without breaking inheritance.
|
|
"""
|
|
|
|
def _init_method_rotation_system(self):
|
|
"""Initialize the method rotation system components"""
|
|
try:
|
|
# Check if db_manager is available
|
|
if not hasattr(self, 'db_manager') or self.db_manager is None:
|
|
self.method_rotation_use_case = None
|
|
return
|
|
|
|
# Initialize repositories
|
|
self.method_strategy_repo = MethodStrategyRepository(self.db_manager)
|
|
self.rotation_session_repo = RotationSessionRepository(self.db_manager)
|
|
self.platform_state_repo = PlatformMethodStateRepository(self.db_manager)
|
|
|
|
# Initialize use case
|
|
self.method_rotation_use_case = MethodRotationUseCase(
|
|
strategy_repo=self.method_strategy_repo,
|
|
session_repo=self.rotation_session_repo,
|
|
state_repo=self.platform_state_repo
|
|
)
|
|
|
|
# Initialize rotation state
|
|
self.current_rotation_session = None
|
|
self.current_rotation_context = None
|
|
|
|
self.logger.info(f"Method rotation system initialized for {self.platform_name}")
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Failed to initialize method rotation system: {e}")
|
|
# Set to None so we can detect failures and fallback
|
|
self.method_rotation_use_case = None
|
|
|
|
def _apply_method_strategy(self, params: Dict[str, Any], strategy: MethodStrategy) -> Dict[str, Any]:
|
|
"""
|
|
Apply method strategy configuration to account creation parameters.
|
|
|
|
Args:
|
|
params: Original account creation parameters
|
|
strategy: Selected method strategy
|
|
|
|
Returns:
|
|
Updated parameters with method-specific configuration
|
|
"""
|
|
updated_params = params.copy()
|
|
|
|
# Apply method selection
|
|
updated_params['registration_method'] = strategy.method_name
|
|
|
|
# Apply method-specific configuration
|
|
config = strategy.configuration
|
|
|
|
if strategy.method_name.startswith('stealth_'):
|
|
# Instagram anti-bot strategy methods
|
|
updated_params['stealth_method'] = strategy.method_name
|
|
updated_params['enhanced_stealth'] = config.get('enhanced_stealth', False)
|
|
updated_params['user_agent_rotation'] = config.get('user_agent_rotation', False)
|
|
updated_params['fingerprint_complexity'] = config.get('fingerprint_complexity', 'basic')
|
|
updated_params['canvas_noise'] = config.get('canvas_noise', False)
|
|
updated_params['webrtc_protection'] = config.get('webrtc_protection', 'basic')
|
|
updated_params['viewport_randomization'] = config.get('viewport_randomization', False)
|
|
updated_params['navigator_spoof'] = config.get('navigator_spoof', False)
|
|
updated_params['timing_randomization'] = config.get('timing_randomization', False)
|
|
updated_params['screen_resolution_spoof'] = config.get('screen_resolution_spoof', False)
|
|
updated_params['memory_spoof'] = config.get('memory_spoof', False)
|
|
updated_params['hardware_spoof'] = config.get('hardware_spoof', False)
|
|
|
|
elif strategy.method_name == 'email':
|
|
# Email method configuration (legacy)
|
|
updated_params['email_domain'] = config.get('email_domain', self.DEFAULT_EMAIL_DOMAIN)
|
|
updated_params['require_phone_verification'] = config.get('require_phone_verification', False)
|
|
updated_params['auto_verify_email'] = config.get('auto_verify_email', True)
|
|
|
|
elif strategy.method_name == 'phone':
|
|
# Phone method configuration (legacy)
|
|
updated_params['registration_method'] = 'phone'
|
|
updated_params['require_email_backup'] = config.get('require_email_backup', True)
|
|
updated_params['phone_verification_timeout'] = config.get('phone_verification_timeout', 300)
|
|
|
|
elif strategy.method_name == 'social_login':
|
|
# Social login configuration (legacy)
|
|
updated_params['registration_method'] = 'social'
|
|
updated_params['social_providers'] = config.get('supported_providers', ['facebook'])
|
|
updated_params['fallback_to_email'] = config.get('fallback_to_email', True)
|
|
|
|
elif strategy.method_name in ['standard_registration', 'recovery_registration']:
|
|
# Gmail-specific methods
|
|
updated_params['registration_method'] = strategy.method_name
|
|
updated_params['recovery_email'] = config.get('recovery_email', False)
|
|
updated_params['recovery_phone'] = config.get('recovery_phone', False)
|
|
|
|
# Add strategy metadata
|
|
updated_params['_method_strategy'] = {
|
|
'strategy_id': strategy.strategy_id,
|
|
'method_name': strategy.method_name,
|
|
'priority': strategy.priority,
|
|
'risk_level': strategy.risk_level.value,
|
|
'effectiveness_score': strategy.effectiveness_score
|
|
}
|
|
|
|
return updated_params
|
|
|
|
def handle_method_failure(self, error_details: Dict[str, Any]) -> bool:
|
|
"""
|
|
Handle method failure and attempt rotation to next best method.
|
|
|
|
Args:
|
|
error_details: Details about the failure
|
|
|
|
Returns:
|
|
True if rotation succeeded and retry should be attempted, False otherwise
|
|
"""
|
|
if not self.method_rotation_use_case or not self.current_rotation_session:
|
|
return False
|
|
|
|
try:
|
|
# Record the failure
|
|
self.method_rotation_use_case.record_method_result(
|
|
session_id=self.current_rotation_session.session_id,
|
|
method_name=self.current_rotation_session.current_method,
|
|
success=False,
|
|
error_details=error_details
|
|
)
|
|
|
|
# Check if rotation should occur
|
|
if self.method_rotation_use_case.should_rotate_method(self.current_rotation_session.session_id):
|
|
|
|
# Attempt rotation
|
|
next_method = self.method_rotation_use_case.rotate_method(
|
|
session_id=self.current_rotation_session.session_id,
|
|
reason=f"Method failure: {error_details.get('error_type', 'unknown')}"
|
|
)
|
|
|
|
if next_method:
|
|
self.logger.info(f"Rotating from {self.current_rotation_session.current_method} to {next_method.method_name}")
|
|
|
|
# Update current session reference
|
|
self.current_rotation_session = self.rotation_session_repo.find_by_id(
|
|
self.current_rotation_session.session_id
|
|
)
|
|
|
|
return True
|
|
else:
|
|
self.logger.warning("No alternative methods available for rotation")
|
|
|
|
else:
|
|
self.logger.info("Rotation not triggered - continuing with current method")
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Method rotation failed: {e}")
|
|
|
|
return False
|
|
|
|
def handle_method_success(self, result: Dict[str, Any]) -> None:
|
|
"""
|
|
Handle successful method execution.
|
|
|
|
Args:
|
|
result: Result details from successful execution
|
|
"""
|
|
if not self.method_rotation_use_case or not self.current_rotation_session:
|
|
return
|
|
|
|
try:
|
|
execution_time = result.get('execution_time', 0.0)
|
|
|
|
# Record the success
|
|
self.method_rotation_use_case.record_method_result(
|
|
session_id=self.current_rotation_session.session_id,
|
|
method_name=self.current_rotation_session.current_method,
|
|
success=True,
|
|
execution_time=execution_time
|
|
)
|
|
|
|
self.logger.info(f"Method {self.current_rotation_session.current_method} succeeded in {execution_time:.2f}s")
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Failed to record method success: {e}")
|
|
|
|
def get_rotation_status(self) -> Optional[Dict[str, Any]]:
|
|
"""
|
|
Get current rotation session status.
|
|
|
|
Returns:
|
|
Dictionary with rotation status information or None if no active session
|
|
"""
|
|
if not self.method_rotation_use_case or not self.current_rotation_session:
|
|
return None
|
|
|
|
try:
|
|
return self.method_rotation_use_case.get_session_status(
|
|
self.current_rotation_session.session_id
|
|
)
|
|
except Exception as e:
|
|
self.logger.error(f"Failed to get rotation status: {e}")
|
|
return None
|
|
|
|
def get_platform_method_recommendations(self) -> Dict[str, Any]:
|
|
"""
|
|
Get method recommendations and insights for the current platform.
|
|
|
|
Returns:
|
|
Dictionary with recommendations and platform insights
|
|
"""
|
|
if not self.method_rotation_use_case:
|
|
return {}
|
|
|
|
try:
|
|
return self.method_rotation_use_case.get_platform_method_recommendations(
|
|
self.platform_name.lower()
|
|
)
|
|
except Exception as e:
|
|
self.logger.error(f"Failed to get method recommendations: {e}")
|
|
return {}
|
|
|
|
def enable_emergency_mode(self, reason: str = "manual_override") -> None:
|
|
"""
|
|
Enable emergency mode for the platform.
|
|
|
|
Args:
|
|
reason: Reason for enabling emergency mode
|
|
"""
|
|
if not self.method_rotation_use_case:
|
|
return
|
|
|
|
try:
|
|
self.method_rotation_use_case.enable_emergency_mode(
|
|
self.platform_name.lower(), reason
|
|
)
|
|
self.logger.warning(f"Emergency mode enabled for {self.platform_name}: {reason}")
|
|
except Exception as e:
|
|
self.logger.error(f"Failed to enable emergency mode: {e}")
|
|
|
|
def disable_emergency_mode(self) -> None:
|
|
"""Disable emergency mode for the platform."""
|
|
if not self.method_rotation_use_case:
|
|
return
|
|
|
|
try:
|
|
self.method_rotation_use_case.disable_emergency_mode(
|
|
self.platform_name.lower()
|
|
)
|
|
self.logger.info(f"Emergency mode disabled for {self.platform_name}")
|
|
except Exception as e:
|
|
self.logger.error(f"Failed to disable emergency mode: {e}")
|
|
|
|
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
|
|
"""
|
|
return RotationContext(
|
|
platform=self.platform_name.lower(),
|
|
account_id=params.get('account_id'),
|
|
fingerprint_id=params.get('fingerprint', {}).get('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),
|
|
session_metadata={
|
|
'user_inputs': {k: v for k, v in params.items() if not k.startswith('_')},
|
|
'creation_started_at': datetime.now().isoformat(),
|
|
'controller_type': self.__class__.__name__
|
|
}
|
|
)
|
|
|
|
def _should_use_rotation_system(self) -> bool:
|
|
"""
|
|
Check if rotation system should be used.
|
|
|
|
Returns:
|
|
True if rotation system is available and should be used
|
|
"""
|
|
return (
|
|
self.method_rotation_use_case is not None and
|
|
hasattr(self, 'db_manager') and
|
|
self.db_manager is not None
|
|
)
|
|
|
|
def cleanup_rotation_session(self) -> None:
|
|
"""Clean up current rotation session."""
|
|
if self.current_rotation_session:
|
|
try:
|
|
if self.current_rotation_session.is_active:
|
|
self.rotation_session_repo.archive_session(
|
|
self.current_rotation_session.session_id,
|
|
False
|
|
)
|
|
except Exception as e:
|
|
self.logger.error(f"Failed to cleanup rotation session: {e}")
|
|
finally:
|
|
self.current_rotation_session = None
|
|
self.current_rotation_context = None |