新增了Telegram适配器的全套基础模块,包括: 1. 核心适配器入口与会话工具 2. 账号管理、认证与配置系统 3. 连接相关的轮询、Webhook、更新偏移管理 4. 话题路由、管理与缓存系统 5. 消息反抖动、超时配置与工具类 6. 响应式UI与命令交互系统 7. 反应表情与通知系统 8. 审批与安全审计模块 9. 健康检查与状态监控 10. 贴纸缓存与视觉工具 11. 流式响应与协作功能 12. 群组迁移与目标归一化处理
111 lines
4.3 KiB
Python
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()]
|