ForcePilot/backend/package/yuxi/channels/adapters/wechat/config_schema.py

121 lines
5.2 KiB
Python
Raw Normal View History

from __future__ import annotations
from typing import Any
WECHAT_CONFIG_SCHEMA: dict[str, Any] = {
"type": "object",
"additionalProperties": False,
"properties": {
"enabled": {"type": "boolean"},
"accounts": {
"type": "object",
"patternProperties": {
"^[a-zA-Z0-9_-]+$": {
"type": "object",
"oneOf": [
{
"required": ["corp_id", "corp_secret", "agent_id"],
"properties": {
"corp_id": {"type": "string", "minLength": 1},
"corp_secret": {"type": "string", "minLength": 1},
"agent_id": {"type": "string", "minLength": 1},
},
},
{
"required": ["app_id", "app_secret"],
"properties": {
"app_id": {"type": "string", "minLength": 1},
"app_secret": {"type": "string", "minLength": 1},
},
},
{
"required": ["bridge_url"],
"properties": {
"bridge_url": {"type": "string", "format": "uri"},
},
},
],
},
},
},
"dmPolicy": {"enum": ["open", "pairing", "allowlist", "disabled"]},
"groupPolicy": {"enum": ["open", "allowlist", "disabled"]},
"retry_attempts": {"type": "integer", "minimum": 1, "maximum": 10},
"retry_min_delay": {"type": "number", "minimum": 0.1, "maximum": 60.0},
"retry_max_delay": {"type": "number", "minimum": 1.0, "maximum": 120.0},
"outbound_priority_enabled": {"type": "boolean"},
"exec_approval_timeout": {"type": "integer", "minimum": 1, "maximum": 30},
"ban_backoff_intervals": {
"type": "array",
"items": {"type": "integer", "minimum": 1},
"minItems": 1,
"maxItems": 5,
},
},
}
def validate_wechat_config(config: dict[str, Any]) -> list[str]:
errors: list[str] = []
if not isinstance(config, dict):
return ["配置必须是对象(dict)"]
enabled = config.get("enabled")
if enabled is not None and not isinstance(enabled, bool):
errors.append("enabled 必须是布尔值")
dm_policy = config.get("dm_policy", "pairing")
if dm_policy not in ("open", "pairing", "allowlist", "disabled"):
errors.append(f"dm_policy 值无效: {dm_policy}(可选: open/pairing/allowlist/disabled")
group_policy = config.get("group_policy", "allowlist")
if group_policy not in ("open", "allowlist", "disabled"):
errors.append(f"group_policy 值无效: {group_policy}(可选: open/allowlist/disabled")
retry_attempts = config.get("retry_attempts")
if retry_attempts is not None and (not isinstance(retry_attempts, int) or retry_attempts < 0):
errors.append("retry_attempts 必须是非负整数")
retry_min_delay = config.get("retry_min_delay")
if retry_min_delay is not None and (not isinstance(retry_min_delay, (int, float)) or retry_min_delay < 0):
errors.append("retry_min_delay 必须是非负数")
retry_max_delay = config.get("retry_max_delay")
if retry_max_delay is not None and (not isinstance(retry_max_delay, (int, float)) or retry_max_delay < 0):
errors.append("retry_max_delay 必须是非负数")
outbound_priority_enabled = config.get("outbound_priority_enabled")
if outbound_priority_enabled is not None and not isinstance(outbound_priority_enabled, bool):
errors.append("outbound_priority_enabled 必须是布尔值")
exec_approval_timeout = config.get("exec_approval_timeout")
if exec_approval_timeout is not None and (not isinstance(exec_approval_timeout, int) or exec_approval_timeout < 0):
errors.append("exec_approval_timeout 必须是非负整数")
ban_backoff_intervals = config.get("ban_backoff_intervals")
if ban_backoff_intervals is not None:
if not isinstance(ban_backoff_intervals, list) or not all(
isinstance(x, int) and x > 0 for x in ban_backoff_intervals
):
errors.append("ban_backoff_intervals 必须是正整数列表")
has_corp = all(config.get(k) for k in ("corp_id", "corp_secret", "agent_id"))
has_mp = all(config.get(k) for k in ("app_id", "app_secret"))
has_bridge = bool(config.get("bridge_url"))
if not (has_corp or has_mp or has_bridge):
errors.append("缺少有效的微信配置 (wecom/mp/bridge)")
accounts = config.get("accounts", {})
if accounts and isinstance(accounts, dict):
for account_id, account_cfg in accounts.items():
if not isinstance(account_id, str) or not account_id.replace("-", "").replace("_", "").isalnum():
errors.append(f"账户 ID 格式无效: {account_id}")
return errors
def get_schema() -> dict[str, Any]:
return dict(WECHAT_CONFIG_SCHEMA)