From 152d94b2e4068ee2953beea3ae58d247b6ee8bca Mon Sep 17 00:00:00 2001 From: Rafael Moraes <50295204+glomatico@users.noreply.github.com> Date: Thu, 16 Apr 2026 08:09:07 -0300 Subject: [PATCH] Include UPC in Spotify song metadata --- votify/interface/song.py | 21 ++++++++++++++++++++- votify/interface/types.py | 5 +++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/votify/interface/song.py b/votify/interface/song.py index 5bc771f..42b3ba3 100644 --- a/votify/interface/song.py +++ b/votify/interface/song.py @@ -110,10 +110,11 @@ class SpotifySongInterface(SpotifyAudioInterface): ) -> MediaTags: release_date = album_data["date"] - (composer, producer), (album_artist, artist, isrc, label) = ( + (composer, producer), (album_artist, artist, isrc, label), upc = ( await asyncio.gather( self._get_composer_producer(track_data["uri"].split(":")[-1]), self._get_isrc_label(track_data["uri"].split(":")[-1]), + self._get_upc(album_data["uri"].split(":")[-1]), ) ) @@ -145,6 +146,7 @@ class SpotifySongInterface(SpotifyAudioInterface): rating=rating, track=track_data["trackNumber"], track_total=track_total, + upc=upc, url=f"https://open.spotify.com/track/{track_data['uri'].split(':')[-1]}", ) @@ -259,3 +261,20 @@ class SpotifySongInterface(SpotifyAudioInterface): synced="\n".join(synced_lines) if synced_lines else None, unsynced="\n".join(unsynced_lines) + "\n" if unsynced_lines else None, ) + + async def _get_upc( + self, + album_id: str, + ) -> str | None: + album_gid = await self.api.get_gid_metadata(album_id, "album") + + upc = next( + ( + external_id["id"] + for external_id in album_gid.get("external_id", []) + if external_id["type"] == "upc" + ), + None, + ) + + return upc diff --git a/votify/interface/types.py b/votify/interface/types.py index 3d07260..2782861 100644 --- a/votify/interface/types.py +++ b/votify/interface/types.py @@ -67,6 +67,7 @@ class MediaTags: title: str = None track: int = None track_total: int = None + upc: str = None url: str = None def as_mp4_tags(self, date_format: str = None) -> dict[str, list[Any]]: @@ -126,6 +127,9 @@ class MediaTags: "\xa9nam": self.title, "trkn": track_mp4, "\xa9url": self.url, + "----:com.apple.iTunes:UPC": ( + MP4FreeForm(self.upc.encode("utf-8")) if self.upc is not None else None + ), } return { k: ([v] if not isinstance(v, (list, bool)) else v) @@ -163,6 +167,7 @@ class MediaTags: "TRACKNUMBER": [str(self.track)], "TRACKTOTAL": [str(self.track_total)], "URL": [self.url], + "UPC": [self.upc], } return {k: v for k, v in flac_tags.items() if v[0] is not None}