from typing import Any from apps.api.src.plugins.base import PluginConnector from apps.api.src.plugins.connectors._shared import safe_json class AdGuardHomeConnector(PluginConnector): id = "adguard-home" name = "AdGuard Home" def _url(self, path: str) -> str: base = self.context.connection.base_url.rstrip("/") if self.context.connection else "" return f"{base}/control{path}" def _headers(self) -> dict[str, str]: headers = {} creds = self.context.credentials if creds.get("username") and creds.get("password"): from base64 import b64encode token = b64encode(f"{creds['username']}:{creds['password']}".encode()).decode() headers["Authorization"] = f"Basic {token}" return headers async def healthcheck(self) -> dict[str, Any]: try: resp = await self.get_client().get(self._url("/status"), headers=self._headers()) ok = resp.status_code == 200 return {"status": "ok" if ok else "error", "status_code": resp.status_code} except Exception as e: return {"status": "error", "message": str(e)} async def fetch_widget_data(self, widget_type: str, settings: dict[str, Any]) -> dict[str, Any]: if widget_type == "dns-overview": return await self._get_stats() if widget_type == "block-rate-chart": return await self._get_stats() if widget_type == "top-clients": return await self._get_top_clients() if widget_type == "top-blocked-domains": return await self._get_top_blocked() return {"error": "Unsupported widget type"} async def _get_stats(self) -> dict[str, Any]: resp = await self.get_client().get(self._url("/stats"), headers=self._headers()) return await safe_json(resp) async def _get_top_clients(self) -> dict[str, Any]: resp = await self.get_client().get( self._url("/stats/top_clients?limit=10"), headers=self._headers() ) return await safe_json(resp) async def _get_top_blocked(self) -> dict[str, Any]: resp = await self.get_client().get( self._url("/stats/top_blocked_domains?limit=10"), headers=self._headers() ) return await safe_json(resp)