新增 Zalo OA、Zoom Chat、Zulip 三个渠道扩展。 Zalo OA 渠道扩展主要模块:sidecar_client, config, gateway, outbound, streaming, pairing, security, auth, dedupe, directory, monitor, status, session, reactions, tools Zoom Chat 渠道扩展主要模块:config, gateway, webhook, outbound, streaming, pairing, security, crypto, dedupe, actions, media, mentions, monitor, status, session, reactions, threading Zulip 渠道扩展主要模块:client, config, gateway, outbound, streaming, pairing, security, monitor, status
155 lines
6.8 KiB
Python
155 lines
6.8 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
|
|
from yuxi.channel.extensions.zalouser.sidecar_client import ZcaSidecarClient
|
|
|
|
DEFAULT_SIDECAR_URL = "http://localhost:3001"
|
|
|
|
|
|
class ZaloUserConfigAdapter:
|
|
def __init__(self):
|
|
self._config_cache: dict | None = None
|
|
|
|
def set_runtime_config(self, config: dict) -> None:
|
|
self._config_cache = config
|
|
|
|
def list_account_ids(self, config: dict) -> list[str]:
|
|
channels = config.get("channels", config)
|
|
zalouser_cfg = channels.get("zalouser", channels)
|
|
accounts = zalouser_cfg.get("accounts", {})
|
|
return list(accounts.keys()) if accounts else ["default"]
|
|
|
|
def resolve_sidecar_url(self, account: dict) -> str:
|
|
sidecar_url = account.get("sidecar_url", "")
|
|
if sidecar_url:
|
|
return sidecar_url
|
|
return os.getenv("ZALOUSER_SIDECAR_URL", DEFAULT_SIDECAR_URL)
|
|
|
|
def resolve_profile(self, account: dict) -> str:
|
|
profile = account.get("profile")
|
|
if profile:
|
|
return profile
|
|
return os.getenv("ZALOUSER_PROFILE", os.getenv("ZCA_PROFILE", "default"))
|
|
|
|
async def resolve_account(self, account_id: str) -> dict:
|
|
config = self._read_channel_config()
|
|
accounts = config.get("accounts", {})
|
|
account = accounts.get(account_id, {})
|
|
profile = self.resolve_profile(account)
|
|
|
|
sidecar_url = self.resolve_sidecar_url(account)
|
|
|
|
return {
|
|
"account_id": account_id,
|
|
"profile": profile,
|
|
"name": account.get("name", account_id),
|
|
"sidecar_url": sidecar_url,
|
|
"ping_interval": account.get("ping_interval", 30),
|
|
"ping_timeout": account.get("ping_timeout", 10),
|
|
"dm_policy": account.get("dm_policy", config.get("dm_policy", "pairing")),
|
|
"allow_from": account.get("allow_from", config.get("allow_from", [])),
|
|
"group_policy": account.get("group_policy", config.get("group_policy", "allowlist")),
|
|
"group_allow_from": account.get("group_allow_from", config.get("group_allow_from", [])),
|
|
"groups": account.get("groups", config.get("groups", {})),
|
|
"dangerously_allow_name_matching": account.get(
|
|
"dangerously_allow_name_matching",
|
|
config.get("dangerously_allow_name_matching", False),
|
|
),
|
|
"history_limit": account.get("history_limit", config.get("history_limit", 50)),
|
|
"text_chunk_limit": account.get("text_chunk_limit", config.get("text_chunk_limit", 2000)),
|
|
"message_prefix": account.get("message_prefix", config.get("message_prefix", "")),
|
|
"response_prefix": account.get("response_prefix", config.get("response_prefix", "")),
|
|
"config": config,
|
|
}
|
|
|
|
def is_configured(self, account: dict) -> bool:
|
|
return bool(account.get("sidecar_url", ""))
|
|
|
|
def is_enabled(self, account: dict, config: dict) -> bool:
|
|
return account.get("enabled", True) if isinstance(account.get("enabled"), bool) else True
|
|
|
|
def disabled_reason(self, account: dict, config: dict) -> str:
|
|
if not account.get("sidecar_url"):
|
|
return "Sidecar URL is required (set ZALOUSER_SIDECAR_URL env or configure sidecar_url)"
|
|
return ""
|
|
|
|
async def resolve_allow_from(self, config: dict, account_id: str) -> list[str] | None:
|
|
account = await self.resolve_account(account_id)
|
|
return account.get("allow_from", [])
|
|
|
|
def describe_account(self, account: dict) -> dict:
|
|
return {
|
|
"account_id": account.get("account_id", ""),
|
|
"name": account.get("name", ""),
|
|
"configured": self.is_configured(account),
|
|
"sidecar_url": account.get("sidecar_url", ""),
|
|
}
|
|
|
|
def config_schema(self) -> dict:
|
|
return {
|
|
"type": "object",
|
|
"properties": {
|
|
"enabled": {"type": "boolean", "default": True},
|
|
"default_account": {"type": "string", "default": "default"},
|
|
"accounts": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"profile": {"type": "string", "default": "default"},
|
|
"name": {"type": "string"},
|
|
"sidecar_url": {"type": "string"},
|
|
"dm_policy": {
|
|
"type": "string",
|
|
"enum": ["pairing", "allowlist", "open", "disabled"],
|
|
"default": "pairing",
|
|
},
|
|
"allow_from": {
|
|
"type": "array",
|
|
"items": {"type": "string"},
|
|
},
|
|
"group_policy": {
|
|
"type": "string",
|
|
"enum": ["open", "allowlist", "disabled"],
|
|
"default": "allowlist",
|
|
},
|
|
"group_allow_from": {
|
|
"type": "array",
|
|
"items": {"type": "string"},
|
|
},
|
|
"groups": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"enabled": {"type": "boolean", "default": True},
|
|
"require_mention": {"type": "boolean", "default": True},
|
|
},
|
|
},
|
|
},
|
|
"dangerously_allow_name_matching": {
|
|
"type": "boolean",
|
|
"default": False,
|
|
},
|
|
"history_limit": {"type": "integer", "default": 50},
|
|
"text_chunk_limit": {"type": "integer", "default": 2000},
|
|
"message_prefix": {"type": "string", "default": ""},
|
|
"response_prefix": {"type": "string", "default": ""},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
def build_sidecar_client(self, account: dict) -> ZcaSidecarClient:
|
|
return ZcaSidecarClient(
|
|
account.get("sidecar_url", DEFAULT_SIDECAR_URL),
|
|
profile=account.get("profile", "default"),
|
|
)
|
|
|
|
def _read_channel_config(self) -> dict:
|
|
if self._config_cache:
|
|
channels = self._config_cache.get("channels", self._config_cache)
|
|
return channels.get("zalouser", self._config_cache)
|
|
return {} |