ForcePilot/backend/package/yuxi/channels/adapters/yuanbao/send.py
Kris eb25707668 feat(yuanbao): 新增元宝渠道适配器完整实现
新增元宝(Yuanbao)渠道的完整适配器实现,包含以下核心模块:
- 基础适配器与导出入口
- 协议编解码与WebSocket帧处理
- 会话管理与路由逻辑
- 事件队列与出站消息队列
- 消息格式转换与发送重试
- 安全审计与权限校验
- 配置映射与账户管理
- 视觉分析与工具函数
- 文档生成与设置向导
2026-05-12 00:52:20 +08:00

74 lines
2.4 KiB
Python

from __future__ import annotations
import asyncio
import aiohttp
from yuxi.channels.models import DeliveryResult
from yuxi.utils.logging_config import logger
async def send_with_retry(
http_client: aiohttp.ClientSession,
token: str,
api_base: str,
payload: dict,
config: dict | None = None,
) -> DeliveryResult:
cfg = config or {}
retry_cfg = cfg.get("retry", {})
max_retries = retry_cfg.get("attempts", 3)
min_delay = retry_cfg.get("min_delay_ms", 400) / 1000
max_delay = retry_cfg.get("max_delay_ms", 30000) / 1000
send_timeout = cfg.get("send_timeout", 30)
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
}
url = f"{api_base}/api/v1/bot/send/message"
last_error = None
for attempt in range(max_retries):
try:
async with http_client.post(
url,
json=payload,
headers=headers,
timeout=aiohttp.ClientTimeout(total=send_timeout),
) as resp:
if resp.status == 200:
data = await resp.json()
return DeliveryResult(
success=True,
message_id=data.get("msg_id"),
)
elif resp.status == 401:
return DeliveryResult(
success=False,
error="Auth failed (401): token expired",
)
elif resp.status == 429:
retry_after = int(resp.headers.get("Retry-After", "30"))
logger.warning(f"[Yuanbao] Rate limited, retry after {retry_after}s")
await asyncio.sleep(retry_after)
continue
else:
error_body = await resp.text()
last_error = f"Send failed ({resp.status}): {error_body}"
except TimeoutError:
last_error = "Request timeout"
except aiohttp.ClientError as e:
last_error = f"Network error: {e}"
logger.debug(f"[Yuanbao] Send attempt {attempt + 1} failed: {e}")
if attempt < max_retries - 1:
delay = min(min_delay * (2**attempt), max_delay)
await asyncio.sleep(delay)
return DeliveryResult(
success=False,
error=str(last_error) if last_error else "Max retries exceeded",
)