Skip to content

Commit 98510fc

Browse files
authored
Merge pull request #406 from exislow/165-feature-get-playlist-track-number
✨ Implemented playlist track position naming (`{list_pos}`) for downloads. Fixes #165
2 parents d7a9227 + 819655d commit 98510fc

File tree

3 files changed

+56
-16
lines changed

3 files changed

+56
-16
lines changed

tidal_dl_ng/download.py

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,8 @@ def item(
329329
quality_audio: Quality | None = None,
330330
quality_video: QualityVideo | None = None,
331331
is_parent_album: bool = False,
332+
list_position: int = 0,
333+
list_total: int = 0,
332334
) -> (bool, pathlib.Path):
333335
try:
334336
if media_id and media_type:
@@ -363,7 +365,9 @@ def item(
363365
metadata_tags=[] if isinstance(media, Video) else media.media_metadata_tags,
364366
is_video=isinstance(media, Video),
365367
)
366-
file_name_relative: str = format_path_media(file_template, media, self.settings.data.album_track_num_pad_min)
368+
file_name_relative: str = format_path_media(
369+
file_template, media, self.settings.data.album_track_num_pad_min, list_position, list_total
370+
)
367371
path_media_dst: pathlib.Path = (
368372
pathlib.Path(self.path_base).expanduser() / (file_name_relative + file_extension_dummy)
369373
).absolute()
@@ -732,7 +736,7 @@ def items(
732736
return
733737

734738
# Create file name and path
735-
file_name_relative: str = format_path_media(file_template, media, self.settings.data.album_track_num_pad_min)
739+
file_name_relative: str = format_path_media(file_template, media)
736740

737741
# Get the name of the list and check, if videos should be included.
738742
list_media_name: str = name_builder_title(media)
@@ -756,7 +760,12 @@ def items(
756760
)
757761

758762
is_album: bool = isinstance(media, Album)
763+
# TODO: Refactor strings to constants (also in cfg.py)
764+
sort_by_track_num: bool = (
765+
True if "album_track_num" in file_name_relative or "list_pos" in file_name_relative else False
766+
)
759767
result_dirs: [pathlib.Path] = []
768+
list_total: int = len(items)
760769

761770
# Iterate through list items
762771
while not progress.finished:
@@ -771,8 +780,10 @@ def items(
771780
quality_video=quality_video,
772781
download_delay=download_delay,
773782
is_parent_album=is_album,
783+
list_position=count + 1,
784+
list_total=list_total,
774785
)
775-
for item_media in items
786+
for count, item_media in enumerate(items)
776787
]
777788

