Closed motlaghreyhan closed 5 months ago
album_num_volumes
and track_volume_num
is implemented in the master branch.
Thanks! I do get errors when using latest master and having those variables in my path. It looks like they need to be strings not integers?
╭───────────────────────────── Traceback (most recent call last) ─────────────────────────────╮
│ /home/rmotlagh/tidal-dl-ng/tidal_dl_ng/cli.py:184 in download │
│ │
│ 181 │ │ │ │ │ media_id=item_id, media_type=media_type, file_template=file_templ │
│ 182 │ │ │ │ ) │
│ 183 │ │ │ elif media_type in [MediaType.ALBUM, MediaType.PLAYLIST, MediaType.MIX]: │
│ ❱ 184 │ │ │ │ dl.items( │
│ 185 │ │ │ │ │ media_id=item_id, │
│ 186 │ │ │ │ │ media_type=media_type, │
│ 187 │ │ │ │ │ file_template=file_template, │
│ │
│ ╭──────────────────────────────────────── locals ─────────────────────────────────────────╮ │
│ │ ctx = <click.core.Context object at 0x7f9938573e50> │ │
│ │ dl = <tidal_dl_ng.download.Download object at 0x7f993858d4d0> │ │
│ │ file_template = '{album_artist}/{album_title} │ │
│ │ [{album_year}]/{album_num_volumes}/{album_track_num'+33 │ │
│ │ file_urls = None │ │
│ │ fn_logger = <tidal_dl_ng.helper.wrapper.LoggerWrapped object at 0x7f993858e890> │ │
│ │ item = 'https://tidal.com/browse/album/118390427?u' │ │
│ │ item_id = '118390427' │ │
│ │ media_type = <MediaType.ALBUM: 'album'> │ │
│ │ progress = <rich.progress.Progress object at 0x7f9938572ed0> │ │
│ │ progress_table = <rich.table.Table object at 0x7f9938254250> │ │
│ │ settings = <tidal_dl_ng.config.Settings object at 0x7f9938241150> │ │
│ │ urls = ['https://tidal.com/browse/album/118390427?u'] │ │
│ │ urls_pos_last = 0 │ │
│ ╰─────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ /home/rmotlagh/tidal-dl-ng/tidal_dl_ng/download.py:355 in items │
│ │
│ 352 │ │ │ raise MediaMissing │
│ 353 │ │ │
│ 354 │ │ # Create file name and path │
│ ❱ 355 │ │ file_name_relative = format_path_media(file_template, media) │
│ 356 │ │ │
│ 357 │ │ # Get the name of the list and check, if videos should be included. │
│ 358 │ │ videos_include: bool = True │
│ │
│ ╭──────────────────────────────────────── locals ─────────────────────────────────────────╮ │
│ │ download_delay = True │ │
│ │ file_template = '{album_artist}/{album_title} │ │
│ │ [{album_year}]/{album_num_volumes}/{album_track_num'+33 │ │
│ │ media = <tidalapi.album.Album object at 0x7f993859f010> │ │
│ │ media_id = '118390427' │ │
│ │ media_type = <MediaType.ALBUM: 'album'> │ │
│ │ self = <tidal_dl_ng.download.Download object at 0x7f993858d4d0> │ │
│ │ video_download = False │ │
│ ╰─────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ /home/rmotlagh/tidal-dl-ng/tidal_dl_ng/helper/path.py:58 in format_path_media │
│ │
│ 55 │ │ result_fmt = format_str_media(match.group(1), media) │
│ 56 │ │ │
│ 57 │ │ if result_fmt != match.group(1): │
│ ❱ 58 │ │ │ value = sanitize_filename(result_fmt) │
│ 59 │ │ │ result = result.replace(template_str, value) │
│ 60 │ │
│ 61 │ return result │
│ │
│ ╭──────────────────────────────────────── locals ─────────────────────────────────────────╮ │
│ │ _matchNum = 4 │ │
│ │ fmt_template = '{album_artist}/{album_title} │ │
│ │ [{album_year}]/{album_num_volumes}/{album_track_num'+33 │ │
│ │ match = <re.Match object; span=(44, 63), match='{album_num_volumes}'> │ │
│ │ matches = <callable_iterator object at 0x7f993821f700> │ │
│ │ media = <tidalapi.album.Album object at 0x7f993859f010> │ │
│ │ regex = '\\{(.+?)\\}' │ │
│ │ result = 'The Beatles/Abbey Road (Super Deluxe Edition) │ │
│ │ [1969]/{album_num_volumes}/{album_'+42 │ │
│ │ result_fmt = 3 │ │
│ │ template_str = '{album_num_volumes}' │ │
│ │ value = '1969' │ │
│ ╰─────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ /home/rmotlagh/tidal-dl-ng/.venv/lib/python3.11/site-packages/pathvalidate/_filename.py:466 │
│ in sanitize_filename │
│ │
│ 463 │ │ reserved_name_handler=reserved_name_handler, │
│ 464 │ │ additional_reserved_names=additional_reserved_names, │
│ 465 │ │ validate_after_sanitize=validate_after_sanitize, │
│ ❱ 466 │ ).sanitize(filename, replacement_text) │
│ 467 │
│ │
│ ╭───────────── locals ──────────────╮ │
│ │ additional_reserved_names = None │ │
│ │ check_reserved = None │ │
│ │ filename = 3 │ │
│ │ fs_encoding = None │ │
│ │ max_len = 255 │ │
│ │ null_value_handler = None │ │
│ │ platform = None │ │
│ │ replacement_text = '' │ │
│ │ reserved_name_handler = None │ │
│ │ validate_after_sanitize = False │ │
│ ╰───────────────────────────────────╯ │
│ │
│ /home/rmotlagh/tidal-dl-ng/.venv/lib/python3.11/site-packages/pathvalidate/_filename.py:68 │
│ in sanitize │
│ │
│ 65 │ │
│ 66 │ def sanitize(self, value: PathType, replacement_text: str = "") -> PathType: │
│ 67 │ │ try: │
│ ❱ 68 │ │ │ validate_pathtype(value, allow_whitespaces=not self._is_windows(include_u │
│ 69 │ │ except ValidationError as e: │
│ 70 │ │ │ if e.reason == ErrorReason.NULL_NAME: │
│ 71 │ │ │ │ if isinstance(value, PurePath): │
│ │
│ ╭──────────────────────────────────────── locals ────────────────────────────────────────╮ │
│ │ replacement_text = '' │ │
│ │ self = <pathvalidate._filename.FileNameSanitizer object at 0x7f9938255610> │ │
│ │ value = 3 │ │
│ ╰────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ /home/rmotlagh/tidal-dl-ng/.venv/lib/python3.11/site-packages/pathvalidate/_common.py:32 in │
│ validate_pathtype │
│ │
│ 29 │ if is_null_string(text): │
│ 30 │ │ raise ValidationError(reason=ErrorReason.NULL_NAME) │
│ 31 │ │
│ ❱ 32 │ raise TypeError(f"text must be a string: actual={type(text)}") │
│ 33 │
│ 34 │
│ 35 def to_str(name: PathType) -> str: │
│ │
│ ╭───────────────────────────── locals ─────────────────────────────╮ │
│ │ allow_whitespaces = False │ │
│ │ error_msg = None │ │
│ │ ErrorReason = <enum 'ErrorReason'> │ │
│ │ text = 3 │ │
│ │ ValidationError = <class 'pathvalidate.error.ValidationError'> │ │
│ ╰──────────────────────────────────────────────────────────────────╯ │
╰─────────────────────────────────────────────────────────────────────────────────────────────╯
TypeError: text must be a string: actual=<class 'int'>
That's right. Just pushed a fix to master.
That fixed it thanks!
One question though, doesn't the album implementation just list the number of volumes in the album? Not the volume number that the particular track is a part of? So if I want to download an entire album into
"{album_artist}/{album_title} [{album_year}]/{album_num_volumes}/{album_track_num} - {artist_name} - {track_title}"
all the files go into
The\ Beatles/Abbey\ Road\ \(Super\ Deluxe\ Edition\)\ \[1969\]/3/.
because the album has 3 volumes total
I would expect each song to belong to it's own volume, and get sent to each of these directories, even when downloading a whole album and not a single track:
The\ Beatles/Abbey\ Road\ \(Super\ Deluxe\ Edition\)\ \[1969\]/1/.
The\ Beatles/Abbey\ Road\ \(Super\ Deluxe\ Edition\)\ \[1969\]/2/.
The\ Beatles/Abbey\ Road\ \(Super\ Deluxe\ Edition\)\ \[1969\]/3/.
I do think the track functionality works as I'd expect, and for my purposes I just added a | Album
to line 149 of paths.py and use track_volume_num for everything.
Thanks for your help here!
The\ Beatles/Abbey\ Road\ \(Super\ Deluxe\ Edition\)\ \[1969\]/1/.
The\ Beatles/Abbey\ Road\ \(Super\ Deluxe\ Edition\)\ \[1969\]/2/.
The\ Beatles/Abbey\ Road\ \(Super\ Deluxe\ Edition\)\ \[1969\]/3/.
If you like to use it this way, you need to use track_volume_num
.
Current Situation
85
Currently if you download an album with the tracklist separated into "Volumes", you get duplicate tracks numbers.
Current behavior:
Settings:
Suggestion / Feature Request
There should be a variable in the path format config like {volume_num} that uses track.volume_num (I think) from tidal. I believe tidal-dl somehow figures this out automatically, because the CD1/CD2 directories appear automatically when needed and don't exist otherwise. But a {volume_num} variable would be all that's needed.
Resulting files should be structured like shown, with :
Example Settings: