From 2ee7a279de66e84dcbf3189fa80b59ccbfbd3222 Mon Sep 17 00:00:00 2001 From: Rafael Moraes <50295204+glomatico@users.noreply.github.com> Date: Fri, 27 Mar 2026 22:45:11 -0300 Subject: [PATCH] Add artist top-tracks selection flow --- votify/interface/enums.py | 1 + votify/interface/interface.py | 53 ++++++++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/votify/interface/enums.py b/votify/interface/enums.py index d6a112a..b84fe9c 100644 --- a/votify/interface/enums.py +++ b/votify/interface/enums.py @@ -124,6 +124,7 @@ class VideoResolution(Enum): class AutoMediaOption(Enum): + ARTIST_TOP_TRACKS = "artist-top-tracks" ARTIST_ALBUMS = "artist-albums" ARTIST_COMPILATIONS = "artist-compilations" ARTIST_SINGLES = "artist-singles" diff --git a/votify/interface/interface.py b/votify/interface/interface.py index 8c82aca..c1f2885 100644 --- a/votify/interface/interface.py +++ b/votify/interface/interface.py @@ -253,12 +253,63 @@ class SpotifyInterface: bool(auto_media_option), ): yield media - else: + elif artist_option == AutoMediaOption.ARTIST_VIDEOS: async for media in self._get_artist_media_videos( media_id, bool(auto_media_option), ): yield media + else: + async for media in self._get_artist_top_tracks_media( + media_id, + bool(auto_media_option), + ): + yield media + + async def _get_artist_top_tracks_media( + self, + media_id: str, + select_all: bool = False, + ) -> AsyncGenerator[SpotifyMedia | BaseException, None]: + artist_response = await self.base.api.get_artist_overview(media_id) + artist_data = artist_response["data"]["artistUnion"] + + if artist_data["__typename"] != "Artist": + yield VotifyMediaNotFoundException(media_id, artist_data) + return + + top_tracks_items = artist_data["discography"]["topTracks"]["items"] + + if not top_tracks_items: + yield VotifyMediaNotFoundException(media_id, artist_data) + return + + if select_all: + selection = top_tracks_items + else: + choices = [ + Choice( + name=" | ".join( + [ + track_item["track"]["name"], + ] + ), + value=track_item, + ) + for track_item in top_tracks_items + ] + selection = await inquirer.select( + message="Select which top tracks to download (Title):", + choices=choices, + multiselect=True, + ).execute_async() + + for track_item in selection: + track_id = track_item["track"]["id"] + media = await self._get_track_media( + track_id=track_id, + ) + yield media async def _get_artist_media_videos( self,