2026-07-02 03:22:12 +08:00
|
|
|
|
"""状态 DTO。
|
|
|
|
|
|
|
|
|
|
|
|
定义消息状态事件的枚举与不可变值对象,包括事件类型、消息状态与状态
|
|
|
|
|
|
负载。所有枚举继承 ``str, Enum`` 以支持 JSON 序列化,DTO 均为
|
|
|
|
|
|
``dataclass(frozen=True)``,仅依赖标准库,用于渠道侧消息状态事件
|
|
|
|
|
|
(送达 / 已读 / 编辑 / 撤回等)的回传与状态机推进。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
from enum import StrEnum
|
|
|
|
|
|
|
2026-07-03 19:18:13 +08:00
|
|
|
|
from yuxi.channels.contract.errors import ValidationError
|
|
|
|
|
|
|
2026-07-02 03:22:12 +08:00
|
|
|
|
|
|
|
|
|
|
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
|
2026-07-03 19:18:13 +08:00
|
|
|
|
|
|
|
|
|
|
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")
|