2026-07-02 03:22:12 +08:00
|
|
|
|
"""管理员消息 DTO。
|
|
|
|
|
|
|
|
|
|
|
|
定义管理员消息发送的命令与结果值对象,包括管理员发送命令与发送结果。
|
|
|
|
|
|
所有 DTO 均为 ``dataclass(frozen=True)``,仅依赖标准库与契约层内部类型,
|
|
|
|
|
|
用于管理员向目标会话或用户批量发送消息并聚合失败与跳过详情。集合字段
|
|
|
|
|
|
使用 tuple 以保证 frozen dataclass 的不可变语义。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
|
|
from dataclasses import dataclass
|
2026-07-03 19:18:13 +08:00
|
|
|
|
from typing import Literal
|
2026-07-02 03:22:12 +08:00
|
|
|
|
|
|
|
|
|
|
from yuxi.channels.contract.dtos.common import (
|
|
|
|
|
|
FailureDetail,
|
|
|
|
|
|
MessageContent,
|
|
|
|
|
|
Operator,
|
|
|
|
|
|
SkipDetail,
|
|
|
|
|
|
)
|
|
|
|
|
|
from yuxi.channels.contract.errors import ValidationError
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
|
|
|
|
class AdminSendCmd:
|
2026-07-03 19:18:13 +08:00
|
|
|
|
"""管理员发送命令(FR-19)。
|
2026-07-02 03:22:12 +08:00
|
|
|
|
|
|
|
|
|
|
由管理员消息端口方法引用,描述管理员向目标会话或用户发送消息的请求,
|
|
|
|
|
|
携带目标、内容、会话策略、幂等键与操作人,支持复用 / 新建 / 临时
|
|
|
|
|
|
三种会话策略。
|
|
|
|
|
|
|
|
|
|
|
|
字段:
|
|
|
|
|
|
target: 目标会话或用户。
|
|
|
|
|
|
content: 消息内容。
|
|
|
|
|
|
conversation_policy: 会话策略(reuse | reuse-or-create | new)。
|
|
|
|
|
|
idempotency_key: 幂等键。
|
|
|
|
|
|
operator: 操作人(审计用)。
|
2026-07-03 19:18:13 +08:00
|
|
|
|
target_type: 目标类型(session_id 或 peer_id,默认 session_id)。
|
2026-07-02 03:22:12 +08:00
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
target: str
|
|
|
|
|
|
content: MessageContent
|
2026-07-03 19:18:13 +08:00
|
|
|
|
conversation_policy: Literal["reuse", "reuse-or-create", "new"]
|
2026-07-02 03:22:12 +08:00
|
|
|
|
idempotency_key: str
|
|
|
|
|
|
operator: Operator
|
2026-07-03 19:18:13 +08:00
|
|
|
|
target_type: Literal["session_id", "peer_id"] = "session_id"
|
2026-07-02 03:22:12 +08:00
|
|
|
|
|
|
|
|
|
|
def __post_init__(self) -> None:
|
|
|
|
|
|
"""校验必填字段非空(FR-19)。
|
|
|
|
|
|
|
|
|
|
|
|
``target`` 与 ``idempotency_key`` 必须非空,在构造时即抛出
|
|
|
|
|
|
``ValidationError``,adapter 不再做该校验(INV-8)。
|
|
|
|
|
|
|
|
|
|
|
|
``conversation_policy`` 的合法值校验由 ``AdminMessageService``
|
|
|
|
|
|
统一执行(``_CONVERSATION_POLICIES``),DTO 层不重复校验,避免
|
|
|
|
|
|
与 service 层默认值回退(``or _DEFAULT_CONVERSATION_POLICY``)
|
|
|
|
|
|
冲突。
|
2026-07-03 19:18:13 +08:00
|
|
|
|
|
|
|
|
|
|
``target_type`` 默认 ``"session_id"``(按会话 ID 触达),
|
|
|
|
|
|
``"peer_id"`` 表示按对端 ID 触达(需配合 ``channel_type`` /
|
|
|
|
|
|
``account_id`` 路由信息,由 ``_resolveTarget`` 解析)。
|
2026-07-02 03:22:12 +08:00
|
|
|
|
"""
|
|
|
|
|
|
if not self.target:
|
|
|
|
|
|
raise ValidationError("target", "must not be empty")
|
|
|
|
|
|
if not self.idempotency_key:
|
|
|
|
|
|
raise ValidationError("idempotency_key", "must not be empty")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
|
|
|
|
class AdminSendResult:
|
2026-07-03 19:18:13 +08:00
|
|
|
|
"""管理员发送结果(FR-19)。
|
2026-07-02 03:22:12 +08:00
|
|
|
|
|
|
|
|
|
|
描述管理员批量发送消息的执行结果,聚合成功消息 ID、失败详情与跳过
|
|
|
|
|
|
详情,用于结果汇报与重试策略决策。集合字段使用 tuple 以保证不可变。
|
|
|
|
|
|
|
|
|
|
|
|
字段:
|
|
|
|
|
|
message_ids: 成功发送的消息 ID 列表。
|
|
|
|
|
|
failures: 失败详情列表(默认空 tuple)。
|
|
|
|
|
|
skipped: 跳过详情列表(默认空 tuple)。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
message_ids: tuple[str, ...]
|
|
|
|
|
|
failures: tuple[FailureDetail, ...] = ()
|
|
|
|
|
|
skipped: tuple[SkipDetail, ...] = ()
|