新增群晖Chat渠道适配器的全套实现,包括: 1. 基础适配器与导出接口定义 2. DSM API认证、探测与会话管理 3. 轮询与Webhook两种消息接收方式 4. 消息去重、格式化与规范化处理 5. 多账号支持与权限安全策略 6. 目录用户/群组发现功能 7. 审批配对与流量控制机制 8. 安全审计与配置检查功能
81 lines
2.3 KiB
Python
81 lines
2.3 KiB
Python
"""Directory adapter for Synology Chat user and channel discovery.
|
|
|
|
Encapsulates DSM user_list and channel_list APIs into a unified directory
|
|
interface for listing peers and groups.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
from dataclasses import dataclass, field
|
|
|
|
from yuxi.channels.adapters.synologychat.client import DSMClient
|
|
from yuxi.utils.logging_config import logger
|
|
|
|
|
|
@dataclass
|
|
class DirectoryPeer:
|
|
id: str
|
|
username: str = ""
|
|
name: str = ""
|
|
is_bot: bool = False
|
|
|
|
|
|
@dataclass
|
|
class DirectoryGroup:
|
|
id: str
|
|
name: str = ""
|
|
member_count: int = 0
|
|
|
|
|
|
@dataclass
|
|
class DirectoryResult:
|
|
peers: list[DirectoryPeer] = field(default_factory=list)
|
|
groups: list[DirectoryGroup] = field(default_factory=list)
|
|
|
|
|
|
async def list_peers(client: DSMClient) -> list[DirectoryPeer]:
|
|
try:
|
|
result = await client.user_list()
|
|
if not result.get("success"):
|
|
logger.warning(f"[SynologyChat] user_list failed: {result.get('error', {})}")
|
|
return []
|
|
users = result.get("data", {}).get("users", [])
|
|
return [
|
|
DirectoryPeer(
|
|
id=str(u.get("user_id", "")),
|
|
username=u.get("username", ""),
|
|
name=u.get("name", ""),
|
|
is_bot=u.get("is_bot", False),
|
|
)
|
|
for u in users
|
|
]
|
|
except Exception as e:
|
|
logger.error(f"[SynologyChat] list_peers failed: {e}")
|
|
return []
|
|
|
|
|
|
async def list_groups(client: DSMClient) -> list[DirectoryGroup]:
|
|
try:
|
|
result = await client.channel_list()
|
|
if not result.get("success"):
|
|
logger.warning(f"[SynologyChat] channel_list failed: {result.get('error', {})}")
|
|
return []
|
|
channels = result.get("data", {}).get("channels", [])
|
|
return [
|
|
DirectoryGroup(
|
|
id=str(c.get("channel_id", "")),
|
|
name=c.get("name", ""),
|
|
member_count=c.get("member_count", 0),
|
|
)
|
|
for c in channels
|
|
]
|
|
except Exception as e:
|
|
logger.error(f"[SynologyChat] list_groups failed: {e}")
|
|
return []
|
|
|
|
|
|
async def get_directory(client: DSMClient) -> DirectoryResult:
|
|
peers, groups = await asyncio.gather(list_peers(client), list_groups(client))
|
|
return DirectoryResult(peers=peers, groups=groups)
|