实现了完整的Nextcloud Talk聊天适配器,包含以下核心功能: 1. 基础客户端通信与认证 2. 会话路由与聊天类型解析 3. 消息分块与格式转换 4. 用户配对与权限校验 5. 轮询式消息监听 6. 配置验证与诊断工具 7. 安全策略与去重缓存 8. 指标统计与状态快照 新增配套的配对用户缓存文件与模块导出入口。
83 lines
2.5 KiB
Python
83 lines
2.5 KiB
Python
from __future__ import annotations
|
|
|
|
import copy
|
|
import logging
|
|
from typing import Any
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
DEFAULT_ACCOUNT_ID = "default"
|
|
|
|
|
|
class NcAccountConfig:
|
|
def __init__(self, account_id: str, config: dict[str, Any] | None = None):
|
|
self.account_id = account_id
|
|
self.config = config or {}
|
|
|
|
@property
|
|
def server_url(self) -> str:
|
|
return self.config.get("server_url", self.config.get("baseUrl", ""))
|
|
|
|
@property
|
|
def bot_user(self) -> str:
|
|
return self.config.get("bot_user", self.config.get("botUser", ""))
|
|
|
|
@property
|
|
def app_password(self) -> str:
|
|
return self.config.get("app_password", self.config.get("appPassword", ""))
|
|
|
|
@property
|
|
def display_name(self) -> str:
|
|
return self.config.get("display_name", self.config.get("displayName", "ForcePilot Bot"))
|
|
|
|
@property
|
|
def dm_policy(self) -> str:
|
|
return self.config.get("dm_policy", self.config.get("dmPolicy", "pairing"))
|
|
|
|
@property
|
|
def group_policy(self) -> str:
|
|
return self.config.get("group_policy", self.config.get("groupPolicy", "allowlist"))
|
|
|
|
|
|
def resolve_nc_account(account_id: str, channel_config: dict[str, Any]) -> NcAccountConfig | None:
|
|
accounts = channel_config.get("accounts", {})
|
|
|
|
if account_id == DEFAULT_ACCOUNT_ID and not accounts:
|
|
return NcAccountConfig(DEFAULT_ACCOUNT_ID, channel_config)
|
|
|
|
account_cfg = accounts.get(account_id)
|
|
if not account_cfg:
|
|
return None
|
|
|
|
merged = resolve_merged_config(account_id, channel_config)
|
|
return NcAccountConfig(account_id, merged)
|
|
|
|
|
|
def resolve_merged_config(account_id: str, channel_config: dict[str, Any]) -> dict[str, Any]:
|
|
base = {k: v for k, v in channel_config.items() if k not in ("accounts",)}
|
|
accounts = channel_config.get("accounts", {})
|
|
account_cfg = accounts.get(account_id, {})
|
|
|
|
merged = copy.deepcopy(base)
|
|
_deep_merge(merged, account_cfg)
|
|
return merged
|
|
|
|
|
|
def _deep_merge(base: dict, override: dict) -> None:
|
|
for key, value in override.items():
|
|
if key in base and isinstance(base[key], dict) and isinstance(value, dict):
|
|
_deep_merge(base[key], value)
|
|
else:
|
|
base[key] = value
|
|
|
|
|
|
def list_nc_accounts(channel_config: dict[str, Any]) -> list[str]:
|
|
accounts = channel_config.get("accounts", {})
|
|
if not accounts:
|
|
return [DEFAULT_ACCOUNT_ID]
|
|
return [DEFAULT_ACCOUNT_ID] + [k for k in accounts if k != DEFAULT_ACCOUNT_ID]
|
|
|
|
|
|
def resolve_default_account_id(channel_config: dict[str, Any]) -> str:
|
|
return DEFAULT_ACCOUNT_ID
|