from __future__ import annotations import httpx from typing import Any, Dict, Optional class CFClient: def __init__(self, worker1_url: str, worker2_url: str, bot_backend_key: str, hf_api_key: str): self.w1 = worker1_url.rstrip("/") self.w2 = worker2_url.rstrip("/") self.bot_backend_key = bot_backend_key self.hf_api_key = hf_api_key self._client = httpx.AsyncClient(timeout=httpx.Timeout(60.0, read=120.0)) async def close(self): await self._client.aclose() # ---------- Worker2 (HF-only) ---------- async def is_allowed(self, tg_id: str) -> bool: r = await self._client.post( f"{self.w2}/api/is_allowed", headers={"Authorization": f"Bearer {self.hf_api_key}"}, json={"tg_id": tg_id}, ) if r.status_code != 200: return False j = r.json() return bool(j.get("allowed", False)) async def allow_user(self, tg_id: str) -> Dict[str, Any]: return await self._post_w2("/api/allow_user", {"tg_id": tg_id}) async def disallow_user(self, tg_id: str) -> Dict[str, Any]: return await self._post_w2("/api/disallow_user", {"tg_id": tg_id}) async def list_profiles_w2(self, tg_id: str) -> Dict[str, Any]: return await self._post_w2("/api/list_profiles", {"tg_id": tg_id}) async def pick_profile(self, tg_id: str, channel_id: str, rotate_after: int) -> Dict[str, Any]: return await self._post_w2("/api/pick_profile", {"tg_id": tg_id, "channel_id": channel_id, "rotate_after": rotate_after}) async def access_token(self, tg_id: str, profile_id: str) -> Dict[str, Any]: return await self._post_w2("/api/access_token", {"tg_id": tg_id, "profile_id": profile_id}) async def record_upload(self, tg_id: str, profile_id: str) -> Dict[str, Any]: return await self._post_w2("/api/record_upload", {"tg_id": tg_id, "profile_id": profile_id}) async def stats_today(self) -> Dict[str, Any]: return await self._post_w2("/api/stats_today", {}) async def log_error(self, tg_id: str, profile_id: str, where: str, err: str) -> None: try: await self._post_w2("/api/log_error", {"tg_id": tg_id, "profile_id": profile_id, "where": where, "err": err}) except Exception: pass async def _post_w2(self, path: str, body: Dict[str, Any]) -> Dict[str, Any]: r = await self._client.post( f"{self.w2}{path}", headers={"Authorization": f"Bearer {self.hf_api_key}"}, json=body, ) try: return r.json() except Exception: return {"ok": False, "err": f"bad_json_{r.status_code}"} # ---------- Worker1 (BOT backend key) ---------- async def profile_add(self, tg_id: str, client_id: str, client_secret: str, label: str = "main", ttl_sec: int = 600) -> Dict[str, Any]: r = await self._client.post( f"{self.w1}/api/profile/add", headers={"Authorization": f"Bearer {self.bot_backend_key}"}, json={"tg_id": tg_id, "client_id": client_id, "client_secret": client_secret, "label": label, "ttl_sec": ttl_sec}, ) try: return r.json() except Exception: return {"ok": False, "err": f"bad_json_{r.status_code}"} async def profile_list_w1(self, tg_id: str) -> Dict[str, Any]: r = await self._client.post( f"{self.w1}/api/profile/list", headers={"Authorization": f"Bearer {self.bot_backend_key}"}, json={"tg_id": tg_id}, ) try: return r.json() except Exception: return {"ok": False, "err": f"bad_json_{r.status_code}"} async def profile_set_default(self, tg_id: str, profile_id: str) -> Dict[str, Any]: r = await self._client.post( f"{self.w1}/api/profile/set_default", headers={"Authorization": f"Bearer {self.bot_backend_key}"}, json={"tg_id": tg_id, "profile_id": profile_id}, ) try: return r.json() except Exception: return {"ok": False, "err": f"bad_json_{r.status_code}"} async def profile_remove(self, tg_id: str, profile_id: str) -> Dict[str, Any]: r = await self._client.post( f"{self.w1}/api/profile/remove", headers={"Authorization": f"Bearer {self.bot_backend_key}"}, json={"tg_id": tg_id, "profile_id": profile_id}, ) try: return r.json() except Exception: return {"ok": False, "err": f"bad_json_{r.status_code}"}