from __future__ import annotations import logging import time from typing import Any from aiohttp import ClientSession logger = logging.getLogger(__name__) CAPABILITIES_ENDPOINT = "/ocs/v2.php/cloud/capabilities" _CAPABILITIES_CACHE: dict[str, tuple[float, dict[str, Any]]] = {} _CACHE_TTL = 300 async def probe_capabilities(http: ClientSession, server_url: str) -> dict[str, Any]: now = time.time() cached = _CAPABILITIES_CACHE.get(server_url) if cached and now - cached[0] < _CACHE_TTL: return cached[1] url = f"{server_url}{CAPABILITIES_ENDPOINT}" headers = {"OCS-APIRequest": "true", "Accept": "application/json"} try: async with http.get(url, headers=headers, timeout=10) as resp: data = await resp.json() ocs = data.get("ocs", {}) caps = ocs.get("data", {}).get("capabilities", {}) spreed = caps.get("spreed", {}) if not spreed: logger.warning("[NextcloudTalk] spreed capability not found in response") _CAPABILITIES_CACHE[server_url] = (now, spreed) return spreed except Exception as e: logger.warning(f"[NextcloudTalk] capabilities probe failed: {e}") return cached[1] if cached else {} def invalidate_cache(server_url: str | None = None) -> None: if server_url: _CAPABILITIES_CACHE.pop(server_url, None) else: _CAPABILITIES_CACHE.clear() def resolve_api_version(capabilities: dict[str, Any]) -> str: version = capabilities.get("version", "") if not version: return "v1" try: major = int(version.split(".")[0]) except (ValueError, IndexError): return "v1" if major >= 17: return "v4" elif major >= 12: return "v3" return "v1" def resolve_api_base(api_version: str) -> str: return f"/ocs/v2.php/apps/spreed/api/{api_version}"