- 新增钉钉工具调用审计日志功能 - 新增参数校验装饰器与基础工具集(文档、审批、多维表格) - 完善事件类型映射与会话ID生成逻辑 - 新增消息去重、访问策略匹配、配置校验与UI提示 - 新增酷应用卡片、目录管理、表情反应支持 - 优化消息发送逻辑,添加401重试机制 - 新增配置化的权限控制与流式输出支持
113 lines
4.1 KiB
Python
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)
|