ForcePilot/backend/package/yuxi/channels/adapters/yuanbao/send.py
Kris 1f78c44b03 refactor: 整理并清理项目中的冗余代码与格式问题
这是一个批量整理提交,包含以下主要改动:
1.  删除多处冗余的空行和未使用的导入
2.  修复文件末尾缺少换行符的问题
3.  调整部分模块的导入顺序与代码排版
4.  修复部分配置默认值与策略逻辑
5.  新增多个功能模块与辅助工具
6.  完善异常处理与日志记录
7.  修复速率限制、消息缓存、权限校验等逻辑bug
8.  废弃部分旧有API与配置项并添加警告提示
2026-05-12 14:51:53 +08:00

79 lines
2.6 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",
auth_expired=True,
)
elif resp.status == 429:
try:
retry_after = int(resp.headers.get("Retry-After", "30"))
except (ValueError, TypeError):
retry_after = 30
retry_after = max(retry_after, 1)
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",
)