ForcePilot/backend/package/yuxi/channel/extensions/telegram/gateway.py
Kris 8a3601250e feat(channel): 添加 Telegram 渠道扩展
新增 Telegram 渠道扩展,支持在 Yuxi 平台中集成 Telegram 即时通讯渠道。

包含以下功能模块:
- config: 渠道配置管理
- gateway: SSE/WebSocket 网关接入
- webhook: Webhook 事件处理
- polling: 长轮询模式
- outbound: 外发消息管理
- streaming: 流式消息处理
- pairing: 用户配对与绑定
- security: 安全校验
- dedupe: 消息去重
- monitor: 渠道状态监控
- status: 会话状态管理
- session: 会话管理
- actions: 动作处理
- inline_keyboard: 内联键盘
- native_commands: 原生指令
- chat: 聊天管理
- delivery: 消息送达确认
- media: 媒体资源处理
- profile: 用户资料
- reactions: 表情反应
- sticker: 贴纸处理
- types: 类型定义
2026-05-21 11:48:09 +08:00

90 lines
3.0 KiB
Python

from __future__ import annotations
import asyncio
import logging
from yuxi.channel.extensions.telegram.config import TelegramConfigAdapter
from yuxi.channel.extensions.telegram.polling import TelegramPolling
logger = logging.getLogger(__name__)
class TelegramGateway:
def __init__(self):
self._config_adapter = TelegramConfigAdapter()
self._polling = TelegramPolling()
self._tasks: list[asyncio.Task] = []
self._running = False
self._queue: asyncio.Queue | None = None
self._abort_event: asyncio.Event | None = None
self._account: dict = {}
async def start(self, ctx) -> object:
account = await self._resolve_account(ctx)
self._account = account
if not account.get("token"):
logger.warning("telegram account %s not configured, skipping start", account.get("account_id"))
return {"running": False, "reason": "not-configured"}
self._queue = asyncio.Queue(maxsize=1000)
self._abort_event = asyncio.Event()
self._running = True
webhook_url = account.get("webhook_url", "")
if webhook_url:
task = asyncio.create_task(
self._start_webhook_mode(account, self._queue, self._abort_event)
)
else:
task = asyncio.create_task(
self._polling.start(account, self._queue, self._abort_event)
)
self._tasks.append(task)
logger.info("telegram gateway started for account %s (mode=%s)", account.get("account_id"),
"webhook" if webhook_url else "polling")
return {"running": True, "account_id": account.get("account_id"), "queue": self._queue}
async def stop(self, ctx) -> None:
self._running = False
if self._abort_event:
self._abort_event.set()
await self._polling.stop()
for task in self._tasks:
task.cancel()
self._tasks.clear()
if self._account.get("webhook_url"):
from yuxi.channel.extensions.telegram.webhook import stop_webhook
await stop_webhook(self._account)
from yuxi.channel.extensions.telegram.outbound import TelegramOutbound
await TelegramOutbound.close_client()
self._queue = None
self._abort_event = None
self._account = {}
logger.info("telegram gateway stopped")
async def _start_webhook_mode(self, account: dict, queue: asyncio.Queue, abort_event: asyncio.Event) -> None:
from yuxi.channel.extensions.telegram.webhook import start_webhook
await start_webhook(account, queue)
while not abort_event.is_set():
await asyncio.sleep(1)
async def _resolve_account(self, ctx) -> dict:
config = getattr(ctx, "config", {}) if ctx else {}
account_id = getattr(ctx, "account_id", "default")
self._config_adapter.list_account_ids(config)
return await self._config_adapter.resolve_account(account_id)