ForcePilot/backend/package/yuxi/channels/contract/dtos/media.py
Kris 00092c818e chore: 批量代码优化与规范完善
本次提交包含多项代码优化与规范修正:
1. 文档与注释优化:修正注释术语、补充注解与FR编号
2. 代码格式调整:统一空格、换行与缩进规范
3. 类型与接口完善:补充__all__导出、修正返回类型注解
4. 错误处理增强:新增领域错误类与校验逻辑
5. 依赖与导入调整:修复路径引用、统一时区导入
6. 协议与契约更新:完善接口文档与一致性注解
2026-07-03 19:18:13 +08:00

135 lines
4.2 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.

"""媒体资源 DTO。
定义媒体上传/下载/元数据查询的数据传输对象,覆盖图片/文件/音频/视频
媒体资源的通用契约。所有渠道插件共享统一媒体 DTO渠道插件实现
``InboundAdapter.downloadAttachment`` 或 ``OutboundAdapter.sendMessage``
时可使用这些 DTO 作为内部类型。
"""
from __future__ import annotations
from dataclasses import dataclass
from datetime import datetime
from enum import StrEnum
from yuxi.channels.contract.errors import ValidationError
class MediaType(StrEnum):
"""媒体类型枚举。"""
IMAGE = "image"
FILE = "file"
AUDIO = "audio"
VIDEO = "video"
@dataclass(frozen=True)
class MediaUploadResult:
"""媒体上传结果。
字段:
media_id: 渠道侧媒体 ID如飞书 image_key / file_key
url: 可访问的媒体 URL部分渠道返回可为 None
expires_at: 媒体资源过期时间UTC不过期时为 None。
"""
media_id: str
url: str | None = None
expires_at: datetime | None = None
def __post_init__(self) -> None:
"""校验 media_id 非空。
``media_id`` 必须非空,在构造时即抛出 ``ValidationError``,避免
空媒体 ID 导致后续上传结果无法定位INV-8
"""
if not self.media_id:
raise ValidationError("media_id", "must not be empty")
@dataclass(frozen=True)
class MediaDownloadResult:
"""媒体下载结果。
字段:
content: 媒体二进制内容。
filename: 文件名(含扩展名),渠道未返回时为 None。
mime_type: MIME 类型(如 image/png渠道未返回时为 None。
size: 内容字节数。
"""
content: bytes
size: int
filename: str | None = None
mime_type: str | None = None
@dataclass(frozen=True)
class MediaMetadata:
"""媒体元数据。
字段:
media_id: 渠道侧媒体 ID。
media_type: 媒体类型。
size: 内容字节数。
mime_type: MIME 类型,渠道未返回时为 None。
created_at: 媒体创建时间UTC渠道未返回时为 None。
"""
media_id: str
media_type: MediaType
size: int
mime_type: str | None = None
created_at: datetime | None = None
def __post_init__(self) -> None:
"""校验 media_id 非空与 size 非负。
``media_id`` 必须非空,``size`` 必须非负,在构造时即抛出
``ValidationError``,避免空媒体 ID 或负字节数导致元数据失效INV-8
"""
if not self.media_id:
raise ValidationError("media_id", "must not be empty")
if self.size < 0:
raise ValidationError("size", "must not be negative")
@dataclass(frozen=True)
class AttachmentUploadResult:
"""附件上传结果MSG-ATTACH-UPLOAD
描述通过插件 ``AttachmentUploadAdapter`` 适配器上传附件后的返回结果,包括
渠道侧附件 ID、可访问 URL、MIME 类型与字节数,由
``MessageManagementPort.uploadAttachment`` 引用FR-12
字段:
attachment_id: 渠道侧附件 ID。
url: 可访问的附件 URL。
mime_type: MIME 类型(如 image/png
size_bytes: 内容字节数。
expires_at: 附件资源过期时间UTC不过期时为 None。
"""
attachment_id: str
url: str
mime_type: str
size_bytes: int
expires_at: datetime | None = None
def __post_init__(self) -> None:
"""校验 attachment_id / url / mime_type 非空与 size_bytes 为正整数。
必填字符串字段必须非空,``size_bytes`` 必须为正整数,在构造时即
抛出 ``ValidationError``,避免空附件 ID / URL 或非正字节数导致上传
结果失效INV-8
"""
if not self.attachment_id:
raise ValidationError("attachment_id", "must not be empty")
if not self.url:
raise ValidationError("url", "must not be empty")
if not self.mime_type:
raise ValidationError("mime_type", "must not be empty")
if self.size_bytes <= 0:
raise ValidationError("size_bytes", "must be a positive integer")