68 lines
2.0 KiB
Python
68 lines
2.0 KiB
Python
|
|
"""群发消息相关数据模型。"""
|
|||
|
|
|
|||
|
|
from __future__ import annotations
|
|||
|
|
|
|||
|
|
from typing import Optional, Literal
|
|||
|
|
|
|||
|
|
from pydantic import BaseModel, Field
|
|||
|
|
|
|||
|
|
|
|||
|
|
class BatchSendRequest(BaseModel):
|
|||
|
|
"""群发请求。
|
|||
|
|
|
|||
|
|
三层幂等:
|
|||
|
|
- 批级:client_request_id(None 时自动生成 batch_id)
|
|||
|
|
- 单条:内部按 f"{batch_id}:{to_wxid}" 作为 client_request_id 传给 orchestrator
|
|||
|
|
- orchestrator:复用 IdemCache(TTL=300s)
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
targets: list[str] = Field(
|
|||
|
|
...,
|
|||
|
|
min_length=1,
|
|||
|
|
max_length=200,
|
|||
|
|
description="目标 wxid 列表(去重后 ≤ 200)",
|
|||
|
|
)
|
|||
|
|
content: str = Field(
|
|||
|
|
...,
|
|||
|
|
min_length=1,
|
|||
|
|
max_length=2000,
|
|||
|
|
description="消息内容(支持 {nickname} 占位符,发送前按目标联系人替换)",
|
|||
|
|
)
|
|||
|
|
client_request_id: Optional[str] = Field(
|
|||
|
|
None,
|
|||
|
|
description="可选:批级幂等 ID,None 时自动生成 batch_id",
|
|||
|
|
)
|
|||
|
|
abort_on_consecutive_fail: int = Field(
|
|||
|
|
5,
|
|||
|
|
ge=1,
|
|||
|
|
le=20,
|
|||
|
|
description="连续失败 N 次中止整批(剩余标记 skipped)",
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
|
|||
|
|
class BatchItemResult(BaseModel):
|
|||
|
|
"""单条群发结果。"""
|
|||
|
|
|
|||
|
|
to_wxid: str
|
|||
|
|
# unknown: 发送被 cancel 中断,实际发送状态未知(send_queue worker 可能已发出)
|
|||
|
|
status: Literal["success", "failed", "skipped", "pending", "unknown"]
|
|||
|
|
error_code: Optional[str] = None
|
|||
|
|
error_message: Optional[str] = None
|
|||
|
|
verified: Optional[bool] = None
|
|||
|
|
|
|||
|
|
|
|||
|
|
class BatchSendStatus(BaseModel):
|
|||
|
|
"""群发任务状态。"""
|
|||
|
|
|
|||
|
|
batch_id: str
|
|||
|
|
status: Literal["pending", "running", "completed", "failed", "cancelled"] = "pending"
|
|||
|
|
total: int = 0
|
|||
|
|
processed: int = 0
|
|||
|
|
success: int = 0
|
|||
|
|
failed: int = 0
|
|||
|
|
skipped: int = 0
|
|||
|
|
progress: float = Field(0.0, ge=0.0, le=1.0)
|
|||
|
|
estimated_remaining_sec: Optional[int] = None
|
|||
|
|
abort_reason: Optional[str] = None
|
|||
|
|
items: Optional[list[BatchItemResult]] = None # 详细结果(可选,列表大时省略)
|