import json import time import uuid from dataclasses import dataclass, field from email.utils import formatdate from typing import Any @dataclass(kw_only=True) class ItemDTO: """ ItemDTO is a data transfer object that represents a single item in the queue. It contains all the required information for both the frontend and the backend to process the item. """ _id: str = field(default_factory=lambda: str(uuid.uuid4()), init=False) error: str | None = None id: str title: str url: str quality: str | None = None format: str | None = None preset: str = "default" folder: str download_dir: str | None = None temp_dir: str | None = None status: str | None = None cookies: str | None = None config: dict = field(default_factory=dict) template: str | None = None template_chapter: str | None = None timestamp: float = field(default_factory=lambda: time.time_ns()) is_live: bool | None = None datetime: str = field(default_factory=lambda: str(formatdate(time.time()))) live_in: str | None = None file_size: int | None = None options: dict = field(default_factory=dict) extras: dict = field(default_factory=dict) # yt-dlp injected fields. tmpfilename: str | None = None filename: str | None = None total_bytes: int | None = None total_bytes_estimate: int | None = None downloaded_bytes: int | None = None msg: str | None = None percent: int | None = None speed: str | None = None eta: str | None = None # DEPRECATED: These fields are deprecated and will be removed in the future. thumbnail: str | None = None ytdlp_cookies: str | None = None ytdlp_config: dict = field(default_factory=dict) output_template: str | None = None output_template_chapter: str | None = None def serialize(self) -> dict: deprecated: tuple = ( "thumbnail", "quality", "format", "ytdlp_cookies", "ytdlp_config", "output_template", "output_template_chapter", ) if self.thumbnail and "thumbnail" not in self.extras: self.extras["thumbnail"] = self.thumbnail mapper: dict = { "cookies": "ytdlp_cookies", "config": "ytdlp_config", "template": "output_template", "template_chapter": "output_template_chapter", } for k, v in mapper.items(): if not self.get(k) and self.get(v): self.__dict__[k] = self.get(v) dump = self.__dict__.copy() for f in deprecated: dump.pop(f, None) return dump def json(self) -> str: return json.dumps(self.serialize(), default=lambda o: o.__dict__, sort_keys=True, indent=4) def get(self, key: str, default: Any = None) -> Any: return self.__dict__.get(key, default) def get_id(self) -> str: return self._id