Initial commit
Dieser Commit ist enthalten in:
17
domain/repositories/__init__.py
Normale Datei
17
domain/repositories/__init__.py
Normale Datei
@ -0,0 +1,17 @@
|
||||
"""
|
||||
Domain repository interfaces.
|
||||
|
||||
These interfaces define the contracts for data persistence,
|
||||
following the Dependency Inversion Principle.
|
||||
Infrastructure layer will implement these interfaces.
|
||||
"""
|
||||
|
||||
from .fingerprint_repository import IFingerprintRepository
|
||||
from .analytics_repository import IAnalyticsRepository
|
||||
from .rate_limit_repository import IRateLimitRepository
|
||||
|
||||
__all__ = [
|
||||
'IFingerprintRepository',
|
||||
'IAnalyticsRepository',
|
||||
'IRateLimitRepository'
|
||||
]
|
||||
79
domain/repositories/analytics_repository.py
Normale Datei
79
domain/repositories/analytics_repository.py
Normale Datei
@ -0,0 +1,79 @@
|
||||
"""
|
||||
Analytics repository interface.
|
||||
"""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import List, Dict, Optional
|
||||
from datetime import datetime
|
||||
|
||||
from domain.entities.account_creation_event import AccountCreationEvent
|
||||
from domain.entities.error_event import ErrorEvent
|
||||
from domain.value_objects.error_summary import ErrorSummary
|
||||
|
||||
|
||||
class IAnalyticsRepository(ABC):
|
||||
"""Interface for analytics data persistence."""
|
||||
|
||||
@abstractmethod
|
||||
def save_account_event(self, event: AccountCreationEvent) -> None:
|
||||
"""Save an account creation event."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def save_error_event(self, event: ErrorEvent) -> None:
|
||||
"""Save an error event."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_account_events(self, platform: str = None,
|
||||
start_date: datetime = None,
|
||||
end_date: datetime = None) -> List[AccountCreationEvent]:
|
||||
"""Get account creation events with optional filters."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_error_events(self, platform: str = None,
|
||||
error_type: str = None,
|
||||
start_date: datetime = None,
|
||||
end_date: datetime = None) -> List[ErrorEvent]:
|
||||
"""Get error events with optional filters."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_success_rate(self, platform: str = None,
|
||||
start_date: datetime = None,
|
||||
end_date: datetime = None) -> float:
|
||||
"""Calculate success rate for account creation."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_error_summary(self, platform: str = None,
|
||||
days: int = 7) -> ErrorSummary:
|
||||
"""Get error summary for specified period."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_platform_statistics(self) -> Dict[str, Dict[str, int]]:
|
||||
"""Get statistics grouped by platform."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_hourly_distribution(self, platform: str = None,
|
||||
days: int = 7) -> Dict[int, int]:
|
||||
"""Get hourly distribution of account creation."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_fingerprint_performance(self, fingerprint_id: str) -> Dict[str, any]:
|
||||
"""Get performance metrics for a specific fingerprint."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_proxy_performance(self, days: int = 7) -> Dict[str, Dict[str, int]]:
|
||||
"""Get proxy performance metrics."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def cleanup_old_events(self, days_to_keep: int = 30) -> int:
|
||||
"""Remove events older than specified days. Returns count deleted."""
|
||||
pass
|
||||
63
domain/repositories/fingerprint_repository.py
Normale Datei
63
domain/repositories/fingerprint_repository.py
Normale Datei
@ -0,0 +1,63 @@
|
||||
"""
|
||||
Fingerprint repository interface.
|
||||
"""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Optional, List
|
||||
from datetime import datetime
|
||||
|
||||
from domain.entities.browser_fingerprint import BrowserFingerprint
|
||||
|
||||
|
||||
class IFingerprintRepository(ABC):
|
||||
"""Interface for fingerprint persistence."""
|
||||
|
||||
@abstractmethod
|
||||
def save(self, fingerprint: BrowserFingerprint) -> str:
|
||||
"""Save a fingerprint and return its ID."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def find_by_id(self, fingerprint_id: str) -> Optional[BrowserFingerprint]:
|
||||
"""Find a fingerprint by ID."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def find_by_account_id(self, account_id: str) -> Optional[BrowserFingerprint]:
|
||||
"""Find a fingerprint associated with an account."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def find_all(self) -> List[BrowserFingerprint]:
|
||||
"""Find all fingerprints."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def update(self, fingerprint: BrowserFingerprint) -> bool:
|
||||
"""Update an existing fingerprint."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def delete(self, fingerprint_id: str) -> bool:
|
||||
"""Delete a fingerprint by ID."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def find_by_platform(self, platform: str) -> List[BrowserFingerprint]:
|
||||
"""Find all fingerprints for a specific platform."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def exists(self, fingerprint_id: str) -> bool:
|
||||
"""Check if a fingerprint exists."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def count(self) -> int:
|
||||
"""Count total fingerprints."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def find_recent(self, limit: int = 10) -> List[BrowserFingerprint]:
|
||||
"""Find most recently created fingerprints."""
|
||||
pass
|
||||
310
domain/repositories/method_rotation_repository.py
Normale Datei
310
domain/repositories/method_rotation_repository.py
Normale Datei
@ -0,0 +1,310 @@
|
||||
"""
|
||||
Repository interfaces for method rotation system.
|
||||
These interfaces define the contracts for data access without implementation details.
|
||||
"""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from datetime import datetime, date
|
||||
from typing import List, Optional, Dict, Any
|
||||
from domain.entities.method_rotation import (
|
||||
MethodStrategy, RotationSession, RotationEvent, PlatformMethodState
|
||||
)
|
||||
|
||||
|
||||
class IMethodStrategyRepository(ABC):
|
||||
"""Interface for method strategy data access"""
|
||||
|
||||
@abstractmethod
|
||||
def save(self, strategy: MethodStrategy) -> None:
|
||||
"""Save or update a method strategy"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def find_by_id(self, strategy_id: str) -> Optional[MethodStrategy]:
|
||||
"""Find a strategy by its ID"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def find_by_platform(self, platform: str) -> List[MethodStrategy]:
|
||||
"""Find all strategies for a platform"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def find_active_by_platform(self, platform: str) -> List[MethodStrategy]:
|
||||
"""Find all active strategies for a platform, ordered by effectiveness"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def find_by_platform_and_method(self, platform: str, method_name: str) -> Optional[MethodStrategy]:
|
||||
"""Find a specific method strategy"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def update_performance_metrics(self, strategy_id: str, success: bool,
|
||||
execution_time: float = 0.0) -> None:
|
||||
"""Update performance metrics for a strategy"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_next_available_method(self, platform: str,
|
||||
excluded_methods: List[str] = None,
|
||||
max_risk_level: str = "HIGH") -> Optional[MethodStrategy]:
|
||||
"""Get the next best available method for a platform"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def disable_method(self, platform: str, method_name: str, reason: str) -> None:
|
||||
"""Disable a method temporarily or permanently"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def enable_method(self, platform: str, method_name: str) -> None:
|
||||
"""Re-enable a disabled method"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_platform_statistics(self, platform: str) -> Dict[str, Any]:
|
||||
"""Get aggregated statistics for all methods on a platform"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def cleanup_old_data(self, days_to_keep: int = 90) -> int:
|
||||
"""Clean up old performance data and return number of records removed"""
|
||||
pass
|
||||
|
||||
|
||||
class IRotationSessionRepository(ABC):
|
||||
"""Interface for rotation session data access"""
|
||||
|
||||
@abstractmethod
|
||||
def save(self, session: RotationSession) -> None:
|
||||
"""Save or update a rotation session"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def find_by_id(self, session_id: str) -> Optional[RotationSession]:
|
||||
"""Find a session by its ID"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def find_active_session(self, platform: str, account_id: Optional[str] = None) -> Optional[RotationSession]:
|
||||
"""Find an active session for a platform/account"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def find_active_sessions_by_platform(self, platform: str) -> List[RotationSession]:
|
||||
"""Find all active sessions for a platform"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def update_session_metrics(self, session_id: str, success: bool,
|
||||
method_name: str, error_message: Optional[str] = None) -> None:
|
||||
"""Update session metrics after a method attempt"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def archive_session(self, session_id: str, final_success: bool = False) -> None:
|
||||
"""Mark a session as completed/archived"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_session_history(self, platform: str, limit: int = 100) -> List[RotationSession]:
|
||||
"""Get recent session history for a platform"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_session_statistics(self, platform: str, days: int = 30) -> Dict[str, Any]:
|
||||
"""Get session statistics for a platform over specified days"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def cleanup_old_sessions(self, days_to_keep: int = 30) -> int:
|
||||
"""Clean up old session data and return number of records removed"""
|
||||
pass
|
||||
|
||||
|
||||
class IRotationEventRepository(ABC):
|
||||
"""Interface for rotation event data access"""
|
||||
|
||||
@abstractmethod
|
||||
def save(self, event: RotationEvent) -> None:
|
||||
"""Save a rotation event"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def save_batch(self, events: List[RotationEvent]) -> None:
|
||||
"""Save multiple events in a batch for performance"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def find_by_session(self, session_id: str) -> List[RotationEvent]:
|
||||
"""Find all events for a specific session"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def find_by_method(self, platform: str, method_name: str,
|
||||
start_date: Optional[datetime] = None,
|
||||
end_date: Optional[datetime] = None) -> List[RotationEvent]:
|
||||
"""Find events for a specific method within date range"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def find_recent_failures(self, platform: str, method_name: str,
|
||||
hours: int = 24) -> List[RotationEvent]:
|
||||
"""Find recent failure events for a method"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_event_statistics(self, platform: str,
|
||||
start_date: Optional[datetime] = None,
|
||||
end_date: Optional[datetime] = None) -> Dict[str, Any]:
|
||||
"""Get event statistics for analysis"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_error_patterns(self, platform: str, method_name: str,
|
||||
days: int = 7) -> Dict[str, int]:
|
||||
"""Get error patterns for a method to identify common issues"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def cleanup_old_events(self, days_to_keep: int = 90) -> int:
|
||||
"""Clean up old event data and return number of records removed"""
|
||||
pass
|
||||
|
||||
|
||||
class IPlatformMethodStateRepository(ABC):
|
||||
"""Interface for platform method state data access"""
|
||||
|
||||
@abstractmethod
|
||||
def save(self, state: PlatformMethodState) -> None:
|
||||
"""Save or update platform method state"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def find_by_platform(self, platform: str) -> Optional[PlatformMethodState]:
|
||||
"""Find method state for a platform"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_or_create_state(self, platform: str) -> PlatformMethodState:
|
||||
"""Get existing state or create new one with defaults"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def update_daily_attempts(self, platform: str, method_name: str) -> None:
|
||||
"""Increment daily attempt counter for a method"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def reset_daily_counters(self, platform: str) -> None:
|
||||
"""Reset daily attempt counters (typically called at midnight)"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def block_method(self, platform: str, method_name: str, reason: str) -> None:
|
||||
"""Block a method temporarily"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def unblock_method(self, platform: str, method_name: str) -> None:
|
||||
"""Unblock a previously blocked method"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def record_method_success(self, platform: str, method_name: str) -> None:
|
||||
"""Record successful method execution"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_preferred_method_order(self, platform: str) -> List[str]:
|
||||
"""Get preferred method order for a platform"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def set_emergency_mode(self, platform: str, enabled: bool) -> None:
|
||||
"""Enable/disable emergency mode for a platform"""
|
||||
pass
|
||||
|
||||
|
||||
class IMethodPerformanceRepository(ABC):
|
||||
"""Interface for method performance analytics data access"""
|
||||
|
||||
@abstractmethod
|
||||
def record_daily_performance(self, platform: str, method_name: str,
|
||||
success: bool, execution_time: float = 0.0) -> None:
|
||||
"""Record performance data for daily aggregation"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_daily_performance(self, platform: str, method_name: str,
|
||||
start_date: date, end_date: date) -> List[Dict[str, Any]]:
|
||||
"""Get daily performance data for a method within date range"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_method_trends(self, platform: str, days: int = 30) -> Dict[str, Any]:
|
||||
"""Get performance trends for all methods on a platform"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_success_rate_history(self, platform: str, method_name: str,
|
||||
days: int = 30) -> List[Dict[str, Any]]:
|
||||
"""Get success rate history for trend analysis"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_peak_usage_patterns(self, platform: str, method_name: str) -> Dict[str, Any]:
|
||||
"""Get usage patterns to identify peak hours and optimize timing"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def aggregate_daily_stats(self, target_date: date) -> int:
|
||||
"""Aggregate raw performance data into daily statistics"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def cleanup_old_performance_data(self, days_to_keep: int = 365) -> int:
|
||||
"""Clean up old performance data and return number of records removed"""
|
||||
pass
|
||||
|
||||
|
||||
class IMethodCooldownRepository(ABC):
|
||||
"""Interface for method cooldown data access"""
|
||||
|
||||
@abstractmethod
|
||||
def add_cooldown(self, platform: str, method_name: str,
|
||||
cooldown_until: datetime, reason: str) -> None:
|
||||
"""Add a cooldown period for a method"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def remove_cooldown(self, platform: str, method_name: str) -> None:
|
||||
"""Remove cooldown for a method"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def is_method_on_cooldown(self, platform: str, method_name: str) -> bool:
|
||||
"""Check if a method is currently on cooldown"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_cooldown_info(self, platform: str, method_name: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get cooldown information for a method"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_active_cooldowns(self, platform: str) -> List[Dict[str, Any]]:
|
||||
"""Get all active cooldowns for a platform"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def cleanup_expired_cooldowns(self) -> int:
|
||||
"""Remove expired cooldowns and return number of records removed"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def extend_cooldown(self, platform: str, method_name: str,
|
||||
additional_seconds: int) -> None:
|
||||
"""Extend existing cooldown period"""
|
||||
pass
|
||||
75
domain/repositories/rate_limit_repository.py
Normale Datei
75
domain/repositories/rate_limit_repository.py
Normale Datei
@ -0,0 +1,75 @@
|
||||
"""
|
||||
Rate limit repository interface.
|
||||
"""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Optional, List, Dict
|
||||
from datetime import datetime
|
||||
|
||||
from domain.entities.rate_limit_policy import RateLimitPolicy
|
||||
|
||||
|
||||
class IRateLimitRepository(ABC):
|
||||
"""Interface for rate limit data persistence."""
|
||||
|
||||
@abstractmethod
|
||||
def save_policy(self, policy: RateLimitPolicy) -> None:
|
||||
"""Save or update a rate limit policy."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_policy(self, platform: str, action: str) -> Optional[RateLimitPolicy]:
|
||||
"""Get rate limit policy for platform and action."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_all_policies(self, platform: str = None) -> List[RateLimitPolicy]:
|
||||
"""Get all policies, optionally filtered by platform."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def record_action(self, platform: str, action: str,
|
||||
success: bool = True, proxy: str = None) -> None:
|
||||
"""Record an action for rate limit tracking."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_action_count(self, platform: str, action: str,
|
||||
window_minutes: int = 60,
|
||||
proxy: str = None) -> int:
|
||||
"""Get action count within time window."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_recent_actions(self, platform: str, action: str,
|
||||
limit: int = 100) -> List[Dict[str, any]]:
|
||||
"""Get recent actions for analysis."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def is_rate_limited(self, platform: str, action: str,
|
||||
proxy: str = None) -> bool:
|
||||
"""Check if action is currently rate limited."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_wait_time(self, platform: str, action: str,
|
||||
proxy: str = None) -> int:
|
||||
"""Get wait time in seconds before next action allowed."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def reset_limits(self, platform: str = None, action: str = None,
|
||||
proxy: str = None) -> int:
|
||||
"""Reset rate limits. Returns count of records affected."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_limit_status(self, platform: str) -> Dict[str, Dict[str, any]]:
|
||||
"""Get current rate limit status for all actions on platform."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def cleanup_old_records(self, days_to_keep: int = 7) -> int:
|
||||
"""Remove old rate limit records. Returns count deleted."""
|
||||
pass
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren