ForcePilot/backend/package/yuxi/channel/extensions/feishu/ws_client.py
Kris 5e91bb9985 feat(feishu): 新增飞书渠道完整插件实现
新增飞书渠道插件,包含基础配置、事件处理、消息收发、工具调用、权限管理等完整功能模块,支持WebSocket长连接、卡片消息、流式响应、群管理、审批通知等能力
2026-05-21 10:46:42 +08:00

83 lines
2.5 KiB
Python

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)