本次提交包含多项代码优化与规范修正: 1. 文档与注释优化:修正注释术语、补充注解与FR编号 2. 代码格式调整:统一空格、换行与缩进规范 3. 类型与接口完善:补充__all__导出、修正返回类型注解 4. 错误处理增强:新增领域错误类与校验逻辑 5. 依赖与导入调整:修复路径引用、统一时区导入 6. 协议与契约更新:完善接口文档与一致性注解
89 lines
2.5 KiB
Python
89 lines
2.5 KiB
Python
"""状态 DTO。
|
||
|
||
定义消息状态事件的枚举与不可变值对象,包括事件类型、消息状态与状态
|
||
负载。所有枚举继承 ``str, Enum`` 以支持 JSON 序列化,DTO 均为
|
||
``dataclass(frozen=True)``,仅依赖标准库,用于渠道侧消息状态事件
|
||
(送达 / 已读 / 编辑 / 撤回等)的回传与状态机推进。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from dataclasses import dataclass
|
||
from datetime import datetime
|
||
from enum import StrEnum
|
||
|
||
from yuxi.channels.contract.errors import ValidationError
|
||
|
||
|
||
class EventType(StrEnum):
|
||
"""事件类型。
|
||
|
||
标识渠道侧回传的消息状态事件类型,用于状态事件解析与状态机推进。
|
||
继承 ``str, Enum`` 以支持 JSON 序列化与字符串比较。
|
||
|
||
取值:
|
||
MESSAGE: 消息事件。
|
||
DELIVERED: 已送达。
|
||
READ: 已读。
|
||
EDITED: 已编辑。
|
||
RECALLED: 已撤回。
|
||
UNKNOWN: 未知事件。
|
||
AGENT_MENTION: Agent 提及事件(多 Agent 协作,标识 @Agent 提及)。
|
||
"""
|
||
|
||
MESSAGE = "message"
|
||
DELIVERED = "delivered"
|
||
READ = "read"
|
||
EDITED = "edited"
|
||
RECALLED = "recalled"
|
||
UNKNOWN = "unknown"
|
||
AGENT_MENTION = "agent_mention"
|
||
|
||
|
||
class MessageStatus(StrEnum):
|
||
"""消息状态。
|
||
|
||
标识出站消息在渠道侧的状态,用于出站状态机推进与持久化。继承
|
||
``str, Enum`` 以支持 JSON 序列化与字符串比较。
|
||
|
||
取值:
|
||
PENDING: 待发送。
|
||
SENT: 已发送。
|
||
DELIVERED: 已送达。
|
||
READ: 已读。
|
||
FAILED: 已失败。
|
||
"""
|
||
|
||
PENDING = "pending"
|
||
SENT = "sent"
|
||
DELIVERED = "delivered"
|
||
READ = "read"
|
||
FAILED = "failed"
|
||
|
||
|
||
@dataclass(frozen=True)
|
||
class StatusPayload:
|
||
"""状态负载。
|
||
|
||
描述渠道侧回传的消息状态事件负载,包括事件类型、关联的渠道消息 ID
|
||
与事件时间戳,用于状态事件解析与状态机推进。
|
||
|
||
字段:
|
||
event_type: 事件类型。
|
||
ref_channel_msg_id: 关联的渠道消息 ID。
|
||
timestamp: 事件时间戳。
|
||
"""
|
||
|
||
event_type: EventType
|
||
ref_channel_msg_id: str
|
||
timestamp: datetime
|
||
|
||
def __post_init__(self) -> None:
|
||
"""校验 ref_channel_msg_id 非空。
|
||
|
||
``ref_channel_msg_id`` 必须非空,在构造时即抛出 ``ValidationError``,
|
||
避免空消息 ID 导致状态机无法定位目标消息(INV-8)。
|
||
"""
|
||
if not self.ref_channel_msg_id:
|
||
raise ValidationError("ref_channel_msg_id", "must not be empty")
|