import base64 import logging import httpx logger = logging.getLogger(__name__) class ZoomStatus: async def probe(self, account: dict | None = None) -> dict: """ 健康探测: 1. Token 有效性: POST /oauth/token → GET /v2/users/me 2. API 连通性: GET /v2/users/me 3. Webhook 连通性: (无法直接探测 Zoom → 本地,仅检查配置) Returns: dict with keys: ok, token_valid, api_accessible, bot_user_id, errors """ if not account: return { "ok": False, "token_valid": False, "api_accessible": False, "bot_user_id": "", "errors": ["No account provided"], } client_id = account.get("client_id", "") client_secret = account.get("client_secret", "") account_id_zoom = account.get("account_id", "") if not client_id or not client_secret or not account_id_zoom: return { "ok": False, "token_valid": False, "api_accessible": False, "bot_user_id": "", "errors": ["Missing Zoom OAuth credentials"], } result: dict = { "ok": True, "token_valid": False, "api_accessible": False, "bot_user_id": "", "errors": [], } try: raw_auth = f"{client_id}:{client_secret}" auth_header = base64.b64encode(raw_auth.encode()).decode() async with httpx.AsyncClient(timeout=httpx.Timeout(15.0)) as client: token_resp = await client.post( "https://zoom.us/oauth/token", params={"grant_type": "account_credentials", "account_id": account_id_zoom}, headers={ "Authorization": f"Basic {auth_header}", "Content-Type": "application/x-www-form-urlencoded", }, ) if token_resp.status_code == 200: result["token_valid"] = True token = token_resp.json().get("access_token", "") user_resp = await client.get( "https://api.zoom.us/v2/users/me", headers={"Authorization": f"Bearer {token}"}, ) if user_resp.status_code == 200: result["api_accessible"] = True result["bot_user_id"] = user_resp.json().get("id", "") else: result["errors"].append(f"API probe failed: {user_resp.status_code}") else: result["errors"].append(f"Token probe failed: {token_resp.status_code}") result["ok"] = False except Exception as e: result["errors"].append(str(e)) result["ok"] = False return result def build_summary(self, snapshot: dict) -> dict: """构建账户状态摘要""" if not isinstance(snapshot, dict): return {"channel": "zoomchat", "status": "unknown"} token_valid = snapshot.get("token_valid", False) api_accessible = snapshot.get("api_accessible", False) if token_valid and api_accessible: status = "ok" elif token_valid: status = "degraded" else: status = "error" return { "channel": "zoomchat", "status": status, "token_valid": token_valid, "api_accessible": api_accessible, "bot_user_id": snapshot.get("bot_user_id", ""), }