from __future__ import annotations from collections.abc import Callable from typing import Any from sqlmodel import Session, select from ..connectors.authentik import AuthentikConnector from ..connectors.deluge import DelugeConnector from ..connectors.nginx_proxy_manager import NginxProxyManagerConnector from ..connectors.plex import PlexConnector from ..connectors.portainer import PortainerConnector from ..connectors.prowlarr import ProwlarrConnector from ..connectors.radarr import RadarrConnector from ..connectors.sonarr import SonarrConnector from ..connectors.tautulli import TautulliConnector from ..connectors.unraid import UnraidConnector from ..connectors.widefrog import WidefrogConnector from ..core.time import utc_now from ..db.models import App, Connector, NotificationChannel from . import notification_service, safety_center_service from .setup_service import apply_stored_connector_settings _TESTERS: dict[str, Callable[[], Any]] = { 'authentik': AuthentikConnector, 'deluge': DelugeConnector, 'nginx_proxy_manager': NginxProxyManagerConnector, 'plex': PlexConnector, 'portainer': PortainerConnector, 'prowlarr': ProwlarrConnector, 'radarr': RadarrConnector, 'sonarr': SonarrConnector, 'tautulli': TautulliConnector, 'unraid': UnraidConnector, 'widefrog': WidefrogConnector, } def _stored_status(status: str) -> str: return 'error' if status == 'unreachable' else status def test_and_persist_connector(session: Session, connector_id: str) -> dict[str, Any]: connector = session.get(Connector, connector_id) if not connector: return {'status': 'disconnected', 'reason': 'connector_not_found'} apply_stored_connector_settings(session, {connector_id}) if connector_id == 'home_assistant': channel = session.get(NotificationChannel, 'home_assistant') result = ( notification_service.test_channel_connection(session, 'home_assistant') if channel else {'status': 'missing_config', 'reason': 'notification_channel_not_found'} ) else: factory = _TESTERS.get(connector_id) result = factory().test_connection() if factory else {'status': 'error', 'reason': 'test_not_implemented'} status = str(result.get('status') or 'disconnected') persisted_status = _stored_status(status) connector.status = persisted_status connector.last_test = utc_now().isoformat() session.add(connector) app = session.get(App, connector_id) if app and app.connector_status != persisted_status: app.connector_status = persisted_status session.add(app) session.commit() safety_center_service.invalidate_cache() return {**result, 'status': status} def refresh_connector_statuses(session: Session) -> dict[str, Any]: connector_ids = list(session.exec(select(Connector.id).order_by(Connector.id)).all()) results: dict[str, str] = {} for connector_id in connector_ids: if connector_id not in _TESTERS and connector_id != 'home_assistant': continue result = test_and_persist_connector(session, connector_id) results[connector_id] = str(result.get('status') or 'disconnected') return { 'success': True, 'status': 'ok', 'tested': len(results), 'connected': sum(status == 'connected' for status in results.values()), 'results': results, }