WechatOnCloud/bridge/woc_bridge/routes/batch.py
Kris 2348a04163 feat: 完成微信4.0模板UI重构与批量群发、导出功能落地
本次提交包含多项核心更新:
1. 新增微信4.0浅色主题UI模板资源与说明文档,补充了联系人图标、新的朋友入口等四个UI元素的图像匹配模板
2. 重构UI驱动层,将原2375行的单文件拆分为5个职责清晰的子驱动类,提升代码可维护性
3. 新增批量群发消息与聊天记录导出的完整数据模型、路由与后台协程,支持幂等校验与风控配置
4. 为所有业务接口新增post_verify校验逻辑,补充了verified字段返回操作结果
5. 优化媒体文件解密逻辑,修复了导出功能中的数据库错误处理与分辨率硬编码问题
6. 更新版本配置,将媒体发送功能标记为已落地,调整了能力列表与配置项
2026-07-16 16:53:42 +08:00

107 lines
3.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""群发消息路由。
端点:
- POST /api/send/batch 提交群发任务
- GET /api/send/batch 列出最近 N 条群发任务
- GET /api/send/batch/{batch_id}/status 查询群发进度
- POST /api/send/batch/{batch_id}/cancel 取消群发
"""
from __future__ import annotations
import logging
from fastapi import APIRouter, Request
from woc_bridge.config import _require_batch_worker
from woc_bridge.models import BridgeError, BatchSendRequest
logger = logging.getLogger("woc-bridge")
router = APIRouter(prefix="/api/send/batch", tags=["batch-send"])
@router.post("")
async def submit_batch(req: BatchSendRequest, request: Request):
"""提交群发任务。
请求体BatchSendRequesttargets / content / client_request_id / abort_on_consecutive_fail
返回:{"success": True, "batch_id": str, "status": str, "status_query_url": str}
异常:
- 400 INVALID_PARAMStargets 超过单批上限
- 409 INVALID_PARAMSbatch_id 重复(批级幂等命中)
- 429 RATE_LIMITED日频次超限 / 批间隔不足
"""
worker = _require_batch_worker()
batch_id = await worker.submit_batch(req)
status = await worker.get_status(batch_id)
return {
"success": True,
"batch_id": batch_id,
"status": status.status if status is not None else "pending",
"status_query_url": f"/api/send/batch/{batch_id}/status",
}
@router.get("/{batch_id}/status")
async def get_batch_status(batch_id: str):
"""查询群发进度。
返回 BatchSendStatus含 total / processed / success / failed / skipped /
progress / estimated_remaining_sec / items 等字段)。
异常:
- 404 NOT_FOUNDbatch_id 不存在
"""
worker = _require_batch_worker()
status = await worker.get_status(batch_id)
if status is None:
raise BridgeError(
code="NOT_FOUND",
message=f"batch_id={batch_id} 不存在",
http_status=404,
)
return status
@router.post("/{batch_id}/cancel")
async def cancel_batch(batch_id: str):
"""取消群发。
已处理条目保留结果,未处理条目标记 skipped。
异常:
- 404 NOT_FOUNDbatch_id 不存在或已完成
"""
worker = _require_batch_worker()
cancelled = await worker.cancel_batch(batch_id)
if not cancelled:
raise BridgeError(
code="NOT_FOUND",
message=f"batch_id={batch_id} 不存在或已完成",
http_status=404,
)
return {"success": True, "batch_id": batch_id, "status": "cancelled"}
@router.get("")
async def list_batches(limit: int = 20):
"""列出最近 N 条群发任务(按提交时间倒序)。
Query 参数:
- limit返回条数1-100默认 20
异常:
- 400 INVALID_PARAMSlimit 越界
"""
worker = _require_batch_worker()
if limit < 1 or limit > 100:
raise BridgeError(
code="INVALID_PARAMS",
message="limit 必须在 1-100 之间",
http_status=400,
)
batches = await worker.list_batches(limit)
return {"batches": batches}