From 93aa569e3fe96cd8579aebca52362379d5a790ec Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Fri, 25 Oct 2024 10:06:54 -0400 Subject: [PATCH 1/5] Improve ListenBrainz error handling and simplify playlist handling --- beetsplug/listenbrainz.py | 101 ++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 54 deletions(-) diff --git a/beetsplug/listenbrainz.py b/beetsplug/listenbrainz.py index 4855481f8..d1efd2275 100644 --- a/beetsplug/listenbrainz.py +++ b/beetsplug/listenbrainz.py @@ -116,13 +116,9 @@ class ListenBrainzPlugin(BeetsPlugin): mbid = self.get_mb_recording_id(track) tracks.append( { - "album": { - "name": track["track_metadata"].get("release_name") - }, + "album": {"name": track["track_metadata"].get("release_name")}, "name": track["track_metadata"].get("track_name"), - "artist": { - "name": track["track_metadata"].get("artist_name") - }, + "artist": {"name": track["track_metadata"].get("artist_name")}, "mbid": mbid, "release_mbid": mbid_mapping.get("release_mbid"), "listened_at": track.get("listened_at"), @@ -148,9 +144,6 @@ class ListenBrainzPlugin(BeetsPlugin): return self._make_request(url) def get_listenbrainz_playlists(self): - """Returns a list of playlists created by ListenBrainz.""" - import re - resp = self.get_playlists_createdfor(self.username) playlists = resp.get("playlists") listenbrainz_playlists = [] @@ -159,35 +152,24 @@ class ListenBrainzPlugin(BeetsPlugin): playlist_info = playlist.get("playlist") if playlist_info.get("creator") == "listenbrainz": title = playlist_info.get("title") - match = re.search( - r"(Missed Recordings of \d{4}|Discoveries of \d{4})", title - ) - if "Exploration" in title: - playlist_type = "Exploration" - elif "Jams" in title: - playlist_type = "Jams" - elif match: - playlist_type = match.group(1) - else: - playlist_type = None - if "week of " in title: + self._log.debug(f"Playlist title: {title}") + playlist_type = "Exploration" if "Exploration" in title else "Jams" + if "week of" in title: date_str = title.split("week of ")[1].split(" ")[0] - date = datetime.datetime.strptime( - date_str, "%Y-%m-%d" - ).date() + date = datetime.datetime.strptime(date_str, "%Y-%m-%d").date() else: - date = None + continue identifier = playlist_info.get("identifier") id = identifier.split("/")[-1] - if playlist_type in ["Jams", "Exploration"]: - listenbrainz_playlists.append( - { - "type": playlist_type, - "date": date, - "identifier": id, - "title": title, - } - ) + listenbrainz_playlists.append( + {"type": playlist_type, "date": date, "identifier": id} + ) + listenbrainz_playlists = sorted(listenbrainz_playlists, key=lambda x: x["type"]) + listenbrainz_playlists = sorted( + listenbrainz_playlists, key=lambda x: x["date"], reverse=True + ) + for playlist in listenbrainz_playlists: + self._log.debug(f'Playlist: {playlist["type"]} - {playlist["date"]}') return listenbrainz_playlists def get_playlist(self, identifier): @@ -199,17 +181,21 @@ class ListenBrainzPlugin(BeetsPlugin): """This function returns a list of tracks in the playlist.""" tracks = [] for track in playlist.get("playlist").get("track"): - tracks.append( - { - "artist": track.get("creator"), - "identifier": track.get("identifier").split("/")[-1], - "title": track.get("title"), - } - ) + identifier = track.get("identifier") + if isinstance(identifier, list): + identifier = identifier[0] + artist = track.get( + "creator", "Unknown artist" + ) # Set a default value if 'creator' key is not present + track_dict = { + "artist": artist, + "identifier": identifier.split("/")[-1], + "title": track.get("title"), + } + tracks.append(track_dict) return self.get_track_info(tracks) def get_track_info(self, tracks): - """Returns a list of track info.""" track_info = [] for track in tracks: identifier = track.get("identifier") @@ -242,25 +228,32 @@ class ListenBrainzPlugin(BeetsPlugin): ) return track_info - def get_weekly_playlist(self, index): - """Returns a list of weekly playlists based on the index.""" + def get_weekly_playlist(self, playlist_type, most_recent=True): + # Fetch all playlists playlists = self.get_listenbrainz_playlists() - playlist = self.get_playlist(playlists[index].get("identifier")) - self._log.info(f"Getting {playlist.get('playlist').get('title')}") + # Filter playlists by type + filtered_playlists = [p for p in playlists if p["type"] == playlist_type] + # Sort playlists by date in descending order + sorted_playlists = sorted( + filtered_playlists, key=lambda x: x["date"], reverse=True + ) + # Select the most recent or older playlist based on the most_recent flag + selected_playlist = sorted_playlists[0] if most_recent else sorted_playlists[1] + self._log.debug( + f"Selected playlist: {selected_playlist['type']} - {selected_playlist['date']}" + ) + # Fetch and return tracks from the selected playlist + playlist = self.get_playlist(selected_playlist.get("identifier")) return self.get_tracks_from_playlist(playlist) def get_weekly_exploration(self): - """Returns a list of weekly exploration.""" - return self.get_weekly_playlist(0) + return self.get_weekly_playlist("Exploration", most_recent=True) def get_weekly_jams(self): - """Returns a list of weekly jams.""" - return self.get_weekly_playlist(1) + return self.get_weekly_playlist("Jams", most_recent=True) def get_last_weekly_exploration(self): - """Returns a list of weekly exploration.""" - return self.get_weekly_playlist(3) + return self.get_weekly_playlist("Exploration", most_recent=False) def get_last_weekly_jams(self): - """Returns a list of weekly jams.""" - return self.get_weekly_playlist(3) + return self.get_weekly_playlist("Jams", most_recent=False) From c49de7afe6a37d4d0372d3c3e33799d11dc7b69a Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Fri, 25 Oct 2024 10:53:26 -0400 Subject: [PATCH 2/5] Update changelog.rst --- docs/changelog.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index a2e15dd31..b159e9bb6 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -253,6 +253,8 @@ New features: Bug fixes: +* Improve ListenBrainz error handling. + :bug:`5459` * :doc:`/plugins/deezer`: Improve requests error handling. * :doc:`/plugins/lastimport`: Improve error handling in the `process_tracks` function and enable it to be used with other plugins. * :doc:`/plugins/spotify`: Improve handling of ConnectionError. From c1b4b58e65ca3109bac13fadb3856bc795c461f2 Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Sun, 10 Nov 2024 20:23:11 -0500 Subject: [PATCH 3/5] Update beetsplug/listenbrainz.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Šarūnas Nejus --- beetsplug/listenbrainz.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/beetsplug/listenbrainz.py b/beetsplug/listenbrainz.py index d1efd2275..1440497c8 100644 --- a/beetsplug/listenbrainz.py +++ b/beetsplug/listenbrainz.py @@ -184,15 +184,14 @@ class ListenBrainzPlugin(BeetsPlugin): identifier = track.get("identifier") if isinstance(identifier, list): identifier = identifier[0] - artist = track.get( - "creator", "Unknown artist" - ) # Set a default value if 'creator' key is not present - track_dict = { - "artist": artist, - "identifier": identifier.split("/")[-1], - "title": track.get("title"), - } - tracks.append(track_dict) + + tracks.append( + { + "artist": track.get("creator", "Unknown artist"), + "identifier": identifier.split("/")[-1], + "title": track.get("title"), + } + ) return self.get_track_info(tracks) def get_track_info(self, tracks): From 35c6e13255114cee29aa622a7856f67c58290794 Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Sun, 10 Nov 2024 20:25:28 -0500 Subject: [PATCH 4/5] Update line length --- beetsplug/listenbrainz.py | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/beetsplug/listenbrainz.py b/beetsplug/listenbrainz.py index 1440497c8..ecfa60fcb 100644 --- a/beetsplug/listenbrainz.py +++ b/beetsplug/listenbrainz.py @@ -116,9 +116,13 @@ class ListenBrainzPlugin(BeetsPlugin): mbid = self.get_mb_recording_id(track) tracks.append( { - "album": {"name": track["track_metadata"].get("release_name")}, + "album": { + "name": track["track_metadata"].get("release_name") + }, "name": track["track_metadata"].get("track_name"), - "artist": {"name": track["track_metadata"].get("artist_name")}, + "artist": { + "name": track["track_metadata"].get("artist_name") + }, "mbid": mbid, "release_mbid": mbid_mapping.get("release_mbid"), "listened_at": track.get("listened_at"), @@ -153,10 +157,14 @@ class ListenBrainzPlugin(BeetsPlugin): if playlist_info.get("creator") == "listenbrainz": title = playlist_info.get("title") self._log.debug(f"Playlist title: {title}") - playlist_type = "Exploration" if "Exploration" in title else "Jams" + playlist_type = ( + "Exploration" if "Exploration" in title else "Jams" + ) if "week of" in title: date_str = title.split("week of ")[1].split(" ")[0] - date = datetime.datetime.strptime(date_str, "%Y-%m-%d").date() + date = datetime.datetime.strptime( + date_str, "%Y-%m-%d" + ).date() else: continue identifier = playlist_info.get("identifier") @@ -164,12 +172,16 @@ class ListenBrainzPlugin(BeetsPlugin): listenbrainz_playlists.append( {"type": playlist_type, "date": date, "identifier": id} ) - listenbrainz_playlists = sorted(listenbrainz_playlists, key=lambda x: x["type"]) + listenbrainz_playlists = sorted( + listenbrainz_playlists, key=lambda x: x["type"] + ) listenbrainz_playlists = sorted( listenbrainz_playlists, key=lambda x: x["date"], reverse=True ) for playlist in listenbrainz_playlists: - self._log.debug(f'Playlist: {playlist["type"]} - {playlist["date"]}') + self._log.debug( + f'Playlist: {playlist["type"]} - {playlist["date"]}' + ) return listenbrainz_playlists def get_playlist(self, identifier): @@ -231,13 +243,17 @@ class ListenBrainzPlugin(BeetsPlugin): # Fetch all playlists playlists = self.get_listenbrainz_playlists() # Filter playlists by type - filtered_playlists = [p for p in playlists if p["type"] == playlist_type] + filtered_playlists = [ + p for p in playlists if p["type"] == playlist_type + ] # Sort playlists by date in descending order sorted_playlists = sorted( filtered_playlists, key=lambda x: x["date"], reverse=True ) # Select the most recent or older playlist based on the most_recent flag - selected_playlist = sorted_playlists[0] if most_recent else sorted_playlists[1] + selected_playlist = ( + sorted_playlists[0] if most_recent else sorted_playlists[1] + ) self._log.debug( f"Selected playlist: {selected_playlist['type']} - {selected_playlist['date']}" ) From b9c6ee208eff45f9a4285160585540a7ee89e4e8 Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Sun, 10 Nov 2024 20:27:41 -0500 Subject: [PATCH 5/5] lint error --- beetsplug/listenbrainz.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/beetsplug/listenbrainz.py b/beetsplug/listenbrainz.py index ecfa60fcb..1e2912793 100644 --- a/beetsplug/listenbrainz.py +++ b/beetsplug/listenbrainz.py @@ -255,7 +255,8 @@ class ListenBrainzPlugin(BeetsPlugin): sorted_playlists[0] if most_recent else sorted_playlists[1] ) self._log.debug( - f"Selected playlist: {selected_playlist['type']} - {selected_playlist['date']}" + f"Selected playlist: {selected_playlist['type']} " + f"- {selected_playlist['date']}" ) # Fetch and return tracks from the selected playlist playlist = self.get_playlist(selected_playlist.get("identifier"))