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,435 @@
"""
Domain entities for method rotation system.
These entities represent the core business logic and rules for method rotation.
"""
from dataclasses import dataclass, field
from datetime import datetime, timedelta
from enum import Enum
from typing import Dict, List, Optional, Any
import uuid
import json
class RiskLevel(Enum):
"""Risk levels for method strategies"""
LOW = "LOW"
MEDIUM = "MEDIUM"
HIGH = "HIGH"
class RotationEventType(Enum):
"""Types of rotation events"""
SUCCESS = "SUCCESS"
FAILURE = "FAILURE"
ROTATION = "ROTATION"
COOLDOWN = "COOLDOWN"
CONFIG_CHANGE = "CONFIG_CHANGE"
EMERGENCY_MODE = "EMERGENCY_MODE"
class RotationStrategy(Enum):
"""Rotation strategy types"""
SEQUENTIAL = "sequential" # Try methods in order
RANDOM = "random" # Random method selection
ADAPTIVE = "adaptive" # Learn from success patterns
SMART = "smart" # AI-driven method selection
@dataclass
class MethodStrategy:
"""
Represents a registration/login method strategy for a platform.
Contains configuration, performance metrics, and business rules.
"""
strategy_id: str
platform: str
method_name: str
priority: int = 5 # 1-10, higher = preferred
success_rate: float = 0.0
failure_rate: float = 0.0
last_success: Optional[datetime] = None
last_failure: Optional[datetime] = None
cooldown_period: int = 0 # seconds
max_daily_attempts: int = 10
risk_level: RiskLevel = RiskLevel.MEDIUM
is_active: bool = True
configuration: Dict[str, Any] = field(default_factory=dict)
tags: List[str] = field(default_factory=list)
created_at: datetime = field(default_factory=datetime.now)
updated_at: datetime = field(default_factory=datetime.now)
def __post_init__(self):
"""Validate and normalize data after initialization"""
if not self.strategy_id:
self.strategy_id = f"{self.platform}_{self.method_name}_{uuid.uuid4().hex[:8]}"
# Ensure priority is within valid range
self.priority = max(1, min(10, self.priority))
# Ensure rates are valid percentages
self.success_rate = max(0.0, min(1.0, self.success_rate))
self.failure_rate = max(0.0, min(1.0, self.failure_rate))
@property
def is_on_cooldown(self) -> bool:
"""Check if method is currently on cooldown"""
if not self.last_failure or self.cooldown_period == 0:
return False
cooldown_until = self.last_failure + timedelta(seconds=self.cooldown_period)
return datetime.now() < cooldown_until
@property
def cooldown_remaining_seconds(self) -> int:
"""Get remaining cooldown time in seconds"""
if not self.is_on_cooldown:
return 0
cooldown_until = self.last_failure + timedelta(seconds=self.cooldown_period)
remaining = cooldown_until - datetime.now()
return max(0, int(remaining.total_seconds()))
@property
def effectiveness_score(self) -> float:
"""Calculate overall effectiveness score for method selection"""
base_score = self.priority / 10.0
# Adjust for success rate
if self.success_rate > 0:
base_score *= (1 + self.success_rate)
# Penalize for high failure rate
if self.failure_rate > 0.5:
base_score *= (1 - self.failure_rate * 0.5)
# Penalize for high risk
risk_penalties = {
RiskLevel.LOW: 0.0,
RiskLevel.MEDIUM: 0.1,
RiskLevel.HIGH: 0.3
}
base_score *= (1 - risk_penalties.get(self.risk_level, 0.1))
# Penalize if on cooldown
if self.is_on_cooldown:
base_score *= 0.1
# Penalize if inactive
if not self.is_active:
base_score = 0.0
return max(0.0, min(1.0, base_score))
def update_performance(self, success: bool, execution_time: float = 0.0):
"""Update performance metrics based on execution result"""
self.updated_at = datetime.now()
if success:
self.last_success = datetime.now()
# Update success rate with exponential moving average
self.success_rate = 0.8 * self.success_rate + 0.2 * 1.0
self.failure_rate = 0.8 * self.failure_rate + 0.2 * 0.0
else:
self.last_failure = datetime.now()
# Update failure rate with exponential moving average
self.success_rate = 0.8 * self.success_rate + 0.2 * 0.0
self.failure_rate = 0.8 * self.failure_rate + 0.2 * 1.0
def to_dict(self) -> Dict[str, Any]:
"""Convert to dictionary for serialization"""
return {
'strategy_id': self.strategy_id,
'platform': self.platform,
'method_name': self.method_name,
'priority': self.priority,
'success_rate': self.success_rate,
'failure_rate': self.failure_rate,
'last_success': self.last_success.isoformat() if self.last_success else None,
'last_failure': self.last_failure.isoformat() if self.last_failure else None,
'cooldown_period': self.cooldown_period,
'max_daily_attempts': self.max_daily_attempts,
'risk_level': self.risk_level.value,
'is_active': self.is_active,
'configuration': self.configuration,
'tags': self.tags,
'created_at': self.created_at.isoformat(),
'updated_at': self.updated_at.isoformat()
}
@dataclass
class RotationSession:
"""
Represents an active rotation session for account creation/login.
Tracks the current state and history of method attempts.
"""
session_id: str
platform: str
account_id: Optional[str] = None
current_method: str = ""
attempted_methods: List[str] = field(default_factory=list)
session_start: datetime = field(default_factory=datetime.now)
last_rotation: Optional[datetime] = None
rotation_count: int = 0
success_count: int = 0
failure_count: int = 0
is_active: bool = True
rotation_reason: Optional[str] = None
fingerprint_id: Optional[str] = None
session_metadata: Dict[str, Any] = field(default_factory=dict)
def __post_init__(self):
"""Validate and normalize data after initialization"""
if not self.session_id:
self.session_id = f"session_{uuid.uuid4().hex}"
@property
def session_duration(self) -> timedelta:
"""Get total session duration"""
return datetime.now() - self.session_start
@property
def success_rate(self) -> float:
"""Calculate session success rate"""
total_attempts = self.success_count + self.failure_count
if total_attempts == 0:
return 0.0
return self.success_count / total_attempts
@property
def should_rotate(self) -> bool:
"""Determine if rotation should occur based on failure patterns"""
# Rotate after 2 consecutive failures
if self.failure_count >= 2 and self.success_count == 0:
return True
# Rotate if failure rate is high and we have alternatives
if len(self.attempted_methods) < 3 and self.success_rate < 0.3:
return True
return False
def add_attempt(self, method_name: str, success: bool, error_message: Optional[str] = None):
"""Record a method attempt"""
if method_name not in self.attempted_methods:
self.attempted_methods.append(method_name)
self.current_method = method_name
if success:
self.success_count += 1
else:
self.failure_count += 1
# Add to metadata
attempt_data = {
'method': method_name,
'success': success,
'timestamp': datetime.now().isoformat(),
'error': error_message
}
if 'attempts' not in self.session_metadata:
self.session_metadata['attempts'] = []
self.session_metadata['attempts'].append(attempt_data)
def rotate_to_method(self, new_method: str, reason: str):
"""Rotate to a new method"""
self.current_method = new_method
self.last_rotation = datetime.now()
self.rotation_count += 1
self.rotation_reason = reason
def complete_session(self, success: bool):
"""Mark session as completed"""
self.is_active = False
self.session_metadata['completed_at'] = datetime.now().isoformat()
self.session_metadata['final_success'] = success
def to_dict(self) -> Dict[str, Any]:
"""Convert to dictionary for serialization"""
return {
'session_id': self.session_id,
'platform': self.platform,
'account_id': self.account_id,
'current_method': self.current_method,
'attempted_methods': self.attempted_methods,
'session_start': self.session_start.isoformat(),
'last_rotation': self.last_rotation.isoformat() if self.last_rotation else None,
'rotation_count': self.rotation_count,
'success_count': self.success_count,
'failure_count': self.failure_count,
'is_active': self.is_active,
'rotation_reason': self.rotation_reason,
'fingerprint_id': self.fingerprint_id,
'session_metadata': self.session_metadata
}
@dataclass
class RotationEvent:
"""
Represents a specific event in the rotation system.
Used for detailed logging and analytics.
"""
event_id: str
session_id: str
method_name: str
event_type: RotationEventType
timestamp: datetime = field(default_factory=datetime.now)
details: Dict[str, Any] = field(default_factory=dict)
error_message: Optional[str] = None
performance_metrics: Dict[str, float] = field(default_factory=dict)
correlation_id: Optional[str] = None
def __post_init__(self):
"""Validate and normalize data after initialization"""
if not self.event_id:
self.event_id = f"event_{uuid.uuid4().hex}"
@classmethod
def create_success_event(cls, session_id: str, method_name: str,
execution_time: float = 0.0, **kwargs) -> 'RotationEvent':
"""Create a success event"""
return cls(
event_id=f"success_{uuid.uuid4().hex[:8]}",
session_id=session_id,
method_name=method_name,
event_type=RotationEventType.SUCCESS,
performance_metrics={'execution_time': execution_time},
details=kwargs
)
@classmethod
def create_failure_event(cls, session_id: str, method_name: str,
error_message: str, **kwargs) -> 'RotationEvent':
"""Create a failure event"""
return cls(
event_id=f"failure_{uuid.uuid4().hex[:8]}",
session_id=session_id,
method_name=method_name,
event_type=RotationEventType.FAILURE,
error_message=error_message,
details=kwargs
)
@classmethod
def create_rotation_event(cls, session_id: str, from_method: str,
to_method: str, reason: str, **kwargs) -> 'RotationEvent':
"""Create a rotation event"""
return cls(
event_id=f"rotation_{uuid.uuid4().hex[:8]}",
session_id=session_id,
method_name=to_method,
event_type=RotationEventType.ROTATION,
details={
'from_method': from_method,
'to_method': to_method,
'reason': reason,
**kwargs
}
)
def to_dict(self) -> Dict[str, Any]:
"""Convert to dictionary for serialization"""
return {
'event_id': self.event_id,
'session_id': self.session_id,
'method_name': self.method_name,
'event_type': self.event_type.value,
'timestamp': self.timestamp.isoformat(),
'details': self.details,
'error_message': self.error_message,
'performance_metrics': self.performance_metrics,
'correlation_id': self.correlation_id
}
@dataclass
class PlatformMethodState:
"""
Represents the rotation state for a specific platform.
Tracks preferences, blocks, and daily limits.
"""
platform: str
last_successful_method: Optional[str] = None
last_successful_at: Optional[datetime] = None
preferred_methods: List[str] = field(default_factory=list)
blocked_methods: List[str] = field(default_factory=list)
daily_attempt_counts: Dict[str, int] = field(default_factory=dict)
reset_date: datetime = field(default_factory=lambda: datetime.now().replace(hour=0, minute=0, second=0, microsecond=0))
rotation_strategy: RotationStrategy = RotationStrategy.ADAPTIVE
emergency_mode: bool = False
metadata: Dict[str, Any] = field(default_factory=dict)
updated_at: datetime = field(default_factory=datetime.now)
def is_method_available(self, method_name: str, max_daily_attempts: int) -> bool:
"""Check if a method is available for use"""
# Check if method is blocked
if method_name in self.blocked_methods:
return False
# Check daily limits
current_attempts = self.daily_attempt_counts.get(method_name, 0)
if current_attempts >= max_daily_attempts:
return False
return True
def increment_daily_attempts(self, method_name: str):
"""Increment daily attempt count for a method"""
# Reset counts if it's a new day
today = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
if today > self.reset_date:
self.daily_attempt_counts = {}
self.reset_date = today
self.daily_attempt_counts[method_name] = self.daily_attempt_counts.get(method_name, 0) + 1
self.updated_at = datetime.now()
def record_success(self, method_name: str):
"""Record a successful method execution"""
self.last_successful_method = method_name
self.last_successful_at = datetime.now()
self.updated_at = datetime.now()
# Move successful method to front of preferred list
if method_name in self.preferred_methods:
self.preferred_methods.remove(method_name)
self.preferred_methods.insert(0, method_name)
def block_method(self, method_name: str, reason: str):
"""Temporarily block a method"""
if method_name not in self.blocked_methods:
self.blocked_methods.append(method_name)
self.metadata[f'block_reason_{method_name}'] = reason
self.metadata[f'blocked_at_{method_name}'] = datetime.now().isoformat()
self.updated_at = datetime.now()
def unblock_method(self, method_name: str):
"""Remove method from blocked list"""
if method_name in self.blocked_methods:
self.blocked_methods.remove(method_name)
# Clean up metadata
self.metadata.pop(f'block_reason_{method_name}', None)
self.metadata.pop(f'blocked_at_{method_name}', None)
self.updated_at = datetime.now()
def to_dict(self) -> Dict[str, Any]:
"""Convert to dictionary for serialization"""
return {
'platform': self.platform,
'last_successful_method': self.last_successful_method,
'last_successful_at': self.last_successful_at.isoformat() if self.last_successful_at else None,
'preferred_methods': self.preferred_methods,
'blocked_methods': self.blocked_methods,
'daily_attempt_counts': self.daily_attempt_counts,
'reset_date': self.reset_date.isoformat(),
'rotation_strategy': self.rotation_strategy.value,
'emergency_mode': self.emergency_mode,
'metadata': self.metadata,
'updated_at': self.updated_at.isoformat()
}