ForcePilot/backend/package/yuxi/channels/contract/dtos/status.py

89 lines
2.5 KiB
Python
Raw Normal View History

"""状态 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")