from __future__ import annotations from typing import Any, TYPE_CHECKING import httpx if TYPE_CHECKING: from .adapter import WeChatAdapter async def diagnose_bridge(bridge_client) -> dict[str, Any]: findings: list[dict[str, Any]] = [] try: status = await bridge_client.check_login_status() if not status.get("logged_in"): findings.append({"severity": "error", "message": "Bridge not logged in"}) else: findings.append({"severity": "ok", "message": "Bridge connected and logged in"}) except Exception as e: findings.append({"severity": "error", "message": f"Bridge unreachable: {e}"}) return { "health": "degraded" if any(f["severity"] == "error" for f in findings) else "healthy", "findings": findings, } async def repair_bridge(bridge_client) -> dict[str, Any]: actions: list[dict[str, Any]] = [] try: status = await bridge_client.check_login_status() if not status.get("logged_in"): actions.append({"action": "relogin", "status": "pending"}) except Exception as e: actions.append({"action": "restart_bridge", "status": "error", "error": str(e)}) return {"repaired": len([a for a in actions if a.get("status") == "ok"]) > 0, "actions": actions} async def diagnose_wecom(client, http_client, config: dict[str, Any]) -> dict[str, Any]: findings: list[dict[str, Any]] = [] try: token = await client.get_access_token() if token: findings.append({"severity": "ok", "message": "WeCom access token valid"}) else: findings.append({"severity": "error", "message": "WeCom access token invalid"}) except Exception as e: findings.append({"severity": "error", "message": f"WeCom auth failed: {e}"}) try: if http_client: resp = await http_client.get("https://qyapi.weixin.qq.com", timeout=httpx.Timeout(5.0)) findings.append({"severity": "ok", "message": f"WeCom API reachable (HTTP {resp.status_code})"}) except Exception as e: findings.append({"severity": "error", "message": f"WeCom API unreachable: {e}"}) webhook_url = config.get("webhook_url", "") if not webhook_url: findings.append({"severity": "warning", "message": "Webhook URL not configured"}) token_cfg = config.get("token", "") if not token_cfg: findings.append( {"severity": "warning", "message": "Webhook token not configured, signature verification disabled"} ) return {"health": "healthy" if all(f["severity"] == "ok" for f in findings) else "degraded", "findings": findings} async def diagnose_mp(client, http_client, config: dict[str, Any]) -> dict[str, Any]: findings: list[dict[str, Any]] = [] try: token = await client.get_access_token() if token: findings.append({"severity": "ok", "message": "MP access token valid"}) else: findings.append({"severity": "error", "message": "MP access token invalid"}) except Exception as e: findings.append({"severity": "error", "message": f"MP auth failed: {e}"}) try: if http_client: resp = await http_client.get("https://api.weixin.qq.com", timeout=httpx.Timeout(5.0)) findings.append({"severity": "ok", "message": f"MP API reachable (HTTP {resp.status_code})"}) except Exception as e: findings.append({"severity": "error", "message": f"MP API unreachable: {e}"}) webhook_url = config.get("webhook_url", "") if not webhook_url: findings.append({"severity": "warning", "message": "Webhook URL not configured"}) return {"health": "healthy" if all(f["severity"] == "ok" for f in findings) else "degraded", "findings": findings} async def diagnose_channel(adapter: WeChatAdapter) -> dict[str, Any]: findings: list[dict[str, Any]] = [] mode = adapter._mode if adapter._banned: findings.append( {"severity": "error", "message": f"Channel is banned: {adapter._banned_reason or 'API unauthorized'}"} ) return {"health": "unhealthy", "findings": findings} if not adapter._http_client: findings.append({"severity": "error", "message": "HTTP client not initialized"}) return {"health": "unhealthy", "findings": findings} mode_result: dict[str, Any] = {} if mode == "wecom" and adapter._wecom_client: mode_result = await diagnose_wecom(adapter._wecom_client, adapter._http_client, adapter.config) elif mode == "mp" and adapter._mp_client: mode_result = await diagnose_mp(adapter._mp_client, adapter._http_client, adapter.config) elif mode == "personal" and adapter._bridge_client: mode_result = await diagnose_bridge(adapter._bridge_client) else: findings.append({"severity": "error", "message": "No active mode"}) return {"health": "unknown", "findings": findings} findings.extend(mode_result.get("findings", [])) return { "health": mode_result.get("health", "unknown"), "mode": mode, "findings": findings, } async def repair_channel(adapter: WeChatAdapter) -> dict[str, Any]: mode = adapter._mode actions: list[dict[str, Any]] = [] if adapter._banned: actions.append( {"action": "unban", "status": "error", "message": "Channel is banned, requires manual intervention"} ) if mode == "personal" and adapter._bridge_client: result = await repair_bridge(adapter._bridge_client) actions.extend(result.get("actions", [])) return {"repaired": result.get("repaired", False), "actions": actions} if mode in ("wecom", "mp"): actions.append( {"action": "token_refresh", "status": "ok", "message": "Token refresh will be attempted on next connect"} ) return {"repaired": False, "actions": actions}