🛠️ Directory length limit is checked and adapted correctly now. Fixes #447 & #436

This commit is contained in:
Robert Honz
2025-06-30 16:33:32 +02:00
parent 0eaeed533f
commit 70e29771b9
3 changed files with 35 additions and 8 deletions
+1
View File
@@ -12,6 +12,7 @@ CHUNK_SIZE: int = BLOCK_SIZE * BLOCKS
PLAYLIST_EXTENSION: str = ".m3u" PLAYLIST_EXTENSION: str = ".m3u"
PLAYLIST_PREFIX: str = "_" PLAYLIST_PREFIX: str = "_"
FILENAME_LENGTH_MAX: int = 255 FILENAME_LENGTH_MAX: int = 255
FORMAT_TEMPLATE_EXPLICIT: str = " (Explicit)"
class QualityVideo(StrEnum): class QualityVideo(StrEnum):
+7 -4
View File
@@ -12,6 +12,7 @@ from uuid import uuid4
import m3u8 import m3u8
import requests import requests
from ffmpeg import FFmpeg from ffmpeg import FFmpeg
from pathvalidate import sanitize_filename
from requests.adapters import HTTPAdapter, Retry from requests.adapters import HTTPAdapter, Retry
from requests.exceptions import HTTPError from requests.exceptions import HTTPError
from rich.progress import Progress, TaskID from rich.progress import Progress, TaskID
@@ -36,7 +37,6 @@ from tidal_dl_ng.helper.path import (
check_file_exists, check_file_exists,
format_path_media, format_path_media,
path_file_sanitize, path_file_sanitize,
sanitize_filename,
url_to_filename, url_to_filename,
) )
from tidal_dl_ng.helper.tidal import ( from tidal_dl_ng.helper.tidal import (
@@ -437,9 +437,12 @@ class Download:
elif isinstance(media, Video): elif isinstance(media, Video):
file_extension = AudioExtensions.MP4 if self.settings.data.video_convert_mp4 else VideoExtensions.TS file_extension = AudioExtensions.MP4 if self.settings.data.video_convert_mp4 else VideoExtensions.TS
# Compute file name, sanitize once again and create destination directory # If file extension was guessed wrong in the beginning
path_media_dst = path_media_dst.with_suffix(file_extension) if path_media_dst.suffix != file_extension:
path_media_dst = pathlib.Path(path_file_sanitize(path_media_dst, adapt=True)) # Compute file name, sanitize once again, because file extension could have been replaced after guessing it first and create destination directory
path_media_dst = path_media_dst.with_suffix(file_extension)
path_media_dst = pathlib.Path(path_file_sanitize(path_media_dst, adapt=True))
os.makedirs(path_media_dst.parent, exist_ok=True) os.makedirs(path_media_dst.parent, exist_ok=True)
if not skip_download: if not skip_download:
+27 -4
View File
@@ -13,7 +13,13 @@ from tidalapi import Album, Mix, Playlist, Track, UserPlaylist, Video
from tidalapi.media import AudioExtensions from tidalapi.media import AudioExtensions
from tidal_dl_ng import __name_display__ from tidal_dl_ng import __name_display__
from tidal_dl_ng.constants import FILENAME_LENGTH_MAX, FILENAME_SANITIZE_PLACEHOLDER, UNIQUIFY_THRESHOLD, MediaType from tidal_dl_ng.constants import (
FILENAME_LENGTH_MAX,
FILENAME_SANITIZE_PLACEHOLDER,
FORMAT_TEMPLATE_EXPLICIT,
UNIQUIFY_THRESHOLD,
MediaType,
)
from tidal_dl_ng.helper.tidal import name_builder_album_artist, name_builder_artist, name_builder_title from tidal_dl_ng.helper.tidal import name_builder_album_artist, name_builder_artist, name_builder_title
@@ -68,7 +74,11 @@ def format_path_media(
result_fmt = format_str_media(match.group(1), media, album_track_num_pad_min, list_pos, list_total) result_fmt = format_str_media(match.group(1), media, album_track_num_pad_min, list_pos, list_total)
if result_fmt != match.group(1): if result_fmt != match.group(1):
value = sanitize_filename(result_fmt) # Sanitize here, in case of the filename has slashes or something, which will be recognized later as a directory separator.
# Do not sanitize if value is the FORMAT_TEMPLATE_EXPLICIT placeholder, since it has a leading whitespace which otherwise gets removed.
value = (
sanitize_filename(result_fmt) if result_fmt != FORMAT_TEMPLATE_EXPLICIT else FORMAT_TEMPLATE_EXPLICIT
)
result = result.replace(template_str, value) result = result.replace(template_str, value)
return result return result
@@ -164,10 +174,10 @@ def format_str_media(
result = ", ".join(tag for tag in media.media_metadata_tags) result = ", ".join(tag for tag in media.media_metadata_tags)
case "track_explicit": case "track_explicit":
if isinstance(media, Track | Video): if isinstance(media, Track | Video):
result = " (Explicit)" if media.explicit else "" result = FORMAT_TEMPLATE_EXPLICIT if media.explicit else ""
case "album_explicit": case "album_explicit":
if isinstance(media, Album): if isinstance(media, Album):
result = " (Explicit)" if media.explicit else "" result = FORMAT_TEMPLATE_EXPLICIT if media.explicit else ""
case "album_num_volumes": case "album_num_volumes":
if isinstance(media, Album): if isinstance(media, Album):
result = str(media.num_volumes) result = str(media.num_volumes)
@@ -264,6 +274,19 @@ def path_file_sanitize(path_file: pathlib.Path, adapt: bool = False, uniquify: b
raise raise
# Sanitize the path. # Sanitize the path.
# First sanitize sanitize each part of the path. Each part of the path is not allowed to be longer then 'PC_NAME_MAX'.
sanitized_parts = []
for part in sanitized_path.parts:
if part in sanitized_path.root:
sanitized_parts.append(part)
else:
sanitized_parts.append(
sanitize_filename(part, replacement_text="_", validate_after_sanitize=True, platform="auto")
)
sanitized_path = pathlib.Path(*sanitized_parts)
# Then sanitize the whole path itself. The whole path is not allowed to be longer than 'PC_NAME_MAX'.
try: try:
sanitized_path: pathlib.Path = sanitize_filepath( sanitized_path: pathlib.Path = sanitize_filepath(
sanitized_path, replacement_text="_", validate_after_sanitize=True, platform="auto" sanitized_path, replacement_text="_", validate_after_sanitize=True, platform="auto"