from __future__ import annotations from typing import Any import httpx from yuxi.utils.logging_config import logger TELEGRAM_API_BASE = "https://api.telegram.org" async def _telegram_api(token: str, method: str, params: dict | None = None) -> dict[str, Any]: url = f"{TELEGRAM_API_BASE}/bot{token}/{method}" async with httpx.AsyncClient(timeout=httpx.Timeout(15.0)) as client: resp = await client.post(url, json=params or {}) return resp.json() async def list_peers(config: dict[str, Any], account_id: str = "default") -> list[dict[str, Any]]: token = config.get("bot_token", "") if not token: logger.warning("[Telegram/Directory] No bot_token in config, cannot list peers") return [] monitored_chats = config.get("monitored_chats", []) results: list[dict[str, Any]] = [] for chat_id_str in monitored_chats: try: chat_id = int(chat_id_str) if chat_id_str.lstrip("-").isdigit() else chat_id_str data = await _telegram_api(token, "getChat", {"chat_id": chat_id}) if not data.get("ok"): continue chat = data.get("result", {}) ctype = chat.get("type", "") if ctype in ("private", "group", "supergroup"): administrators = await _telegram_api(token, "getChatAdministrators", {"chat_id": chat_id}) if administrators.get("ok"): for admin in administrators.get("result", []): user = admin.get("user", {}) uid = user.get("id") uname = user.get("first_name", "") or user.get("username", "") or str(uid) results.append( { "id": f"tg:{uid}", "name": uname, "chat_id": str(chat_id), "chat_title": chat.get("title", ""), "is_admin": True, } ) member_count_data = await _telegram_api(token, "getChatMemberCount", {"chat_id": chat_id}) if member_count_data.get("ok"): count = member_count_data.get("result", 0) if count > len([r for r in results if r.get("chat_id") == str(chat_id)]): pass except Exception as e: logger.warning(f"[Telegram/Directory] Failed to list peers for chat {chat_id_str}: {e}") continue return results async def list_groups(config: dict[str, Any], account_id: str = "default") -> list[dict[str, Any]]: token = config.get("bot_token", "") if not token: logger.warning("[Telegram/Directory] No bot_token in config, cannot list groups") return [] monitored_chats = config.get("monitored_chats", []) results: list[dict[str, Any]] = [] for chat_id_str in monitored_chats: try: chat_id = int(chat_id_str) if chat_id_str.lstrip("-").isdigit() else chat_id_str data = await _telegram_api(token, "getChat", {"chat_id": chat_id}) if not data.get("ok"): continue chat = data.get("result", {}) ctype = chat.get("type", "") if ctype in ("group", "supergroup"): count_data = await _telegram_api(token, "getChatMemberCount", {"chat_id": chat_id}) member_count = count_data.get("result", 0) if count_data.get("ok") else 0 results.append( { "id": f"tg:group:{chat_id}", "name": chat.get("title", str(chat_id)), "type": ctype, "member_count": member_count, "description": chat.get("description", ""), } ) except Exception as e: logger.warning(f"[Telegram/Directory] Failed to list groups for chat {chat_id_str}: {e}") continue return results async def search_peers(config: dict[str, Any], query: str) -> list[dict[str, Any]]: all_peers = await list_peers(config) query_lower = query.lower() return [p for p in all_peers if query_lower in p.get("name", "").lower() or query_lower in p.get("id", "").lower()]