from __future__ import annotations import asyncio import logging from yuxi.channel.extensions.feishu.client import get_ws_client, HAS_LARK_SDK from yuxi.channel.extensions.feishu.errors import FeishuConnectionError from yuxi.channel.extensions.feishu.types import FeishuAccount logger = logging.getLogger(__name__) class FeishuWSClient: def __init__( self, account: FeishuAccount, *, ping_interval: int = 30, ping_timeout: int = 3, ): self._account = account self._ping_interval = ping_interval self._ping_timeout = ping_timeout self._ws: object | None = None self._running = False self._event_handlers: dict[str, list] = {} @property def is_running(self) -> bool: return self._running def on_event(self, event_type: str, handler): if event_type not in self._event_handlers: self._event_handlers[event_type] = [] self._event_handlers[event_type].append(handler) async def start(self) -> None: if not HAS_LARK_SDK: raise FeishuConnectionError("lark-oapi SDK is required. Install with: pip install lark-oapi") self._running = True try: self._ws = get_ws_client( self._account.app_id, self._account.app_secret, self._account.domain, ) import lark_oapi dispatcher = lark_oapi.event.EventDispatcher.builder( self._account.encrypt_key or "", self._account.verification_token or "", ).build() self._register_default_handlers(dispatcher) self._ws.start(dispatcher) logger.info("Feishu WS client started for account %s", self._account.account_id) except Exception as e: self._running = False raise FeishuConnectionError(f"Failed to start Feishu WS client: {e}") async def stop(self) -> None: self._running = False if self._ws: try: self._ws.stop() except Exception: logger.debug("Error stopping Feishu WS client", exc_info=True) def _register_default_handlers(self, dispatcher) -> None: import lark_oapi for event_type, handlers in self._event_handlers.items(): for handler in handlers: async def wrapped(req: lark_oapi.event.BaseEvent, h=handler, et=event_type): await h(et, req.event) dispatcher.register(event_type, wrapped)