新增 Synology Chat 渠道扩展,支持在 Yuxi 平台中集成群晖 Synology Chat 即时通讯渠道。 包含以下功能模块: - client: Synology Chat API 客户端封装 - accounts: 账户管理 - webhook: Webhook 事件处理 - security: 安全校验 - dedupe: 消息去重 - status: 会话状态管理 - session: 会话管理 - types: 类型定义
76 lines
3.2 KiB
Python
76 lines
3.2 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
|
|
from yuxi.channel.extensions.synology_chat.types import (
|
|
ACCOUNT_ID_DEFAULT,
|
|
BOT_NAME_DEFAULT,
|
|
RATE_LIMIT_DEFAULT,
|
|
WEBHOOK_PATH_DEFAULT,
|
|
WEBHOOK_PATH_SOURCE_DEFAULT,
|
|
WEBHOOK_PATH_SOURCE_EXPLICIT,
|
|
WEBHOOK_PATH_SOURCE_INHERITED,
|
|
DM_POLICY_ALLOWLIST,
|
|
ResolvedSynologyChatAccount,
|
|
)
|
|
|
|
|
|
def list_account_ids(config: dict) -> list[str]:
|
|
channel_cfg = config.get("channels", {}).get("synology-chat", {})
|
|
base_ids = [ACCOUNT_ID_DEFAULT]
|
|
named = list(channel_cfg.get("accounts", {}).keys())
|
|
return base_ids + named
|
|
|
|
|
|
def resolve_account(config: dict, account_id: str = ACCOUNT_ID_DEFAULT) -> ResolvedSynologyChatAccount:
|
|
channel_cfg = config.get("channels", {}).get("synology-chat", {})
|
|
account_overrides = channel_cfg.get("accounts", {}).get(account_id, {}) if account_id != ACCOUNT_ID_DEFAULT else {}
|
|
|
|
def _resolve(key: str, env_var: str | None = None, default: str | int | bool = "") -> str | int | bool:
|
|
if key in account_overrides:
|
|
return account_overrides[key]
|
|
if key in channel_cfg:
|
|
return channel_cfg[key]
|
|
if env_var and account_id == ACCOUNT_ID_DEFAULT:
|
|
env_val = os.environ.get(env_var, "")
|
|
if env_val:
|
|
return env_val
|
|
return default
|
|
|
|
def _resolve_list(key: str) -> list[str]:
|
|
if key in account_overrides:
|
|
val = account_overrides[key]
|
|
return val if isinstance(val, list) else []
|
|
if key in channel_cfg:
|
|
val = channel_cfg[key]
|
|
return val if isinstance(val, list) else []
|
|
if account_id == ACCOUNT_ID_DEFAULT:
|
|
env_val = os.environ.get("SYNOLOGY_ALLOWED_USER_IDS", "")
|
|
if env_val:
|
|
return [u.strip() for u in env_val.split(",") if u.strip()]
|
|
return []
|
|
|
|
def _resolve_webhook_path_source() -> str:
|
|
if account_overrides.get("webhookPath"):
|
|
return WEBHOOK_PATH_SOURCE_EXPLICIT
|
|
if account_id != ACCOUNT_ID_DEFAULT and channel_cfg.get("webhookPath"):
|
|
return WEBHOOK_PATH_SOURCE_INHERITED
|
|
return WEBHOOK_PATH_SOURCE_DEFAULT
|
|
|
|
return ResolvedSynologyChatAccount(
|
|
account_id=account_id,
|
|
enabled=bool(_resolve("enabled", default=True)),
|
|
token=str(_resolve("token", "SYNOLOGY_CHAT_TOKEN")),
|
|
incoming_url=str(_resolve("incomingUrl", "SYNOLOGY_CHAT_INCOMING_URL")),
|
|
nas_host=str(_resolve("nasHost", "SYNOLOGY_NAS_HOST", "localhost")),
|
|
webhook_path=str(_resolve("webhookPath", default=WEBHOOK_PATH_DEFAULT)),
|
|
webhook_path_source=_resolve_webhook_path_source(),
|
|
dm_policy=str(_resolve("dmPolicy", default=DM_POLICY_ALLOWLIST)),
|
|
allowed_user_ids=_resolve_list("allowedUserIds"),
|
|
rate_limit_per_minute=int(_resolve("rateLimitPerMinute", "SYNOLOGY_RATE_LIMIT", RATE_LIMIT_DEFAULT)),
|
|
bot_name=str(_resolve("botName", "OPENCLAW_BOT_NAME", BOT_NAME_DEFAULT)),
|
|
allow_insecure_ssl=bool(_resolve("allowInsecureSsl", default=False)),
|
|
dangerously_allow_name_matching=bool(_resolve("dangerouslyAllowNameMatching", default=False)),
|
|
dangerously_allow_inherited_webhook_path=bool(_resolve("dangerouslyAllowInheritedWebhookPath", default=False)),
|
|
)
|