diff --git a/unshackle/commands/dl.py b/unshackle/commands/dl.py index dc69c17..79a6784 100644 --- a/unshackle/commands/dl.py +++ b/unshackle/commands/dl.py @@ -2829,6 +2829,9 @@ class dl: {"timestamp": chapter.timestamp, "name": chapter.name} for chapter in (title.tracks.chapters or []) ] + if "attachments" not in tinfo: + tinfo["attachments"] = [a.to_dict() for a in (title.tracks.attachments or []) if a.url] + export.write_text(json.dumps(doc, indent=4, ensure_ascii=False), encoding="utf8") def prepare_drm( diff --git a/unshackle/core/import_service.py b/unshackle/core/import_service.py index 3d1e44e..3ecaf41 100644 --- a/unshackle/core/import_service.py +++ b/unshackle/core/import_service.py @@ -18,6 +18,7 @@ from unshackle.core.manifests import DASH, HLS, ISM from unshackle.core.remote_service import RemoteService, _build_title, _resolve_proxy from unshackle.core.titles import Episode, Movies, Series, Title_T, Titles_T, remap_titles from unshackle.core.tracks import Audio, Chapter, Chapters, Tracks, Video +from unshackle.core.tracks.attachment import Attachment from unshackle.core.tracks.track import Track log = logging.getLogger("import") @@ -166,6 +167,23 @@ class ImportService: track.drm = drm tracks.add(track) + for attachment in entry.get("attachments") or []: + url = attachment.get("url") + if not url: + continue + try: + tracks.attachments.append( + Attachment.from_url( + url, + name=attachment.get("name"), + mime_type=attachment.get("mime_type"), + description=attachment.get("description"), + session=self.session, + ) + ) + except Exception as e: + self.log.warning(f"Skipping attachment '{attachment.get('name')}': {e}") + self.tracks_by_title[title_id] = tracks return tracks diff --git a/unshackle/core/tracks/attachment.py b/unshackle/core/tracks/attachment.py index 00a82e2..d9e427d 100644 --- a/unshackle/core/tracks/attachment.py +++ b/unshackle/core/tracks/attachment.py @@ -125,6 +125,10 @@ class Attachment: def __str__(self) -> str: return " | ".join(filter(bool, ["ATT", self.name, self.mime_type, self.description])) + def to_dict(self) -> dict[str, Optional[str]]: + """Serialise a URL-backed attachment for export/import.""" + return {"url": self.url, "name": self.name, "mime_type": self.mime_type, "description": self.description} + @property def id(self) -> str: """Compute an ID from the attachment data."""