ForcePilot/backend/package/yuxi/channels/adapters/zalo_oa/accounts.py
Kris 30dd9e16f4 feat(zalo-oa): 实现完整的 Zalo OA 渠道适配器模块
新增 Zalo OA 官方账号完整集成能力,包含:
1. 基础通信能力:消息编解码、目标归一化、文本分块
2. 安全与校验:Webhook 签名验证、DM 策略管理、配对流程
3. 辅助工具:重复事件去重、请求限流、异常告警
4. 管理功能:账号多实例管理、配置验证、健康诊断
5. 扩展能力:媒体托管、视觉识别、TTS 语音合成
6. 运维支持:审计日志、状态监控、目录同步
2026-05-12 00:52:47 +08:00

79 lines
2.2 KiB
Python

from __future__ import annotations
from typing import Any
from yuxi.utils.logging_config import logger
def list_account_ids(config: dict[str, Any]) -> list[str]:
accounts = config.get("accounts", {})
if not isinstance(accounts, dict) or not accounts:
return ["default"]
return list(accounts.keys())
def resolve_account(config: dict[str, Any], account_id: str = "") -> dict[str, Any]:
accounts = config.get("accounts", {})
if not isinstance(accounts, dict) or not accounts:
return config
if not account_id:
default_id = config.get("defaultAccount", config.get("default_account", ""))
if default_id and default_id in accounts:
account_id = default_id
else:
account_ids = list(accounts.keys())
account_id = account_ids[0] if account_ids else "default"
base_config = _extract_top_level_config(config)
account_config = accounts.get(account_id, {})
name = account_config.get("name", account_id)
merged = {**base_config, **account_config}
merged["name"] = name
merged["account_id"] = account_id
logger.info(f"[ZaloOA] Resolved account: {name} (id={account_id})")
return merged
def get_default_account_id(config: dict[str, Any]) -> str:
default_id = config.get("defaultAccount", config.get("default_account", ""))
if default_id:
return default_id
account_ids = list_account_ids(config)
return account_ids[0] if account_ids else "default"
def _extract_top_level_config(config: dict[str, Any]) -> dict[str, Any]:
top_keys = {
"token",
"retry",
"network",
"health_check_ttl_sec",
"webhook",
"dm_policy",
"dmPolicy",
"allowFrom",
"response_prefix",
"responsePrefix",
"dedup",
"enabled",
"rate_limit_window_ms",
"rate_limit_max_requests",
"anomaly_tracking_enabled",
"audit_enabled",
"audit_log_level",
"media_vision_enabled",
"media_vision_model",
"token_file",
"app_id_file",
"secret_key_file",
"dedup_window_ms",
}
result = {}
for key in top_keys:
if key in config:
result[key] = config[key]
return result