新增群晖Chat渠道适配器的全套实现,包括: 1. 基础适配器与导出接口定义 2. DSM API认证、探测与会话管理 3. 轮询与Webhook两种消息接收方式 4. 消息去重、格式化与规范化处理 5. 多账号支持与权限安全策略 6. 目录用户/群组发现功能 7. 审批配对与流量控制机制 8. 安全审计与配置检查功能
73 lines
2.1 KiB
Python
73 lines
2.1 KiB
Python
"""Session routing for Synology Chat conversations.
|
|
|
|
Routes incoming messages to agent sessions based on chat type (direct/group),
|
|
user identity, and account for multi-account isolation.
|
|
|
|
DM sessions are keyed by userId to prevent cross-user session confusion
|
|
in shared DM channels. Group sessions are keyed by chat_id since group
|
|
context is shared among all members in the same group.
|
|
|
|
Identity links allow mapping between different representations of the
|
|
same user (e.g. webhook user_id ↔ DSM API user_id).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from yuxi.channels.models import ChannelMessage, ChatType
|
|
|
|
DEFAULT_ACCOUNT_ID = "default"
|
|
|
|
|
|
def resolve_session_route(
|
|
msg: ChannelMessage,
|
|
default_agent_id: str = "default",
|
|
account_id: str = DEFAULT_ACCOUNT_ID,
|
|
) -> str:
|
|
user_id = msg.identity.channel_user_id
|
|
chat_id = msg.identity.channel_chat_id
|
|
chat_type = msg.chat_type
|
|
|
|
if chat_type == ChatType.DIRECT:
|
|
return f"agent:{default_agent_id}:synologychat:{account_id}:direct:{user_id}"
|
|
else:
|
|
return f"agent:{default_agent_id}:synologychat:{account_id}:group:{chat_id}"
|
|
|
|
|
|
def build_identity_link(
|
|
user_id: str,
|
|
account_id: str = DEFAULT_ACCOUNT_ID,
|
|
username: str = "",
|
|
chat_id: str = "",
|
|
) -> dict:
|
|
return {
|
|
"channel": "synologychat",
|
|
"account_id": account_id,
|
|
"user_id": user_id,
|
|
"username": username,
|
|
"chat_id": chat_id,
|
|
}
|
|
|
|
|
|
def resolve_identity_links(
|
|
msg: ChannelMessage,
|
|
account_id: str = DEFAULT_ACCOUNT_ID,
|
|
) -> list[dict]:
|
|
links = [
|
|
build_identity_link(
|
|
user_id=msg.identity.channel_user_id,
|
|
account_id=account_id,
|
|
username=msg.metadata.get("dsm_user_name", "") if msg.metadata else "",
|
|
chat_id=msg.identity.channel_chat_id,
|
|
)
|
|
]
|
|
forwarded_from = msg.metadata.get("forwarded_from") if msg.metadata else None
|
|
if forwarded_from:
|
|
links.append(
|
|
build_identity_link(
|
|
user_id=str(forwarded_from),
|
|
account_id=account_id,
|
|
chat_id=msg.identity.channel_chat_id,
|
|
)
|
|
)
|
|
return links
|