"""Nextcloud service definition. Nextcloud is included as a proof-of-concept third-party service. It has no dashboard widgets yet; its service page holds connection config only. """ from __future__ import annotations from typing import TYPE_CHECKING, Any import requests from media_library_viewer_api.integrations.base import ( SecretField, ServiceBaseUrl, ServiceConfigBase, ServiceDefinition, TestResult, translate_connection_error, ) if TYPE_CHECKING: from media_library_viewer_api.services.settings_store import SettingsStore def test_connection( config: dict[str, Any], secrets: dict[str, str], store: SettingsStore, ) -> TestResult: """GET {base_url}/status.php (unauthenticated server probe).""" try: base_url = str(config.get("base_url") or "").rstrip("/") resp = requests.get(f"{base_url}/status.php", timeout=(5.0, 60.0)) resp.raise_for_status() payload = resp.json() version = str(payload.get("version", "") or "connected") return TestResult(ok=True, detail="Connected to Nextcloud.", evidence=version) except Exception as exc: return translate_connection_error(exc, context="Nextcloud") class NextcloudConfig(ServiceConfigBase): """Non-secret Nextcloud connection config.""" base_url: ServiceBaseUrl username: str = "" DEFINITION = ServiceDefinition( service_type="nextcloud", name="Nextcloud", description="Self-hosted files and collaboration.", config_model=NextcloudConfig, secret_fields=[ SecretField(key="app_password", label="App password", required=True), ], widget_kinds=[], test_callable=test_connection, )