新增了Zalo用户频道的完整适配器实现,包括: - 基础的适配器初始化与导出结构 - 群组同步与成员获取功能 - 请求限流与退避重试机制 - 健康检查与状态探针 - 消息反应/表情处理工具 - 贴纸缓存与消息去重功能 - 消息ID格式化与追踪 - TTS语音合成支持 - 消息发送权限校验 - 长文本分块发送 - 操作审批流程 - 常量配置与国际化支持 - 图像视觉分析功能 - 贴纸消息处理 - 登录与配置向导 - 群组上下文缓存 - 网关连接管理 - 配置Schema校验 - 状态问题与安全审计 - 内联按钮与交互组件 - 交互式回调分发 - 联系人与群组目录管理 - 富媒体卡片消息支持
67 lines
1.7 KiB
Python
67 lines
1.7 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from yuxi.channels.models import DeliveryResult
|
|
from yuxi.utils.logging_config import logger
|
|
|
|
|
|
async def synthesize_and_send(
|
|
bridge: Any,
|
|
conversation_id: str,
|
|
text: str,
|
|
voice: str = "default",
|
|
rate_limiter: Any = None,
|
|
) -> DeliveryResult:
|
|
try:
|
|
if rate_limiter:
|
|
await rate_limiter.check_and_wait()
|
|
|
|
tts_resp = await bridge.post(
|
|
"/tts/synthesize",
|
|
json={
|
|
"text": text,
|
|
"voice": voice,
|
|
},
|
|
)
|
|
tts_data = tts_resp.json()
|
|
|
|
audio_url = tts_data.get("audio_url") or tts_data.get("url")
|
|
if not audio_url:
|
|
return DeliveryResult(success=False, error="TTS synthesis returned no audio URL")
|
|
|
|
voice_result = await bridge.send_voice_attachment(
|
|
conversation_id,
|
|
audio_url,
|
|
f"tts_{voice}.mp3",
|
|
)
|
|
return voice_result
|
|
|
|
except Exception as e:
|
|
logger.warning(f"[ZaloUser] TTS synthesis failed: {e}")
|
|
return DeliveryResult(success=False, error=str(e))
|
|
|
|
|
|
async def tts_to_audio_url(
|
|
bridge: Any,
|
|
text: str,
|
|
voice: str = "default",
|
|
) -> str | None:
|
|
try:
|
|
resp = await bridge.post(
|
|
"/tts/synthesize",
|
|
json={
|
|
"text": text,
|
|
"voice": voice,
|
|
},
|
|
)
|
|
data = resp.json()
|
|
return data.get("audio_url") or data.get("url")
|
|
except Exception as e:
|
|
logger.warning(f"[ZaloUser] TTS synthesis to URL failed: {e}")
|
|
return None
|
|
|
|
|
|
def has_tts_support(config: dict[str, Any]) -> bool:
|
|
return config.get("tts", {}).get("enabled", False)
|