ForcePilot/backend/package/yuxi/channels/adapters/dingding/stream_handler.py
Kris 9c01d480cc feat(dingding): 完整实现钉钉适配器功能模块
- 新增钉钉工具调用审计日志功能
- 新增参数校验装饰器与基础工具集(文档、审批、多维表格)
- 完善事件类型映射与会话ID生成逻辑
- 新增消息去重、访问策略匹配、配置校验与UI提示
- 新增酷应用卡片、目录管理、表情反应支持
- 优化消息发送逻辑,添加401重试机制
- 新增配置化的权限控制与流式输出支持
2026-05-13 16:06:10 +08:00

113 lines
4.1 KiB
Python

from __future__ import annotations
import logging
from typing import TYPE_CHECKING
from yuxi.channels.models import EventType
logger = logging.getLogger(__name__)
if TYPE_CHECKING:
from yuxi.channels.adapters.dingding.adapter import DingDingChannelAdapter
HAS_DINGTALK_STREAM = False
try:
import dingtalk_stream
HAS_DINGTALK_STREAM = True
except ImportError:
dingtalk_stream = None
class DingDingChatbotHandler:
def __init__(self, adapter: DingDingChannelAdapter):
self._adapter = adapter
async def process(self, callback: object) -> tuple[int, str]:
if not HAS_DINGTALK_STREAM:
return 200, "OK"
from dingtalk_stream import AckMessage
try:
raw_data = getattr(callback, "data", {})
session_webhook = getattr(callback, "sessionWebhook", None) or raw_data.get("sessionWebhook", "")
if session_webhook:
self._adapter._session_webhooks[raw_data.get("conversationId", "")] = session_webhook
msg = self._adapter.normalize_inbound(raw_data)
await self._adapter._handle_message(msg)
return AckMessage.STATUS_OK, "OK"
except Exception as e:
logger.error(f"[DingDing] ChatbotHandler error: {e}")
return AckMessage.STATUS_INTERNAL_SERVER_ERROR, str(e)
class DingDingCallbackHandler:
def __init__(self, adapter: DingDingChannelAdapter):
self._adapter = adapter
async def process(self, callback: object) -> tuple[int, str]:
if not HAS_DINGTALK_STREAM:
return 200, "OK"
from dingtalk_stream import AckMessage
try:
raw_data = getattr(callback, "data", {})
msg = self._adapter.normalize_inbound(raw_data)
msg.event_type = EventType.CARD_ACTION
await self._adapter._handle_message(msg)
return AckMessage.STATUS_OK, "OK"
except Exception as e:
logger.error(f"[DingDing] CallbackHandler error: {e}")
return AckMessage.STATUS_INTERNAL_SERVER_ERROR, str(e)
class DingDingEventHandler:
def __init__(self, adapter: DingDingChannelAdapter):
self._adapter = adapter
async def process(self, callback: object) -> tuple[int, str]:
if not HAS_DINGTALK_STREAM:
return 200, "OK"
from dingtalk_stream import AckMessage
try:
raw_data = getattr(callback, "data", {})
event_type_raw = raw_data.get("eventType", raw_data.get("event_type", ""))
event_type_map = {
"chat_update_title": EventType.CHANNEL_UPDATED,
"chat_update_owner": EventType.CHANNEL_UPDATED,
"chat_update_icon": EventType.CHANNEL_UPDATED,
"chat_update_extension": EventType.CHANNEL_UPDATED,
"chat_member_add": EventType.MEMBER_JOINED,
"chat_member_remove": EventType.MEMBER_LEFT,
"chat_member_admin_add": EventType.CHANNEL_UPDATED,
"chat_member_admin_remove": EventType.CHANNEL_UPDATED,
"chat_add": EventType.CHANNEL_CREATED,
"chat_disband": EventType.CHANNEL_DELETED,
"org_dept_create": EventType.SYSTEM_EVENT,
"org_dept_modify": EventType.SYSTEM_EVENT,
"org_dept_remove": EventType.SYSTEM_EVENT,
"org_user_add": EventType.SYSTEM_EVENT,
"org_user_modify": EventType.SYSTEM_EVENT,
"org_user_leave": EventType.SYSTEM_EVENT,
"bot_added_to_group": EventType.BOT_ADDED,
"bot_removed_from_group": EventType.BOT_REMOVED,
"check_url": EventType.SYSTEM_EVENT,
}
event_type = event_type_map.get(event_type_raw, EventType.SYSTEM_EVENT)
msg = self._adapter.normalize_inbound(raw_data)
msg.event_type = event_type
await self._adapter._handle_message(msg)
return AckMessage.STATUS_OK, "OK"
except Exception as e:
logger.error(f"[DingDing] EventHandler error: {e}")
return AckMessage.STATUS_INTERNAL_SERVER_ERROR, str(e)