This commit is contained in:
nose
2025-11-27 10:59:01 -08:00
parent e9b505e609
commit 9eff65d1af
30 changed files with 2099 additions and 1095 deletions

View File

@@ -7,7 +7,7 @@ disables Hydrus features if the API is unavailable.
import logging
import sys
from helper.logger import log
from helper.logger import log, debug
from typing import Tuple, Optional, Dict, Any
from pathlib import Path
@@ -28,6 +28,11 @@ _MPV_AVAILABLE: Optional[bool] = None
_MPV_UNAVAILABLE_REASON: Optional[str] = None
_MPV_CHECK_COMPLETE = False
# Global state for Matrix availability
_MATRIX_AVAILABLE: Optional[bool] = None
_MATRIX_UNAVAILABLE_REASON: Optional[str] = None
_MATRIX_CHECK_COMPLETE = False
def check_hydrus_availability(config: Dict[str, Any]) -> Tuple[bool, Optional[str]]:
"""Check if Hydrus API is available by pinging it.
@@ -80,20 +85,16 @@ def initialize_hydrus_health_check(config: Dict[str, Any]) -> None:
_HYDRUS_CHECK_COMPLETE = True
if is_available:
log("✅ Hydrus: ENABLED - All Hydrus features available", file=sys.stderr)
debug("✅ Hydrus: ENABLED - All Hydrus features available", file=sys.stderr)
else:
log(f"⚠️ Hydrus: DISABLED - {reason or 'Connection failed'}", file=sys.stderr)
log("- Export functionality disabled", file=sys.stderr)
log("- Hydrus library features disabled", file=sys.stderr)
log("- Hydrus tag operations disabled", file=sys.stderr)
log("→ Local storage and All-Debrid features still available", file=sys.stderr)
debug(f"⚠️ Hydrus: DISABLED - {reason or 'Connection failed'}", file=sys.stderr)
except Exception as e:
logger.error(f"[Startup] Failed to initialize Hydrus health check: {e}", exc_info=True)
_HYDRUS_AVAILABLE = False
_HYDRUS_UNAVAILABLE_REASON = str(e)
_HYDRUS_CHECK_COMPLETE = True
log(f"⚠️ Hydrus: DISABLED - Error during health check: {e}", file=sys.stderr)
debug(f"⚠️ Hydrus: DISABLED - Error during health check: {e}", file=sys.stderr)
def check_debrid_availability(config: Dict[str, Any]) -> Tuple[bool, Optional[str]]:
@@ -176,13 +177,10 @@ def initialize_debrid_health_check(config: Dict[str, Any]) -> None:
_DEBRID_CHECK_COMPLETE = True
if is_available:
log("✅ Debrid: ENABLED - All Debrid features available", file=sys.stderr)
debug("✅ Debrid: ENABLED - All Debrid features available", file=sys.stderr)
logger.info("[Startup] Debrid health check PASSED")
else:
log(f"⚠️ Debrid: DISABLED - {reason or 'Connection failed'}", file=sys.stderr)
log("- Debrid export disabled", file=sys.stderr)
log("- Debrid library features disabled", file=sys.stderr)
log("→ Local storage and Hydrus features still available", file=sys.stderr)
debug(f"⚠️ Debrid: DISABLED - {reason or 'Connection failed'}", file=sys.stderr)
logger.warning(f"[Startup] Debrid health check FAILED: {reason}")
except Exception as e:
@@ -190,7 +188,7 @@ def initialize_debrid_health_check(config: Dict[str, Any]) -> None:
_DEBRID_AVAILABLE = False
_DEBRID_UNAVAILABLE_REASON = str(e)
_DEBRID_CHECK_COMPLETE = True
log(f"⚠️ Debrid: DISABLED - Error during health check: {e}", file=sys.stderr)
debug(f"⚠️ Debrid: DISABLED - Error during health check: {e}", file=sys.stderr)
def check_mpv_availability() -> Tuple[bool, Optional[str]]:
@@ -263,11 +261,11 @@ def initialize_mpv_health_check() -> None:
_MPV_CHECK_COMPLETE = True
if is_available:
log("✅ MPV: ENABLED - All MPV features available", file=sys.stderr)
debug("✅ MPV: ENABLED - All MPV features available", file=sys.stderr)
logger.info("[Startup] MPV health check PASSED")
else:
log(f"⚠️ MPV: DISABLED - {reason or 'Connection failed'}", file=sys.stderr)
log("→ Hydrus features still available", file=sys.stderr)
debug(f"⚠️ MPV: DISABLED - {reason or 'Connection failed'}", file=sys.stderr)
debug("→ Hydrus features still available", file=sys.stderr)
logger.warning(f"[Startup] MPV health check FAILED: {reason}")
except Exception as e:
@@ -275,7 +273,77 @@ def initialize_mpv_health_check() -> None:
_MPV_AVAILABLE = False
_MPV_UNAVAILABLE_REASON = str(e)
_MPV_CHECK_COMPLETE = True
log(f"⚠️ MPV: DISABLED - Error during health check: {e}", file=sys.stderr)
debug(f"⚠️ MPV: DISABLED - Error during health check: {e}", file=sys.stderr)
def check_matrix_availability(config: Dict[str, Any]) -> Tuple[bool, Optional[str]]:
"""Check if Matrix homeserver is reachable and credentials are valid.
Args:
config: Application configuration dictionary
Returns:
Tuple of (is_available: bool, reason: Optional[str])
"""
try:
import requests
matrix_conf = config.get('storage', {}).get('matrix', {})
homeserver = matrix_conf.get('homeserver')
access_token = matrix_conf.get('access_token')
if not homeserver:
return False, "Not configured"
if not homeserver.startswith('http'):
homeserver = f"https://{homeserver}"
# Check versions endpoint (no auth required)
try:
resp = requests.get(f"{homeserver}/_matrix/client/versions", timeout=5)
if resp.status_code != 200:
return False, f"Homeserver returned {resp.status_code}"
except Exception as e:
return False, f"Homeserver unreachable: {e}"
# Check auth if token provided (whoami)
if access_token:
try:
headers = {"Authorization": f"Bearer {access_token}"}
resp = requests.get(f"{homeserver}/_matrix/client/v3/account/whoami", headers=headers, timeout=5)
if resp.status_code != 200:
return False, f"Authentication failed: {resp.status_code}"
except Exception as e:
return False, f"Auth check failed: {e}"
return True, None
except Exception as e:
return False, str(e)
def initialize_matrix_health_check(config: Dict[str, Any]) -> None:
"""Initialize Matrix health check at startup."""
global _MATRIX_AVAILABLE, _MATRIX_UNAVAILABLE_REASON, _MATRIX_CHECK_COMPLETE
logger.info("[Startup] Starting Matrix health check...")
try:
is_available, reason = check_matrix_availability(config)
_MATRIX_AVAILABLE = is_available
_MATRIX_UNAVAILABLE_REASON = reason
_MATRIX_CHECK_COMPLETE = True
if is_available:
debug("Matrix: ENABLED - Homeserver reachable", file=sys.stderr)
else:
if reason != "Not configured":
debug(f"Matrix: DISABLED - {reason}", file=sys.stderr)
except Exception as e:
logger.error(f"[Startup] Failed to initialize Matrix health check: {e}", exc_info=True)
_MATRIX_AVAILABLE = False
_MATRIX_UNAVAILABLE_REASON = str(e)
_MATRIX_CHECK_COMPLETE = True
def is_hydrus_available() -> bool:
@@ -423,3 +491,52 @@ def enable_mpv_features() -> None:
_MPV_AVAILABLE = True
_MPV_UNAVAILABLE_REASON = None
logger.info("[MPV] Features manually enabled")
def is_matrix_available() -> bool:
"""Check if Matrix is available (from cached health check).
Returns:
True if Matrix is available, False otherwise
"""
return _MATRIX_AVAILABLE is True
def get_matrix_unavailable_reason() -> Optional[str]:
"""Get the reason why Matrix is unavailable.
Returns:
String explaining why Matrix is unavailable, or None if available
"""
return _MATRIX_UNAVAILABLE_REASON if not is_matrix_available() else None
def is_matrix_check_complete() -> bool:
"""Check if the Matrix health check has been completed.
Returns:
True if health check has run, False if still pending
"""
return _MATRIX_CHECK_COMPLETE
def disable_matrix_features() -> None:
"""Manually disable all Matrix features (for testing/fallback).
This can be called if Matrix connectivity is lost after startup.
"""
global _MATRIX_AVAILABLE, _MATRIX_UNAVAILABLE_REASON
_MATRIX_AVAILABLE = False
_MATRIX_UNAVAILABLE_REASON = "Manually disabled or lost connection"
logger.warning("[Matrix] Features manually disabled")
def enable_matrix_features() -> None:
"""Manually enable Matrix features (for testing/fallback).
This can be called if Matrix connectivity is restored after startup.
"""
global _MATRIX_AVAILABLE, _MATRIX_UNAVAILABLE_REASON
_MATRIX_AVAILABLE = True
_MATRIX_UNAVAILABLE_REASON = None
logger.info("[Matrix] Features manually enabled")