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

@ -0,0 +1,362 @@
"""
Use cases for method rotation system.
Implements business logic for method selection, rotation, and performance tracking.
"""
import uuid
from datetime import datetime, timedelta
from typing import List, Optional, Dict, Any
from dataclasses import dataclass
from domain.entities.method_rotation import (
MethodStrategy, RotationSession, RotationEvent, PlatformMethodState,
RotationEventType, RotationStrategy, RiskLevel
)
from domain.repositories.method_rotation_repository import (
IMethodStrategyRepository, IRotationSessionRepository,
IPlatformMethodStateRepository
)
@dataclass
class RotationContext:
"""Context information for rotation decisions"""
platform: str
account_id: Optional[str] = None
fingerprint_id: Optional[str] = None
excluded_methods: List[str] = None
max_risk_level: RiskLevel = RiskLevel.HIGH
emergency_mode: bool = False
session_metadata: Dict[str, Any] = None
def __post_init__(self):
if self.excluded_methods is None:
self.excluded_methods = []
if self.session_metadata is None:
self.session_metadata = {}
class MethodRotationUseCase:
"""
Core use case for method rotation operations.
Handles method selection, rotation logic, and performance tracking.
"""
def __init__(self,
strategy_repo: IMethodStrategyRepository,
session_repo: IRotationSessionRepository,
state_repo: IPlatformMethodStateRepository):
self.strategy_repo = strategy_repo
self.session_repo = session_repo
self.state_repo = state_repo
def start_rotation_session(self, context: RotationContext) -> RotationSession:
"""
Start a new rotation session and select the optimal initial method.
"""
# Check for existing active session
existing_session = self.session_repo.find_active_session(
context.platform, context.account_id
)
if existing_session:
# Archive the old session and start fresh
self.session_repo.archive_session(existing_session.session_id, False)
# Get optimal method for initial attempt
optimal_method = self.get_optimal_method(context)
if not optimal_method:
raise ValueError(f"No available methods for platform {context.platform}")
# Create new session
session = RotationSession(
session_id=f"session_{uuid.uuid4().hex}",
platform=context.platform,
account_id=context.account_id,
current_method=optimal_method.method_name,
fingerprint_id=context.fingerprint_id,
session_metadata=context.session_metadata.copy()
)
# Update platform state
platform_state = self.state_repo.get_or_create_state(context.platform)
platform_state.increment_daily_attempts(optimal_method.method_name)
self.state_repo.save(platform_state)
# Save session
self.session_repo.save(session)
return session
def get_optimal_method(self, context: RotationContext) -> Optional[MethodStrategy]:
"""
Get the optimal method based on current conditions and strategy.
"""
platform_state = self.state_repo.get_or_create_state(context.platform)
# In emergency mode, use only the safest methods
if context.emergency_mode or platform_state.emergency_mode:
return self._get_emergency_method(context)
# Use platform-specific rotation strategy
if platform_state.rotation_strategy == RotationStrategy.ADAPTIVE:
return self._get_adaptive_method(context, platform_state)
elif platform_state.rotation_strategy == RotationStrategy.SEQUENTIAL:
return self._get_sequential_method(context, platform_state)
elif platform_state.rotation_strategy == RotationStrategy.RANDOM:
return self._get_random_method(context, platform_state)
else:
return self._get_smart_method(context, platform_state)
def rotate_method(self, session_id: str, reason: str = "failure") -> Optional[MethodStrategy]:
"""
Rotate to the next best available method for an active session.
"""
session = self.session_repo.find_by_id(session_id)
if not session or not session.is_active:
return None
# Create context for finding next method
context = RotationContext(
platform=session.platform,
account_id=session.account_id,
fingerprint_id=session.fingerprint_id,
excluded_methods=session.attempted_methods.copy()
)
# Find next method
next_method = self.get_optimal_method(context)
if not next_method:
# No more methods available
self.session_repo.archive_session(session_id, False)
return None
# Update session
session.rotate_to_method(next_method.method_name, reason)
self.session_repo.save(session)
# Update platform state
platform_state = self.state_repo.get_or_create_state(session.platform)
platform_state.increment_daily_attempts(next_method.method_name)
self.state_repo.save(platform_state)
return next_method
def record_method_result(self, session_id: str, method_name: str,
success: bool, execution_time: float = 0.0,
error_details: Optional[Dict] = None) -> None:
"""
Record the result of a method execution and update metrics.
"""
session = self.session_repo.find_by_id(session_id)
if not session:
return
# Update session metrics
error_message = error_details.get('message') if error_details else None
self.session_repo.update_session_metrics(
session_id, success, method_name, error_message
)
# Update method strategy performance
strategy = self.strategy_repo.find_by_platform_and_method(
session.platform, method_name
)
if strategy:
self.strategy_repo.update_performance_metrics(
strategy.strategy_id, success, execution_time
)
# Update platform state
if success:
self.state_repo.record_method_success(session.platform, method_name)
# Archive successful session
self.session_repo.archive_session(session_id, True)
else:
# Handle failure - might trigger automatic rotation
self._handle_method_failure(session, method_name, error_details or {})
def should_rotate_method(self, session_id: str) -> bool:
"""
Determine if method rotation should occur based on current session state.
"""
session = self.session_repo.find_by_id(session_id)
if not session or not session.is_active:
return False
return session.should_rotate
def get_session_status(self, session_id: str) -> Optional[Dict[str, Any]]:
"""
Get detailed status information for a rotation session.
"""
session = self.session_repo.find_by_id(session_id)
if not session:
return None
current_strategy = self.strategy_repo.find_by_platform_and_method(
session.platform, session.current_method
)
return {
'session_id': session.session_id,
'platform': session.platform,
'is_active': session.is_active,
'current_method': session.current_method,
'attempted_methods': session.attempted_methods,
'rotation_count': session.rotation_count,
'success_count': session.success_count,
'failure_count': session.failure_count,
'success_rate': session.success_rate,
'session_duration_minutes': session.session_duration.total_seconds() / 60,
'current_strategy_effectiveness': current_strategy.effectiveness_score if current_strategy else 0.0,
'should_rotate': session.should_rotate
}
def get_platform_method_recommendations(self, platform: str) -> Dict[str, Any]:
"""
Get method recommendations and insights for a platform.
"""
strategies = self.strategy_repo.find_active_by_platform(platform)
platform_stats = self.strategy_repo.get_platform_statistics(platform)
session_stats = self.session_repo.get_session_statistics(platform, days=30)
platform_state = self.state_repo.find_by_platform(platform)
recommendations = []
for strategy in strategies[:3]: # Top 3 methods
recommendations.append({
'method_name': strategy.method_name,
'effectiveness_score': strategy.effectiveness_score,
'success_rate': strategy.success_rate,
'risk_level': strategy.risk_level.value,
'is_on_cooldown': strategy.is_on_cooldown,
'daily_attempts_remaining': strategy.max_daily_attempts - platform_state.daily_attempt_counts.get(strategy.method_name, 0) if platform_state else strategy.max_daily_attempts
})
return {
'platform': platform,
'recommended_methods': recommendations,
'platform_statistics': platform_stats,
'session_statistics': session_stats,
'emergency_mode': platform_state.emergency_mode if platform_state else False,
'rotation_strategy': platform_state.rotation_strategy.value if platform_state else 'adaptive'
}
def enable_emergency_mode(self, platform: str, reason: str = "system_override") -> None:
"""Enable emergency mode for a platform"""
self.state_repo.set_emergency_mode(platform, True)
# Archive all active sessions for safety
active_sessions = self.session_repo.find_active_sessions_by_platform(platform)
for session in active_sessions:
session.session_metadata['emergency_archived'] = True
session.session_metadata['emergency_reason'] = reason
self.session_repo.archive_session(session.session_id, False)
def disable_emergency_mode(self, platform: str) -> None:
"""Disable emergency mode for a platform"""
self.state_repo.set_emergency_mode(platform, False)
def _get_adaptive_method(self, context: RotationContext,
platform_state: PlatformMethodState) -> Optional[MethodStrategy]:
"""Get method using adaptive strategy based on recent performance"""
# Prefer last successful method if it's available
if (platform_state.last_successful_method and
platform_state.last_successful_method not in context.excluded_methods):
strategy = self.strategy_repo.find_by_platform_and_method(
context.platform, platform_state.last_successful_method
)
if (strategy and strategy.is_active and
not strategy.is_on_cooldown and
platform_state.is_method_available(strategy.method_name, strategy.max_daily_attempts)):
return strategy
# Fall back to best available method
return self.strategy_repo.get_next_available_method(
context.platform, context.excluded_methods, context.max_risk_level.value
)
def _get_sequential_method(self, context: RotationContext,
platform_state: PlatformMethodState) -> Optional[MethodStrategy]:
"""Get method using sequential strategy"""
for method_name in platform_state.preferred_methods:
if method_name in context.excluded_methods:
continue
strategy = self.strategy_repo.find_by_platform_and_method(
context.platform, method_name
)
if (strategy and strategy.is_active and
not strategy.is_on_cooldown and
platform_state.is_method_available(method_name, strategy.max_daily_attempts)):
return strategy
return None
def _get_random_method(self, context: RotationContext,
platform_state: PlatformMethodState) -> Optional[MethodStrategy]:
"""Get method using random strategy"""
import random
available_strategies = []
for method_name in platform_state.preferred_methods:
if method_name in context.excluded_methods:
continue
strategy = self.strategy_repo.find_by_platform_and_method(
context.platform, method_name
)
if (strategy and strategy.is_active and
not strategy.is_on_cooldown and
platform_state.is_method_available(method_name, strategy.max_daily_attempts)):
available_strategies.append(strategy)
return random.choice(available_strategies) if available_strategies else None
def _get_smart_method(self, context: RotationContext,
platform_state: PlatformMethodState) -> Optional[MethodStrategy]:
"""Get method using AI-driven smart strategy"""
# For now, smart strategy is the same as adaptive
# This can be enhanced with ML models in the future
return self._get_adaptive_method(context, platform_state)
def _get_emergency_method(self, context: RotationContext) -> Optional[MethodStrategy]:
"""Get the safest available method for emergency mode"""
emergency_strategies = self.strategy_repo.get_emergency_methods(context.platform)
for strategy in emergency_strategies:
if (strategy.method_name not in context.excluded_methods and
not strategy.is_on_cooldown):
return strategy
return None
def _handle_method_failure(self, session: RotationSession, method_name: str,
error_details: Dict) -> None:
"""Handle method failure and determine if action is needed"""
# Check if this is a recurring failure pattern
if error_details.get('error_type') == 'rate_limit':
# Temporarily block the method
self.state_repo.block_method(
session.platform, method_name,
f"Rate limited: {error_details.get('message', 'Unknown')}"
)
elif error_details.get('error_type') == 'account_suspended':
# This might indicate method detection, block temporarily
self.state_repo.block_method(
session.platform, method_name,
f"Possible detection: {error_details.get('message', 'Unknown')}"
)
# Check if we need to enable emergency mode
platform_stats = self.strategy_repo.get_platform_statistics(session.platform)
if platform_stats.get('recent_failures_24h', 0) > 10:
self.enable_emergency_mode(session.platform, "high_failure_rate")