WechatOnCloud/bridge/woc_bridge/models/send.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

112 lines
4.6 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.

"""发送域模型:发送文本 / 发送文件 / 发送响应。"""
from __future__ import annotations
from typing import Optional
from pydantic import BaseModel, Field
# ---------------------------------------------------------------------------
# 发送接口
# ---------------------------------------------------------------------------
class SendTextRequest(BaseModel):
"""发送文本消息请求。"""
to_wxid: str = Field(description="目标 wxid")
content: str = Field(description="文本内容")
display_name: Optional[str] = Field(
default=None,
description="可选:用于微信搜索框定位会话的显示名。不传时 bridge 自动按备注->昵称->wxid 查找",
)
client_request_id: str = Field(default="", description="客户端幂等去重 ID空字符串表示不参与幂等校验")
class SendFileRequest(BaseModel):
"""发送图片/文件请求。"""
to_wxid: str = Field(description="目标 wxid")
file_path: str = Field(description="容器内文件绝对路径")
display_name: Optional[str] = Field(
default=None,
description="可选:用于微信搜索框定位会话的显示名。不传时 bridge 自动按备注->昵称->wxid 查找",
)
client_request_id: Optional[str] = Field(
default=None,
description="可选:客户端幂等去重 IDNone 或空字符串表示不参与幂等校验",
)
class SendResponse(BaseModel):
"""发送消息响应。
字段说明:
- local_send_idbridge 本地生成的发送 ID格式 local_<unix秒>_<随机>。
仅用于客户端幂等去重,**不对应微信原生 msg_id**,禁止用于
/api/media/{msg_id} 查媒体。
- placeholder是否为占位实现true 表示真实文件/图片内容未传输,
仅发了提示文本;客户端应走降级处理)。
"""
success: bool = Field(default=False)
local_send_id: str = Field(default="", description="本地生成的发送 ID非微信原生 msg_id")
placeholder: bool = Field(default=False, description="是否为占位实现(真实内容未传输)")
error: Optional[str] = Field(default=None, description="失败时的错误描述")
verified: bool = Field(default=False, description="是否已通过发送结果验证")
skipped: bool = Field(default=False, description="是否因幂等去重被跳过")
# ---------------------------------------------------------------------------
# 消息撤回experimental
# ---------------------------------------------------------------------------
class RevokeMessageRequest(BaseModel):
"""撤回消息请求experimental"""
talker: str = Field(description="会话对方 wxid")
create_time: int = Field(description="消息发送时间戳Unix 秒),用于校验撤回时限,必须 > 0")
display_name: Optional[str] = Field(
default=None,
description="会话显示名(备注/昵称),用于微信搜索框定位会话;"
"不传则从 contact.db 解析(优先 remark其次 nickname回退 wxid",
)
class RevokeMessageResponse(BaseModel):
"""撤回消息响应。"""
success: bool = Field(default=False)
error: Optional[str] = Field(default=None, description="失败时的错误描述")
verified: Optional[bool] = Field(
default=None,
description="post_verify 校验结果True=已确认撤回标记写入 DB"
"False=超时未检测到None=未执行校验DB 不可用或未接入)",
)
# ---------------------------------------------------------------------------
# 消息转发experimental
# ---------------------------------------------------------------------------
class ForwardMessageRequest(BaseModel):
"""转发消息请求experimental"""
talker: str = Field(description="源会话对方 wxid")
target_display_name: str = Field(
description="转发目标联系人的显示名(备注/昵称)"
)
source_display_name: Optional[str] = Field(
default=None,
description="源会话显示名,用于搜索框定位源会话;不传则从 contact.db 解析",
)
class ForwardMessageResponse(BaseModel):
"""转发消息响应。"""
success: bool = Field(default=False)
error: Optional[str] = Field(default=None, description="失败时的错误描述")
verified: Optional[bool] = Field(
default=None,
description="post_verify 校验结果True=目标会话出现 type=49 转发消息,"
"False=超时未检测到None=未执行校验",
)