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,259 @@
"""
Fingerprint Persistence Service - Handles fingerprint storage and retrieval.
"""
import logging
from typing import Optional, List, Dict, Any
from datetime import datetime, timedelta
from domain.entities.browser_fingerprint import BrowserFingerprint
from domain.repositories.fingerprint_repository import IFingerprintRepository
logger = logging.getLogger("fingerprint_persistence_service")
class FingerprintPersistenceService:
"""Service for fingerprint persistence operations."""
def __init__(self, repository: IFingerprintRepository):
self.repository = repository
self._cache = {} # Simple in-memory cache
self._cache_ttl = 300 # 5 minutes
def save_fingerprint(self, fingerprint: BrowserFingerprint) -> str:
"""Save a fingerprint and return its ID."""
try:
fingerprint_id = self.repository.save(fingerprint)
# Update cache
self._cache[fingerprint_id] = {
'fingerprint': fingerprint,
'timestamp': datetime.now()
}
logger.info(f"Saved fingerprint: {fingerprint_id}")
return fingerprint_id
except Exception as e:
logger.error(f"Failed to save fingerprint: {e}")
raise
def load_fingerprint(self, fingerprint_id: str) -> Optional[BrowserFingerprint]:
"""Load a fingerprint by ID."""
# Check cache first
if fingerprint_id in self._cache:
cache_entry = self._cache[fingerprint_id]
if (datetime.now() - cache_entry['timestamp']).seconds < self._cache_ttl:
logger.debug(f"Loaded fingerprint from cache: {fingerprint_id}")
return cache_entry['fingerprint']
# Load from repository
try:
fingerprint = self.repository.find_by_id(fingerprint_id)
if fingerprint:
# Update cache
self._cache[fingerprint_id] = {
'fingerprint': fingerprint,
'timestamp': datetime.now()
}
logger.info(f"Loaded fingerprint from repository: {fingerprint_id}")
else:
logger.warning(f"Fingerprint not found: {fingerprint_id}")
return fingerprint
except Exception as e:
logger.error(f"Failed to load fingerprint {fingerprint_id}: {e}")
return None
def load_fingerprint_for_account(self, account_id: str) -> Optional[BrowserFingerprint]:
"""Load fingerprint associated with an account."""
try:
fingerprint = self.repository.find_by_account_id(account_id)
if fingerprint:
# Update cache
self._cache[fingerprint.fingerprint_id] = {
'fingerprint': fingerprint,
'timestamp': datetime.now()
}
logger.info(f"Loaded fingerprint for account {account_id}")
else:
logger.warning(f"No fingerprint found for account {account_id}")
return fingerprint
except Exception as e:
logger.error(f"Failed to load fingerprint for account {account_id}: {e}")
return None
def update_fingerprint(self, fingerprint: BrowserFingerprint) -> bool:
"""Update an existing fingerprint."""
try:
success = self.repository.update(fingerprint)
if success:
# Update cache
self._cache[fingerprint.fingerprint_id] = {
'fingerprint': fingerprint,
'timestamp': datetime.now()
}
logger.info(f"Updated fingerprint: {fingerprint.fingerprint_id}")
else:
logger.warning(f"Failed to update fingerprint: {fingerprint.fingerprint_id}")
return success
except Exception as e:
logger.error(f"Failed to update fingerprint {fingerprint.fingerprint_id}: {e}")
return False
def delete_fingerprint(self, fingerprint_id: str) -> bool:
"""Delete a fingerprint."""
try:
success = self.repository.delete(fingerprint_id)
if success:
# Remove from cache
self._cache.pop(fingerprint_id, None)
logger.info(f"Deleted fingerprint: {fingerprint_id}")
else:
logger.warning(f"Failed to delete fingerprint: {fingerprint_id}")
return success
except Exception as e:
logger.error(f"Failed to delete fingerprint {fingerprint_id}: {e}")
return False
def list_fingerprints(self, limit: int = 100) -> List[BrowserFingerprint]:
"""List all fingerprints."""
try:
fingerprints = self.repository.find_all()
# Limit results
if len(fingerprints) > limit:
fingerprints = fingerprints[:limit]
logger.info(f"Listed {len(fingerprints)} fingerprints")
return fingerprints
except Exception as e:
logger.error(f"Failed to list fingerprints: {e}")
return []
def list_recent_fingerprints(self, limit: int = 10) -> List[BrowserFingerprint]:
"""List recently created fingerprints."""
try:
fingerprints = self.repository.find_recent(limit)
logger.info(f"Listed {len(fingerprints)} recent fingerprints")
return fingerprints
except Exception as e:
logger.error(f"Failed to list recent fingerprints: {e}")
return []
def list_fingerprints_by_platform(self, platform: str) -> List[BrowserFingerprint]:
"""List fingerprints for a specific platform."""
try:
fingerprints = self.repository.find_by_platform(platform)
logger.info(f"Listed {len(fingerprints)} fingerprints for platform {platform}")
return fingerprints
except Exception as e:
logger.error(f"Failed to list fingerprints for platform {platform}: {e}")
return []
def get_fingerprint_pool(self, size: int = 10) -> List[BrowserFingerprint]:
"""Get a pool of random fingerprints."""
try:
# Get more than needed to filter
candidates = self.repository.find_recent(size * 3)
# Filter for quality
quality_fingerprints = []
for fp in candidates:
# Skip if too old
if fp.created_at:
age_days = (datetime.now() - fp.created_at).days
if age_days > 30:
continue
# Skip if account-bound
if fp.account_bound:
continue
quality_fingerprints.append(fp)
if len(quality_fingerprints) >= size:
break
logger.info(f"Created fingerprint pool of size {len(quality_fingerprints)}")
return quality_fingerprints
except Exception as e:
logger.error(f"Failed to create fingerprint pool: {e}")
return []
def cleanup_old_fingerprints(self, days_to_keep: int = 90) -> int:
"""Clean up fingerprints older than specified days."""
try:
# Calculate cutoff date
cutoff = datetime.now() - timedelta(days=days_to_keep)
# Get all fingerprints to check
all_fingerprints = self.repository.find_all()
deleted_count = 0
for fp in all_fingerprints:
if fp.created_at and fp.created_at < cutoff:
# Skip if account-bound
if fp.account_bound:
continue
if self.repository.delete(fp.fingerprint_id):
deleted_count += 1
# Remove from cache
self._cache.pop(fp.fingerprint_id, None)
logger.info(f"Cleaned up {deleted_count} old fingerprints")
return deleted_count
except Exception as e:
logger.error(f"Failed to cleanup old fingerprints: {e}")
return 0
def clear_cache(self) -> None:
"""Clear the in-memory cache."""
self._cache.clear()
logger.info("Cleared fingerprint cache")
def get_statistics(self) -> Dict[str, Any]:
"""Get fingerprint statistics."""
try:
total = self.repository.count()
recent = len(self.repository.find_recent(100))
# Platform breakdown
platforms = {}
for platform in ['instagram', 'facebook', 'tiktok', 'twitter']:
count = len(self.repository.find_by_platform(platform))
if count > 0:
platforms[platform] = count
return {
'total_fingerprints': total,
'recent_fingerprints': recent,
'platforms': platforms,
'cache_size': len(self._cache)
}
except Exception as e:
logger.error(f"Failed to get statistics: {e}")
return {
'total_fingerprints': 0,
'recent_fingerprints': 0,
'platforms': {},
'cache_size': len(self._cache)
}