from __future__ import annotations import logging import time from yuxi.channel.extensions.feishu.client import get_client, get_bot_info logger = logging.getLogger(__name__) _probe_cache: dict[str, dict] = {} PROBE_CACHE_MAX = 64 PROBE_TTL_SUCCESS = 600 PROBE_TTL_FAILURE = 60 async def probe_feishu(app_id: str, app_secret: str, domain: str = "feishu", http_timeout_ms: int = 30000) -> dict: cache_key = f"{app_id}:{domain}" cached = _probe_cache.get(cache_key) now = time.monotonic() if cached: ttl = PROBE_TTL_SUCCESS if cached["ok"] else PROBE_TTL_FAILURE if now - cached["ts"] < ttl: return cached result = {"ok": False, "app_id": app_id, "bot_name": "", "bot_open_id": ""} try: client = get_client(app_id, app_secret, domain, http_timeout_ms) info = await get_bot_info(client) if info: result["ok"] = True result["bot_name"] = info.get("bot_name", "") result["bot_open_id"] = info.get("open_id", "") result["activate_status"] = info.get("activate_status", 0) except Exception: logger.debug("Feishu probe failed for %s", app_id, exc_info=True) result["ts"] = now _probe_cache[cache_key] = result if len(_probe_cache) > PROBE_CACHE_MAX: oldest = min(_probe_cache, key=lambda k: _probe_cache[k]["ts"]) del _probe_cache[oldest] return result async def probe_account(account: dict) -> bool: app_id = account.get("app_id") or account.get("appId", "") app_secret = account.get("app_secret") or account.get("appSecret", "") domain = account.get("domain", "feishu") http_timeout_ms = account.get("http_timeout_ms", 30000) if not app_id or not app_secret: return False result = await probe_feishu(app_id, app_secret, domain, http_timeout_ms) return result.get("ok", False)