""" Diagnostic and monitoring routes. """ from flask import Blueprint, jsonify, request from datetime import datetime from functools import wraps from web.controllers.auth_controller import optional_auth, require_auth diagnostic_bp = Blueprint('diagnostic', __name__, url_prefix='/api/diagnostics') # Simple decorator to handle API errors def handle_api_errors(f): """Simple error handling decorator.""" @wraps(f) def decorated_function(*args, **kwargs): try: return f(*args, **kwargs) except Exception as e: return jsonify({'status': 'error', 'message': str(e)}), 500 return decorated_function # Placeholder objects for missing modules class PlaceholderNetworkChecker: def get_network_status(self): return { "status": "unknown", "connected": True, "ping_ms": 0, "dns_working": True } def check_url_reachability(self, url): return True class PlaceholderErrorManager: def __init__(self): self.error_history = [] self.blacklisted_urls = {} self.retry_counts = {} class PlaceholderHealthMonitor: def get_current_health_status(self): return { "status": "healthy", "uptime": "1h 30m", "memory_usage": "45%", "cpu_usage": "12%" } class RetryableError(Exception): """Placeholder exception for retryable errors.""" pass network_health_checker = PlaceholderNetworkChecker() error_recovery_manager = PlaceholderErrorManager() health_monitor = PlaceholderHealthMonitor() # Placeholder process lock constants and functions RESCAN_LOCK = "rescan" DOWNLOAD_LOCK = "download" # Simple in-memory process lock system _active_locks = {} def is_process_running(lock_name): """Check if a process is currently running (locked).""" return lock_name in _active_locks @diagnostic_bp.route('/network') @handle_api_errors @optional_auth def network_diagnostics(): """Get network diagnostics and connectivity status.""" try: network_status = network_health_checker.get_network_status() # Test AniWorld connectivity aniworld_reachable = network_health_checker.check_url_reachability("https://aniworld.to") network_status['aniworld_reachable'] = aniworld_reachable return jsonify({ 'status': 'success', 'data': network_status }) except Exception as e: raise RetryableError(f"Network diagnostics failed: {e}") @diagnostic_bp.route('/errors') @handle_api_errors @optional_auth def get_error_history(): """Get recent error history.""" try: recent_errors = error_recovery_manager.error_history[-50:] # Last 50 errors return jsonify({ 'status': 'success', 'data': { 'recent_errors': recent_errors, 'total_errors': len(error_recovery_manager.error_history), 'blacklisted_urls': list(error_recovery_manager.blacklisted_urls.keys()) } }) except Exception as e: raise RetryableError(f"Error history retrieval failed: {e}") @diagnostic_bp.route('/system-status') @handle_api_errors @optional_auth def system_status_summary(): """Get comprehensive system status summary.""" try: # Get health status health_status = health_monitor.get_current_health_status() # Get network status network_status = network_health_checker.get_network_status() # Get process status process_status = { 'rescan_running': is_process_running(RESCAN_LOCK), 'download_running': is_process_running(DOWNLOAD_LOCK) } # Get error statistics error_stats = { 'total_errors': len(error_recovery_manager.error_history), 'recent_errors': len([e for e in error_recovery_manager.error_history if (datetime.now() - datetime.fromisoformat(e.get('timestamp', datetime.now().isoformat()))).seconds < 3600]), 'blacklisted_urls': len(error_recovery_manager.blacklisted_urls) } return jsonify({ 'status': 'success', 'data': { 'health': health_status, 'network': network_status, 'processes': process_status, 'errors': error_stats, 'timestamp': datetime.now().isoformat() } }) except Exception as e: raise RetryableError(f"System status retrieval failed: {e}") # Recovery routes @diagnostic_bp.route('/recovery/clear-blacklist', methods=['POST']) @handle_api_errors @require_auth def clear_blacklist(): """Clear URL blacklist.""" try: error_recovery_manager.blacklisted_urls.clear() return jsonify({ 'status': 'success', 'message': 'URL blacklist cleared successfully' }) except Exception as e: raise RetryableError(f"Blacklist clearing failed: {e}") @diagnostic_bp.route('/recovery/retry-counts') @handle_api_errors @optional_auth def get_retry_counts(): """Get retry statistics.""" try: return jsonify({ 'status': 'success', 'data': { 'retry_counts': error_recovery_manager.retry_counts, 'total_retries': sum(error_recovery_manager.retry_counts.values()) } }) except Exception as e: raise RetryableError(f"Retry statistics retrieval failed: {e}")