ForcePilot/backend/package/yuxi/channels/adapters/telegram/directory.py
Kris 71fec609bb feat(telegram-adapter): 实现完整的Telegram适配器基础代码
新增了Telegram适配器的全套基础模块,包括:
1.  核心适配器入口与会话工具
2.  账号管理、认证与配置系统
3.  连接相关的轮询、Webhook、更新偏移管理
4.  话题路由、管理与缓存系统
5.  消息反抖动、超时配置与工具类
6.  响应式UI与命令交互系统
7.  反应表情与通知系统
8.  审批与安全审计模块
9.  健康检查与状态监控
10. 贴纸缓存与视觉工具
11. 流式响应与协作功能
12. 群组迁移与目标归一化处理
2026-05-12 00:49:52 +08:00

111 lines
4.3 KiB
Python

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()]