"""DSM API probe and version resolution. Discovers available APIs on the target Synology NAS and resolves the best API version to use. """ from __future__ import annotations from typing import Any import httpx from yuxi.utils.logging_config import logger async def probe_dsm( http_client: httpx.AsyncClient, base_url: str, ) -> dict[str, Any]: try: response = await http_client.get( f"{base_url}/webapi/query.cgi", params={ "api": "SYNO.API.Info", "version": "1", "method": "query", "query": "SYNO.API.Auth,SYNO.Chat.External", }, ) response.raise_for_status() data = response.json() if not data.get("success"): error_code = data.get("error", {}).get("code", "unknown") logger.error(f"DSM API probe failed: error code {error_code}") return {} api_info = data.get("data", {}) required_apis = ["SYNO.API.Auth", "SYNO.Chat.External"] missing = [api for api in required_apis if api not in api_info] if missing: logger.error(f"Required DSM APIs not available: {missing}") return {} logger.info( f"DSM API probe successful: Auth v{api_info.get('SYNO.API.Auth', {}).get('maxVersion', '?')}, " f"Chat v{api_info.get('SYNO.Chat.External', {}).get('maxVersion', '?')}" ) return api_info except httpx.HTTPError as e: logger.error(f"DSM API probe HTTP error: {e}") return {} except Exception as e: logger.error(f"DSM API probe failed: {e}") return {} def resolve_api_version(api_info: dict[str, Any] | None, api: str) -> int: if not api_info: if api == "SYNO.API.Auth": return 6 if api == "SYNO.Chat.External": return 1 return 1 api_entry = api_info.get(api, {}) return api_entry.get("maxVersion", api_entry.get("minVersion", 1))