新增 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
158 lines
6.9 KiB
Python
158 lines
6.9 KiB
Python
import os
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
ENV_PREFIX = "ZOOMCHAT"
|
|
|
|
|
|
class ZoomConfigAdapter:
|
|
def __init__(self, config: dict | None = None):
|
|
self._config = config or {}
|
|
|
|
def list_account_ids(self, config: dict) -> list[str]:
|
|
accounts = config.get("accounts", {})
|
|
if not accounts:
|
|
return ["default"] if self._env_client_id() else []
|
|
return list(accounts.keys())
|
|
|
|
async def resolve_account(self, account_id: str = "default") -> dict:
|
|
accounts = self._get_raw_accounts()
|
|
raw = accounts.get(account_id, {})
|
|
|
|
if account_id == "default":
|
|
client_id = raw.get("client_id") or self._env_client_id()
|
|
client_secret = raw.get("client_secret") or os.environ.get(f"{ENV_PREFIX}_CLIENT_SECRET", "")
|
|
account_id_zoom = raw.get("account_id") or os.environ.get(f"{ENV_PREFIX}_ACCOUNT_ID", "")
|
|
webhook_secret = raw.get("webhook_secret") or os.environ.get(f"{ENV_PREFIX}_WEBHOOK_SECRET", "")
|
|
else:
|
|
upper = account_id.upper()
|
|
client_id = raw.get("client_id") or os.environ.get(f"{ENV_PREFIX}_CLIENT_ID_{upper}", "")
|
|
client_secret = raw.get("client_secret") or os.environ.get(f"{ENV_PREFIX}_CLIENT_SECRET_{upper}", "")
|
|
account_id_zoom = raw.get("account_id") or os.environ.get(f"{ENV_PREFIX}_ACCOUNT_ID_{upper}", "")
|
|
webhook_secret = raw.get("webhook_secret") or os.environ.get(f"{ENV_PREFIX}_WEBHOOK_SECRET_{upper}", "")
|
|
|
|
return {
|
|
"account_id": account_id_zoom,
|
|
"client_id": client_id,
|
|
"client_secret": client_secret,
|
|
"webhook_secret": webhook_secret,
|
|
"bot_user_id": raw.get("bot_user_id", ""),
|
|
"name": raw.get("name", account_id),
|
|
"dm_policy": raw.get("dm_policy", "open"),
|
|
"group_policy": raw.get("group_policy", "mentioned"),
|
|
"allow_from": raw.get("allow_from", []),
|
|
"api_base_url": raw.get("api_base_url", "https://api.zoom.us/v2"),
|
|
"text_chunk_limit": raw.get("text_chunk_limit", 3800),
|
|
"chunk_mode": raw.get("chunk_mode", "length"),
|
|
"webhook_host": raw.get("webhook_host", "0.0.0.0"),
|
|
"webhook_port": raw.get("webhook_port", 0),
|
|
"enabled": raw.get("enabled", True),
|
|
}
|
|
|
|
def is_configured(self, account: dict) -> bool:
|
|
return bool(
|
|
account.get("account_id")
|
|
and account.get("client_id")
|
|
and account.get("client_secret")
|
|
and account.get("webhook_secret")
|
|
)
|
|
|
|
def is_enabled(self, account: dict) -> bool:
|
|
return account.get("enabled", True)
|
|
|
|
def disabled_reason(self, account: dict) -> str:
|
|
if not self.is_configured(account):
|
|
return "Missing Zoom API credentials (account_id / client_id / client_secret / webhook_secret)"
|
|
if not self.is_enabled(account):
|
|
return "Account disabled in config"
|
|
return ""
|
|
|
|
def describe_account(self, account: dict) -> dict:
|
|
return {
|
|
"label": account.get("name", account.get("account_id", "Unknown")),
|
|
"bot_user_id": account.get("bot_user_id", "") or "(auto)",
|
|
"dm_policy": account.get("dm_policy", "open"),
|
|
"api_base_url": account.get("api_base_url", "https://api.zoom.us/v2"),
|
|
}
|
|
|
|
def config_schema(self) -> dict:
|
|
return {
|
|
"type": "object",
|
|
"title": "Zoom Team Chat 渠道配置",
|
|
"properties": {
|
|
"accounts": {
|
|
"type": "object",
|
|
"description": "Zoom account configurations",
|
|
"additionalProperties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"client_id": {
|
|
"type": "string",
|
|
"title": "Client ID",
|
|
"description": "Zoom Marketplace App Client ID",
|
|
},
|
|
"client_secret": {
|
|
"type": "string",
|
|
"title": "Client Secret",
|
|
"description": "Zoom Marketplace App Client Secret",
|
|
"x-ui-password": True,
|
|
},
|
|
"account_id": {
|
|
"type": "string",
|
|
"title": "Account ID",
|
|
"description": "Zoom Account ID for S2S OAuth",
|
|
},
|
|
"webhook_secret": {
|
|
"type": "string",
|
|
"title": "Webhook Secret Token",
|
|
"description": "Zoom Webhook Secret Token",
|
|
"x-ui-password": True,
|
|
},
|
|
"bot_user_id": {
|
|
"type": "string",
|
|
"title": "Bot User ID",
|
|
"description": "Bot Zoom user ID (auto-resolved if empty)",
|
|
},
|
|
"dm_policy": {
|
|
"type": "string",
|
|
"title": "DM 策略",
|
|
"enum": ["open", "pairing", "allowlist", "disabled"],
|
|
},
|
|
"group_policy": {
|
|
"type": "string",
|
|
"title": "群组策略",
|
|
"enum": ["mentioned", "activated", "allowlist"],
|
|
},
|
|
"allow_from": {"type": "array", "items": {"type": "string"}, "title": "允许列表"},
|
|
"api_base_url": {
|
|
"type": "string",
|
|
"title": "API Base URL",
|
|
"description": "Custom API base URL for data residency",
|
|
},
|
|
"text_chunk_limit": {"type": "integer", "title": "文本分块上限", "default": 3800},
|
|
},
|
|
},
|
|
}
|
|
},
|
|
}
|
|
|
|
def default_account_id(self, config: dict) -> str:
|
|
return config.get("default_account", "default")
|
|
|
|
def resolve_allow_from(self, config: dict, account_id: str | None = None) -> list[str]:
|
|
aid = account_id or self.default_account_id(config)
|
|
accounts = config.get("accounts", {})
|
|
account = accounts.get(aid, {})
|
|
return account.get("allow_from", [])
|
|
|
|
def set_config(self, config: dict) -> None:
|
|
self._config = config
|
|
|
|
def _get_raw_accounts(self) -> dict:
|
|
return self._config.get("accounts", {})
|
|
|
|
@staticmethod
|
|
def _env_client_id() -> str:
|
|
return os.environ.get(f"{ENV_PREFIX}_CLIENT_ID", "")
|