"""Asset data model. An Asset represents an uploaded file (sound, image, video, or other) stored on the server. Assets are referenced by ID from other entities (e.g. NotificationColorStripSource uses sound assets for alert sounds). """ from dataclasses import dataclass, field from datetime import datetime from typing import List, Optional # Map MIME type prefixes to asset_type categories _MIME_TO_ASSET_TYPE = { "audio/": "sound", "image/": "image", "video/": "video", } def asset_type_from_mime(mime_type: str) -> str: """Derive asset_type from a MIME type string.""" for prefix, asset_type in _MIME_TO_ASSET_TYPE.items(): if mime_type.startswith(prefix): return asset_type return "other" @dataclass class Asset: """Persistent metadata for an uploaded file asset.""" id: str name: str filename: str # original upload filename stored_filename: str # on-disk filename (uuid-based) mime_type: str # e.g. "audio/wav", "image/png" asset_type: str # "sound" | "image" | "video" | "other" size_bytes: int created_at: datetime updated_at: datetime description: Optional[str] = None tags: List[str] = field(default_factory=list) prebuilt: bool = False # True for shipped assets deleted: bool = False # soft-delete for prebuilt assets def to_dict(self) -> dict: return { "id": self.id, "name": self.name, "filename": self.filename, "stored_filename": self.stored_filename, "mime_type": self.mime_type, "asset_type": self.asset_type, "size_bytes": self.size_bytes, "description": self.description, "tags": self.tags, "prebuilt": self.prebuilt, "deleted": self.deleted, "created_at": self.created_at.isoformat(), "updated_at": self.updated_at.isoformat(), } @staticmethod def from_dict(data: dict) -> "Asset": return Asset( id=data["id"], name=data["name"], filename=data.get("filename", ""), stored_filename=data.get("stored_filename", ""), mime_type=data.get("mime_type", "application/octet-stream"), asset_type=data.get("asset_type", "other"), size_bytes=int(data.get("size_bytes", 0)), description=data.get("description"), tags=data.get("tags", []), prebuilt=bool(data.get("prebuilt", False)), deleted=bool(data.get("deleted", False)), created_at=datetime.fromisoformat(data["created_at"]), updated_at=datetime.fromisoformat(data["updated_at"]), )