from __future__ import annotations import logging import time import httpx from .config import _apply_env_overrides, _dict_to_account from .constants import BASE_URL, ENDPOINT_USER_GET_INFO, ENDPOINT_USER_PUBLIC_PROFILE, PROBE_TIMEOUT from .types import ProbeResult from .utils import build_auth_headers, create_http_client, flock_api_call logger = logging.getLogger(__name__) async def probe(config: dict, account_id: str = "default") -> ProbeResult: account_data = config.get("accounts", {}).get(account_id, {}) account = _dict_to_account(account_data) account = _apply_env_overrides(account) if not account.bot_token: return ProbeResult(ok=False, reason="bot_token not configured") start = time.monotonic() client = create_http_client(timeout=PROBE_TIMEOUT) try: headers = build_auth_headers(account.bot_token) resp = await client.post( f"{BASE_URL}{ENDPOINT_USER_GET_INFO}", json={}, headers=headers, ) latency_ms = (time.monotonic() - start) * 1000 if resp.status_code == 200: logger.info("Flock probe OK for account %s", account_id) return ProbeResult(ok=True, latency_ms=latency_ms) error_code = _try_extract_error(resp) logger.warning( "Flock probe failed for account %s: %s (HTTP %d)", account_id, error_code, resp.status_code, ) return ProbeResult(ok=False, reason=error_code, latency_ms=latency_ms) except Exception as e: latency_ms = (time.monotonic() - start) * 1000 logger.warning("Flock probe error for account %s: %s", account_id, e) return ProbeResult(ok=False, reason=str(e), latency_ms=latency_ms) finally: await client.aclose() def _try_extract_error(resp: httpx.Response) -> str: try: body = resp.json() return body.get("error", f"HTTP {resp.status_code}") except Exception: return f"HTTP {resp.status_code}" def build_summary(config: dict) -> dict: accounts = config.get("accounts", {}) configured = any(bool(a.get("bot_token") or a.get("incoming_webhook_url")) for a in accounts.values()) return { "channel": "flock", "configured": configured, "accounts_count": len(accounts) if accounts else 1, } def build_account_snapshot(account: dict, config: dict) -> dict: acct = _dict_to_account(account) acct = _apply_env_overrides(acct) return { "account_id": acct.account_id, "configured": bool(acct.bot_token or acct.incoming_webhook_url), "enabled": acct.enabled, "dm_policy": acct.dm_policy, "group_policy": acct.group_policy, } async def get_user_info( user_id: str | None = None, *, config: dict, account_id: str = "default", ) -> dict | None: account_data = config.get("accounts", {}).get(account_id, {}) account = _dict_to_account(account_data) account = _apply_env_overrides(account) if not account.bot_token: logger.warning("Flock get_user_info: bot_token not configured") return None if user_id: payload = {"userId": user_id} endpoint = ENDPOINT_USER_PUBLIC_PROFILE else: payload = {} endpoint = ENDPOINT_USER_GET_INFO client = create_http_client() try: result = await flock_api_call(client, endpoint, account.bot_token, payload) return result except Exception as e: logger.error("Flock get_user_info failed: %s", e) return None finally: await client.aclose()