778789
# Report results as they become available
@@ -800,11 +811,13 @@ def items(
800811

801812
# Create playlist file
802813
if self.settings.data.playlist_create:
803-
self.playlist_populate(set(result_dirs), list_media_name, is_album)
814+
self.playlist_populate(set(result_dirs), list_media_name, is_album, sort_by_track_num)
804815

805816
self.fn_logger.info(f"Finished list '{list_media_name}'.")
806817

807-
def playlist_populate(self, dirs_scoped: [pathlib.Path], name_list: str, is_album: bool) -> [pathlib.Path]:
818+
def playlist_populate(
819+
self, dirs_scoped: [pathlib.Path], name_list: str, is_album: bool, sort_alphabetically
820+
) -> [pathlib.Path]:
808821
result: [pathlib.Path] = []
809822

810823
# For each dir, which contains tracks
@@ -821,8 +834,11 @@ def playlist_populate(self, dirs_scoped: [pathlib.Path], name_list: str, is_albu
821834
for extension_audio in AudioExtensions:
822835
path_tracks = path_tracks + list(dir_scoped.glob(f"*{extension_audio!s}"))
823836

824-
# If it is not an album sort by modification time
825-
if not is_album:
837+
# Sort alphabetically, e.g. if items are prefixed with numbers
838+
if sort_alphabetically:
839+
path_tracks.sort()
840+
elif not is_album:
841+
# If it is not an album sort by modification time
826842
path_tracks.sort(key=lambda x: os.path.getmtime(x))
827843

828844
# Write data to m3u file

tidal_dl_ng/helper/path.py

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,11 @@ def path_file_settings() -> str:
5151

5252

5353
def format_path_media(
54-
fmt_template: str, media: Track | Album | Playlist | UserPlaylist | Video | Mix, album_track_num_pad_min: int = 0
54+
fmt_template: str,
55+
media: Track | Album | Playlist | UserPlaylist | Video | Mix,
56+
album_track_num_pad_min: int = 0,
57+
list_pos: int = 0,
58+
list_total: int = 0,
5559
) -> str:
5660
result = fmt_template
5761

@@ -61,7 +65,7 @@ def format_path_media(
6165

6266
for _matchNum, match in enumerate(matches, start=1):
6367
template_str = match.group()
64-
result_fmt = format_str_media(match.group(1), media, album_track_num_pad_min)
68+
result_fmt = format_str_media(match.group(1), media, album_track_num_pad_min, list_pos, list_total)
6569

6670
if result_fmt != match.group(1):
6771
value = sanitize_filename(result_fmt)
@@ -71,7 +75,11 @@ def format_path_media(
7175

7276

7377
def format_str_media(
74-
name: str, media: Track | Album | Playlist | UserPlaylist | Video | Mix, album_track_num_pad_min: int = 0
78+
name: str,
79+
media: Track | Album | Playlist | UserPlaylist | Video | Mix,
80+
album_track_num_pad_min: int = 0,
81+
list_pos: int = 0,
82+
list_total: int = 0,
7583
) -> str:
7684
result: str = name
7785

@@ -101,12 +109,11 @@ def format_str_media(
101109
result = media.album.name
102110
case "album_track_num":
103111
if isinstance(media, Track | Video):
104-
num_tracks: int = media.album.num_tracks if hasattr(media, "album") else 1
105-
count_digits: int = int(math.log10(num_tracks)) + 1
106-
count_digits_computed: int = (
107-
count_digits if count_digits > album_track_num_pad_min else album_track_num_pad_min
112+
result = calculate_number_padding(
113+
album_track_num_pad_min,
114+
media.track_num,
115+
media.album.num_tracks if hasattr(media, "album") else 1,
108116
)
109-
result = str(media.track_num).zfill(count_digits_computed)
110117
case "album_num_tracks":
111118
if isinstance(media, Track | Video):
112119
result = str(media.album.num_tracks if hasattr(media, "album") else 1)
@@ -176,6 +183,10 @@ def format_str_media(
176183
case "isrc":
177184
if isinstance(media, Track):
178185
result = media.isrc
186+
case "list_pos":
187+
if isinstance(media, Track | Video):
188+
# TODO: Rename `album_track_num_pad_min` globally.
189+
result = calculate_number_padding(album_track_num_pad_min, list_pos, list_total)
179190
except Exception as e:
180191
# TODO: Implement better exception logging.
181192
print(e)
@@ -185,6 +196,19 @@ def format_str_media(
185196
return result
186197

187198

199+
def calculate_number_padding(padding_minimum: int, item_position: int, items_max: int) -> str:
200+
result: str
201+
202+
if items_max > 0:
203+
count_digits: int = int(math.log10(items_max)) + 1
204+
count_digits_computed: int = count_digits if count_digits > padding_minimum else padding_minimum
205+
result = str(item_position).zfill(count_digits_computed)
206+
else:
207+
result = str(item_position)
208+
209+
return result
210+
211+
188212
def get_format_template(
189213
media: Track | Album | Playlist | UserPlaylist | Video | Mix | MediaType, settings
190214
) -> str | bool:

tidal_dl_ng/model/cfg.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class Settings:
2727
"Albums/{album_artist} - {album_title}{album_explicit}/{track_volume_num_optional}"
2828
"{album_track_num}. {artist_name} - {track_title}{album_explicit}"
2929
)
30-
format_playlist: str = "Playlists/{playlist_name}/{artist_name} - {track_title}"
30+
format_playlist: str = "Playlists/{playlist_name}/{list_pos}. {artist_name} - {track_title}"
3131
format_mix: str = "Mix/{mix_name}/{artist_name} - {track_title}"
3232
format_track: str = "Tracks/{artist_name} - {track_title}{track_explicit}"
3333
format_video: str = "Videos/{artist_name} - {track_title}{track_explicit}"

0 commit comments

Comments
 (0)