From 00b179dbd74a9b8e9b71895b77e91fd73ef2b07d Mon Sep 17 00:00:00 2001 From: Xoconoch Date: Mon, 9 Jun 2025 14:51:32 -0600 Subject: [PATCH] finally --- deezspot/deezloader/__download__.py | 134 +++++++++++++++++++--------- deezspot/deezloader/__init__.py | 77 ++++++++++++++-- 2 files changed, 158 insertions(+), 53 deletions(-) diff --git a/deezspot/deezloader/__download__.py b/deezspot/deezloader/__download__.py index 054060f..06856d5 100644 --- a/deezspot/deezloader/__download__.py +++ b/deezspot/deezloader/__download__.py @@ -323,17 +323,30 @@ class EASY_DW: # Add parent info based on parent type if self.__parent == "playlist" and hasattr(self.__preferences, "json_data"): playlist_data = self.__preferences.json_data - playlist_name = playlist_data.get('title', 'unknown') - total_tracks = getattr(self.__preferences, 'total_tracks', 0) - current_track = getattr(self.__preferences, 'track_number', 0) + is_spotify_playlist = 'display_name' in playlist_data.get('owner', {}) - # Format for playlist-parented tracks exactly as required + if is_spotify_playlist: + playlist_name = playlist_data.get('name', 'unknown') + owner = playlist_data.get('owner', {}).get('display_name', 'unknown') + total_tracks = playlist_data.get('tracks', {}).get('total', 0) + playlist_id = playlist_data.get('id', '') + url = f"https://open.spotify.com/playlist/{playlist_id}" + else: # Deezer logic + playlist_name = playlist_data.get('title', 'unknown') + owner = playlist_data.get('creator', {}).get('name', 'unknown') + total_tracks = getattr(self.__preferences, 'total_tracks', 0) + playlist_id = playlist_data.get('id', '') + url = f"https://deezer.com/playlist/{playlist_id}" + + total_tracks_val = getattr(self.__preferences, 'total_tracks', total_tracks) + current_track_val = getattr(self.__preferences, 'track_number', 0) + parent = { "type": "playlist", "name": playlist_name, - "owner": playlist_data.get('creator', {}).get('name', 'unknown'), - "total_tracks": total_tracks, - "url": f"https://deezer.com/playlist/{self.__preferences.json_data.get('id', '')}" + "owner": owner, + "total_tracks": total_tracks_val, + "url": url } elif self.__parent == "album": album_name = self.__song_metadata.get('album', '') @@ -375,8 +388,8 @@ class EASY_DW: convert_to=self.__convert_to, bitrate=self.__bitrate, parent=parent, - current_track=current_track, - total_tracks=total_tracks, + current_track=current_track_val, + total_tracks=total_tracks_val, summary=summary ) # self.__c_track might not be fully initialized here if __write_track() hasn't been called @@ -415,20 +428,33 @@ class EASY_DW: parent = None current_track = None total_tracks = None + summary = None spotify_url = getattr(self.__preferences, 'spotify_url', None) url = spotify_url if spotify_url else self.__link if self.__parent == "playlist" and hasattr(self.__preferences, "json_data"): playlist_data = self.__preferences.json_data + is_spotify_playlist = 'display_name' in playlist_data.get('owner', {}) + if is_spotify_playlist: + playlist_name = playlist_data.get('name', 'unknown') + owner = playlist_data.get('owner', {}).get('display_name', 'unknown') + playlist_id = playlist_data.get('id', '') + playlist_url = f"https://open.spotify.com/playlist/{playlist_id}" + else: # Deezer logic + playlist_name = playlist_data.get('title', 'unknown') + owner = playlist_data.get('creator', {}).get('name', 'unknown') + playlist_id = playlist_data.get('id', '') + playlist_url = f"https://deezer.com/playlist/{playlist_data.get('id', '')}" + total_tracks = getattr(self.__preferences, 'total_tracks', 0) current_track = getattr(self.__preferences, 'track_number', 0) parent = { "type": "playlist", - "name": playlist_data.get('title', 'unknown'), - "owner": playlist_data.get('creator', {}).get('name', 'unknown'), + "name": playlist_name, + "owner": owner, "total_tracks": total_tracks, - "url": f"https://deezer.com/playlist/{playlist_data.get('id', '')}" + "url": playlist_url } elif self.__parent == "album": album_name = self.__song_metadata.get('album', '') @@ -442,18 +468,34 @@ class EASY_DW: "total_tracks": total_tracks, "url": f"https://deezer.com/album/{self.__preferences.song_metadata.get('album_id', '')}" } + + if self.__parent is None: + track_info = { + "name": self.__song_metadata.get('music', 'Unknown Track'), + "artist": self.__song_metadata.get('artist', 'Unknown Artist') + } + summary = { + "successful_tracks": [f"{track_info['name']} - {track_info['artist']}"], + "skipped_tracks": [], + "failed_tracks": [], + "total_successful": 1, + "total_skipped": 0, + "total_failed": 0, + } report_progress( reporter=Download_JOB.progress_reporter, report_type="track", song=self.__song_metadata['music'], artist=self.__song_metadata['artist'], + album=self.__song_metadata.get("album", ""), status="done", url=url, parent=parent, current_track=current_track, total_tracks=total_tracks, - convert_to=self.__convert_to + convert_to=self.__convert_to, + summary=summary ) except Exception as e: # Covers failures within download_try or download_episode_try @@ -589,15 +631,26 @@ class EASY_DW: if self.__parent == "playlist" and hasattr(self.__preferences, "json_data"): playlist_data = self.__preferences.json_data - playlist_name = playlist_data.get('title', 'unknown') + is_spotify_playlist = 'display_name' in playlist_data.get('owner', {}) + if is_spotify_playlist: + playlist_name = playlist_data.get('name', 'unknown') + owner = playlist_data.get('owner', {}).get('display_name', 'unknown') + playlist_id = playlist_data.get('id', '') + playlist_url = f"https://open.spotify.com/playlist/{playlist_id}" + else: # Deezer logic + playlist_name = playlist_data.get('title', 'unknown') + owner = playlist_data.get('creator', {}).get('name', 'unknown') + playlist_id = playlist_data.get('id', '') + playlist_url = f"https://deezer.com/playlist/{playlist_data.get('id', '')}" + total_tracks = getattr(self.__preferences, 'total_tracks', 0) current_track = getattr(self.__preferences, 'track_number', 0) parent = { "type": "playlist", "name": playlist_name, - "owner": playlist_data.get('creator', {}).get('name', 'unknown'), + "owner": owner, "total_tracks": total_tracks, - "url": f"https://deezer.com/playlist/{self.__preferences.json_data.get('id', '')}" + "url": playlist_url } elif self.__parent == "album": album_name = self.__song_metadata.get('album', '') @@ -617,6 +670,7 @@ class EASY_DW: report_type="track", song=self.__song_metadata.get("music", ""), artist=self.__song_metadata.get("artist", ""), + album=self.__song_metadata.get("album", ""), status="initializing", url=url, parent=parent, @@ -720,14 +774,25 @@ class EASY_DW: if self.__parent == "playlist" and hasattr(self.__preferences, "json_data"): playlist_data = self.__preferences.json_data - playlist_name = playlist_data.get('title', 'unknown') + is_spotify_playlist = 'display_name' in playlist_data.get('owner', {}) + if is_spotify_playlist: + playlist_name = playlist_data.get('name', 'unknown') + owner = playlist_data.get('owner', {}).get('display_name', 'unknown') + playlist_id = playlist_data.get('id', '') + playlist_url = f"https://open.spotify.com/playlist/{playlist_id}" + else: # Deezer logic + playlist_name = playlist_data.get('title', 'unknown') + owner = playlist_data.get('creator', {}).get('name', 'unknown') + playlist_id = playlist_data.get('id', '') + playlist_url = f"https://deezer.com/playlist/{playlist_data.get('id', '')}" + total_tracks = getattr(self.__preferences, 'total_tracks', 0) current_track = getattr(self.__preferences, 'track_number', 0) parent = { "type": "playlist", "name": playlist_name, - "owner": playlist_data.get('creator', {}).get('name', 'unknown'), + "owner": owner, "total_tracks": total_tracks, - "url": f"https://deezer.com/playlist/{playlist_data.get('id', '')}" + "url": playlist_url } elif self.__parent == "album": album_name = self.__song_metadata.get('album', '') @@ -938,10 +1003,12 @@ class EASY_DW: class DW_TRACK: def __init__( self, - preferences: Preferences + preferences: Preferences, + parent: str = None ) -> None: self.__preferences = preferences + self.__parent = parent self.__ids = self.__preferences.ids self.__song_metadata = self.__preferences.song_metadata self.__quality_download = self.__preferences.quality_download @@ -956,7 +1023,7 @@ class DW_TRACK: infos_dw['media_url'] = media[0] # For individual tracks, parent is None (not part of album or playlist) - track = EASY_DW(infos_dw, self.__preferences, parent=None).easy_dw() + track = EASY_DW(infos_dw, self.__preferences, parent=self.__parent).easy_dw() # Check if track failed but was NOT intentionally skipped if not track.success and not getattr(track, 'was_skipped', False): @@ -968,29 +1035,6 @@ class DW_TRACK: logger.error(f"{error_msg} (Link: {current_link})") raise TrackNotFound(message=error_msg, url=current_link) - if track.success and not getattr(track, 'was_skipped', False): - track_info = { - "name": track.tags.get('music', 'Unknown Track'), - "artist": track.tags.get('artist', 'Unknown Artist') - } - summary = { - "successful_tracks": [f"{track_info['name']} - {track_info['artist']}"], - "skipped_tracks": [], - "failed_tracks": [], - "total_successful": 1, - "total_skipped": 0, - "total_failed": 0, - } - report_progress( - reporter=Download_JOB.progress_reporter, - report_type="track", - song=track_info['name'], - artist=track_info['artist'], - status="done", - url=track.link, - summary=summary - ) - return track class DW_ALBUM: @@ -1401,6 +1445,8 @@ class DW_PLAYLIST: c_preferences.song_metadata = c_song_metadata_item # This is the full metadata dict for a successful track c_preferences.track_number = idx c_preferences.total_tracks = total_tracks + c_preferences.json_data = self.__json_data + c_preferences.link = f"https://deezer.com/track/{c_preferences.ids}" # Download the track using the EASY_DW downloader # Wrap this in a try-except block to handle individual track failures diff --git a/deezspot/deezloader/__init__.py b/deezspot/deezloader/__init__.py index 5be79a9..fdadaff 100644 --- a/deezspot/deezloader/__init__.py +++ b/deezspot/deezloader/__init__.py @@ -105,7 +105,8 @@ class DeeLogin: convert_to=None, bitrate=None, save_cover=stock_save_cover, - market=stock_market + market=stock_market, + playlist_context=None ) -> Track: link_is_valid(link_track) @@ -171,8 +172,15 @@ class DeeLogin: preferences.save_cover = save_cover preferences.market = market + if playlist_context: + preferences.json_data = playlist_context['json_data'] + preferences.track_number = playlist_context['track_number'] + preferences.total_tracks = playlist_context['total_tracks'] + preferences.spotify_url = playlist_context['spotify_url'] + try: - track = DW_TRACK(preferences).dw() + parent = 'playlist' if playlist_context else None + track = DW_TRACK(preferences, parent=parent).dw() return track except Exception as e: logger.error(f"Failed to download track: {str(e)}") @@ -211,7 +219,8 @@ class DeeLogin: convert_to=None, bitrate=None, save_cover=stock_save_cover, - market=stock_market + market=stock_market, + playlist_context=None ) -> Album: link_is_valid(link_album) @@ -252,6 +261,12 @@ class DeeLogin: preferences.save_cover = save_cover preferences.market = market + if playlist_context: + preferences.json_data = playlist_context['json_data'] + preferences.track_number = playlist_context['track_number'] + preferences.total_tracks = playlist_context['total_tracks'] + preferences.spotify_url = playlist_context['spotify_url'] + album = DW_ALBUM(preferences).dw() return album @@ -631,7 +646,8 @@ class DeeLogin: convert_to=None, bitrate=None, save_cover=stock_save_cover, - market=stock_market + market=stock_market, + playlist_context=None ) -> Track: link_dee = self.convert_spoty_to_dee_link_track(link_track) @@ -652,7 +668,8 @@ class DeeLogin: convert_to=convert_to, bitrate=bitrate, save_cover=save_cover, - market=market + market=market, + playlist_context=playlist_context ) return track @@ -674,7 +691,8 @@ class DeeLogin: convert_to=None, bitrate=None, save_cover=stock_save_cover, - market=stock_market + market=stock_market, + playlist_context=None ) -> Album: link_dee = self.convert_spoty_to_dee_link_album(link_album) @@ -693,7 +711,8 @@ class DeeLogin: convert_to=convert_to, bitrate=bitrate, save_cover=save_cover, - market=market + market=market, + playlist_context=playlist_context ) return album @@ -744,6 +763,21 @@ class DeeLogin: for index, item in enumerate(playlist_tracks, 1): is_track = item.get('track') if not is_track: + logger.warning(f"Skipping an item in playlist {playlist_name} as it does not appear to be a valid track object.") + # Create a placeholder for the failed item + failed_track_tags = { + 'name': 'Unknown Skipped Item', + 'artist': 'Unknown Artist', + 'error_type': 'InvalidItemStructure', + 'message': 'Playlist item was not a valid track object.' + } + failed_track = Track( + tags=failed_track_tags, + song_path=None, file_format=None, quality=None, link=None, ids=None + ) + failed_track.success = False + failed_track.error_message = 'Playlist item was not a valid track object.' + tracks.append(failed_track) continue track_info = is_track @@ -759,6 +793,13 @@ class DeeLogin: link_track = external_urls['spotify'] try: + # Add context for reporting + playlist_context={ + 'json_data': playlist_json, # spotify json + 'track_number': index, + 'total_tracks': total_tracks, + 'spotify_url': link_track # The individual track's spotify URL + } # Download each track individually via the Spotify-to-Deezer conversion method. downloaded_track = self.download_trackspo( link_track, @@ -776,12 +817,30 @@ class DeeLogin: convert_to=convert_to, bitrate=bitrate, save_cover=save_cover, - market=market + market=market, + playlist_context=playlist_context ) tracks.append(downloaded_track) except (TrackNotFound, NoDataApi) as e: logger.error(f"Failed to download track: {track_name} - {artist_name}") - tracks.append(f"{track_name} - {artist_name}") + + # Create a proper failed Track object + error_message = e.message if hasattr(e, 'message') else str(e) + failed_track_tags = { + 'name': track_name, + 'artist': artist_name, + 'error_type': e.__class__.__name__, + 'message': error_message + } + failed_track = Track( + tags=failed_track_tags, + song_path=None, file_format=None, quality=None, + link=link_track, # The spotify track link + ids=None # We don't have the deezer ID + ) + failed_track.success = False + failed_track.error_message = error_message + tracks.append(failed_track) # Done status successful_tracks_list = []