diff --git a/README.md b/README.md index 8484651..64de143 100644 --- a/README.md +++ b/README.md @@ -183,6 +183,8 @@ You can customize the directory structure and track filenames using `custom_dir_ * `%showname%` (for episodes) * `%episodetitle%` (for episodes) * `%podcastgenre%` (for episodes) +* `%playlist%` (for playlist downloads: playlist name) +* `%playlist_num%` (for playlist downloads: 1-based index of the track within the playlist; respects `pad_tracks`) **Example:** diff --git a/deezspot/deezloader/__download__.py b/deezspot/deezloader/__download__.py index a1d0c30..086e3a3 100644 --- a/deezspot/deezloader/__download__.py +++ b/deezspot/deezloader/__download__.py @@ -356,6 +356,22 @@ class EASY_DW: custom_track_format = getattr(self.__preferences, 'custom_track_format', None) pad_tracks = getattr(self.__preferences, 'pad_tracks', True) self.__song_metadata_dict['artist_separator'] = getattr(self.__preferences, 'artist_separator', '; ') + # Inject playlist placeholders if in playlist context + try: + if self.__parent == 'playlist' and hasattr(self.__preferences, 'json_data') and self.__preferences.json_data: + playlist_data = self.__preferences.json_data + # Support both Deezer playlistObject and raw dict (Spotify metadata case) + if isinstance(playlist_data, dict): + playlist_name = playlist_data.get('name') or playlist_data.get('title') or 'unknown' + else: + # playlistObject has 'title' + playlist_name = getattr(playlist_data, 'title', 'unknown') + self.__song_metadata_dict['playlist'] = playlist_name + # 1-based index already stored in preferences during iteration + self.__song_metadata_dict['playlist_num'] = getattr(self.__preferences, 'track_number', None) or 0 + except Exception: + # Non-fatal if playlist metadata is not available + pass self.__song_path = set_path( self.__song_metadata_dict, self.__output_dir, diff --git a/deezspot/libutils/utils.py b/deezspot/libutils/utils.py index 00ca297..0d174bb 100644 --- a/deezspot/libutils/utils.py +++ b/deezspot/libutils/utils.py @@ -194,7 +194,7 @@ def apply_custom_format(format_str, metadata: dict, pad_tracks=True) -> str: # Fallback for string-based dates like "YYYY-MM-DD" or just "YYYY" return str(value).split('-')[0] - if pad_tracks and full_key in ['tracknum', 'discnum']: + if pad_tracks and full_key in ['tracknum', 'discnum', 'playlist_num']: str_value = str(value) # Pad with leading zero if it's a single digit if str_value.isdigit() and len(str_value) == 1: diff --git a/deezspot/spotloader/__download__.py b/deezspot/spotloader/__download__.py index 7e5ad56..80c108d 100644 --- a/deezspot/spotloader/__download__.py +++ b/deezspot/spotloader/__download__.py @@ -144,6 +144,20 @@ class EASY_DW: pad_tracks = getattr(self.__preferences, 'pad_tracks', True) # Ensure the separator is available to formatting utils for indexed placeholders self.__song_metadata_dict['artist_separator'] = getattr(self.__preferences, 'artist_separator', '; ') + # Inject playlist placeholders if in playlist context + try: + if self.__parent == 'playlist' and hasattr(self.__preferences, 'json_data') and self.__preferences.json_data: + playlist_data = self.__preferences.json_data + playlist_name = None + if isinstance(playlist_data, dict): + playlist_name = playlist_data.get('name') or playlist_data.get('title') + if not playlist_name and hasattr(playlist_data, 'title'): + playlist_name = getattr(playlist_data, 'title') + self.__song_metadata_dict['playlist'] = playlist_name or 'unknown' + self.__song_metadata_dict['playlist_num'] = getattr(self.__preferences, 'track_number', None) or 0 + except Exception: + # If playlist info missing, skip silently + pass self.__song_path = set_path( self.__song_metadata_dict, self.__output_dir,