90 lines
3.0 KiB
Python
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)
|