mirror of
https://github.com/LukeHagar/ytdl-sub.git
synced 2025-12-06 04:22:12 +00:00
[BUGFIX] File name too long with -thumb.jpg, upgrade docker alpine image (#560)
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
FROM ghcr.io/linuxserver/baseimage-alpine:3.17
|
FROM ghcr.io/linuxserver/baseimage-alpine:edge
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# YTDL-SUB INSTALL
|
# YTDL-SUB INSTALL
|
||||||
@@ -12,7 +12,7 @@ RUN mkdir -p /config && \
|
|||||||
g++ \
|
g++ \
|
||||||
nano \
|
nano \
|
||||||
make \
|
make \
|
||||||
python3=~3.10 \
|
"python3>=3.10" \
|
||||||
py3-pip \
|
py3-pip \
|
||||||
fontconfig \
|
fontconfig \
|
||||||
py3-setuptools && \
|
py3-setuptools && \
|
||||||
@@ -30,13 +30,14 @@ RUN mkdir -p /config && \
|
|||||||
cd -; \
|
cd -; \
|
||||||
fi && \
|
fi && \
|
||||||
# Install ytdl-sub, ensure it is installed properly
|
# Install ytdl-sub, ensure it is installed properly
|
||||||
pip install --no-cache-dir ytdl_sub-*.whl && \
|
python3 -m pip install --no-cache-dir ytdl_sub-*.whl && \
|
||||||
ytdl-sub -h && \
|
ytdl-sub -h && \
|
||||||
# Delete unneeded packages after install
|
# Delete unneeded packages after install
|
||||||
rm ytdl_sub-*.whl && \
|
rm ytdl_sub-*.whl && \
|
||||||
apk del \
|
apk del \
|
||||||
g++ \
|
g++ \
|
||||||
make \
|
make \
|
||||||
|
py3-pip \
|
||||||
py3-setuptools
|
py3-setuptools
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ classifiers =
|
|||||||
License :: Public Domain
|
License :: Public Domain
|
||||||
Environment :: Console
|
Environment :: Console
|
||||||
Programming Language :: Python :: 3.10
|
Programming Language :: Python :: 3.10
|
||||||
|
Programming Language :: Python :: 3.11
|
||||||
|
|
||||||
[options.entry_points]
|
[options.entry_points]
|
||||||
console_scripts =
|
console_scripts =
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
__pypi_version__ = "2023.03.15"
|
__pypi_version__ = "2023.03.24.post7"
|
||||||
__local_version__ = "2023.03.15+e69933d"
|
__local_version__ = "2023.03.24+14e4a4b"
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ if IS_WINDOWS:
|
|||||||
else:
|
else:
|
||||||
_MAX_FILE_NAME_BYTES = os.pathconf("/", "PC_NAME_MAX")
|
_MAX_FILE_NAME_BYTES = os.pathconf("/", "PC_NAME_MAX")
|
||||||
|
|
||||||
|
# Save file-name bytes for the -thumb.jpg portion
|
||||||
|
_MAX_BASE_FILE_NAME_BYTES = _MAX_FILE_NAME_BYTES - len("-thumb.jpg".encode("utf-8")) - 8
|
||||||
|
|
||||||
|
|
||||||
class FFmpegFileValidator(StringValidator):
|
class FFmpegFileValidator(StringValidator):
|
||||||
_expected_value_type_name = "ffmpeg dependency"
|
_expected_value_type_name = "ffmpeg dependency"
|
||||||
@@ -90,17 +93,24 @@ class StringFormatterFileNameValidator(StringFormatterValidator, FilePathValidat
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _get_extension_split(cls, file_name: str) -> Tuple[str, str]:
|
def _get_extension_split(cls, file_name: str) -> Tuple[str, str]:
|
||||||
|
"""
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
file_name, ext (including .)
|
||||||
|
"""
|
||||||
if file_name.endswith(".info.json"):
|
if file_name.endswith(".info.json"):
|
||||||
ext = "info.json"
|
ext = ".info.json"
|
||||||
|
elif file_name.endswith("-thumb.jpg"):
|
||||||
|
ext = "-thumb.jpg"
|
||||||
elif any(file_name.endswith(f".{subtitle_ext}") for subtitle_ext in SUBTITLE_EXTENSIONS):
|
elif any(file_name.endswith(f".{subtitle_ext}") for subtitle_ext in SUBTITLE_EXTENSIONS):
|
||||||
file_name_split = file_name.split(".")
|
file_name_split = file_name.split(".")
|
||||||
ext = file_name_split[-1]
|
ext = file_name_split[-1]
|
||||||
|
|
||||||
# Try to capture .lang.ext
|
# Try to capture .lang.ext
|
||||||
if len(file_name_split) > 2 and len(file_name_split[-2]) < 6:
|
if len(file_name_split) > 2 and len(file_name_split[-2]) < 6:
|
||||||
ext = f"{file_name_split[-2]}.{file_name_split[-1]}"
|
ext = f".{file_name_split[-2]}.{file_name_split[-1]}"
|
||||||
else:
|
else:
|
||||||
ext = file_name.rsplit(".", maxsplit=1)[-1]
|
ext = f".{file_name.rsplit('.', maxsplit=1)[-1]}"
|
||||||
|
|
||||||
return file_name[: -len(ext)], ext
|
return file_name[: -len(ext)], ext
|
||||||
|
|
||||||
@@ -108,11 +118,10 @@ class StringFormatterFileNameValidator(StringFormatterValidator, FilePathValidat
|
|||||||
def _truncate_file_name(cls, file_name: str) -> str:
|
def _truncate_file_name(cls, file_name: str) -> str:
|
||||||
file_sub_name, file_ext = cls._get_extension_split(file_name)
|
file_sub_name, file_ext = cls._get_extension_split(file_name)
|
||||||
|
|
||||||
desired_size = _MAX_FILE_NAME_BYTES - len(file_ext.encode("utf-8")) - 1
|
while len(file_sub_name.encode("utf-8")) > _MAX_BASE_FILE_NAME_BYTES:
|
||||||
while len(file_sub_name.encode("utf-8")) > desired_size:
|
|
||||||
file_sub_name = file_sub_name[:-1]
|
file_sub_name = file_sub_name[:-1]
|
||||||
|
|
||||||
return f"{file_sub_name}.{file_ext}"
|
return f"{file_sub_name}{file_ext}"
|
||||||
|
|
||||||
def apply_formatter(self, variable_dict: Dict[str, str]) -> str:
|
def apply_formatter(self, variable_dict: Dict[str, str]) -> str:
|
||||||
"""Turn into a Path, then a string, to get correct directory separators"""
|
"""Turn into a Path, then a string, to get correct directory separators"""
|
||||||
|
|||||||
@@ -10,18 +10,16 @@ from ytdl_sub.validators.file_path_validators import StringFormatterFileNameVali
|
|||||||
class TestStringFormatterFilePathValidator:
|
class TestStringFormatterFilePathValidator:
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"ext",
|
"ext",
|
||||||
[
|
["mp4", "info.json", "-thumb.jpg"] + [f"en-US.{ext}" for ext in SUBTITLE_EXTENSIONS],
|
||||||
"mp4",
|
|
||||||
"info.json",
|
|
||||||
]
|
|
||||||
+ [f"en-US.{ext}" for ext in SUBTITLE_EXTENSIONS],
|
|
||||||
)
|
)
|
||||||
@pytest.mark.parametrize("file_name_char", ["a", "𒃀"])
|
@pytest.mark.parametrize("file_name_char", ["a", "𒃀"])
|
||||||
@pytest.mark.parametrize("file_name_len", [10, 10000])
|
@pytest.mark.parametrize("file_name_len", [10, 10000])
|
||||||
def test_truncates_file_name_successfully(
|
def test_truncates_file_name_successfully(
|
||||||
self, ext: str, file_name_char: str, file_name_len: int
|
self, ext: str, file_name_char: str, file_name_len: int
|
||||||
):
|
):
|
||||||
ext = f".{ext}" # pytest args with . in the beginning act weird
|
if "thumb" not in ext: # do not put . in front of -thumb
|
||||||
|
ext = f".{ext}" # pytest args with . in the beginning act weird
|
||||||
|
|
||||||
with tempfile.TemporaryDirectory() as temp_dir:
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
file_name = (file_name_char * file_name_len) + ext
|
file_name = (file_name_char * file_name_len) + ext
|
||||||
file_path = str(Path(temp_dir) / file_name)
|
file_path = str(Path(temp_dir) / file_name)
|
||||||
@@ -40,3 +38,32 @@ class TestStringFormatterFilePathValidator:
|
|||||||
|
|
||||||
assert len(dir_paths) == 1
|
assert len(dir_paths) == 1
|
||||||
assert Path(truncated_file_path) == dir_paths[0]
|
assert Path(truncated_file_path) == dir_paths[0]
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"ext",
|
||||||
|
["mp4", "info.json", "-thumb.jpg"] + [f"en-US.{ext}" for ext in SUBTITLE_EXTENSIONS],
|
||||||
|
)
|
||||||
|
def test_truncates_file_names_successfully(self, ext: str):
|
||||||
|
if "thumb" not in ext: # do not put . in front of -thumb
|
||||||
|
ext = f".{ext}" # pytest args with . in the beginning act weird
|
||||||
|
|
||||||
|
base_file_name = "s2023.e031701 - 𝗪𝗔𝗥𝗡𝗜𝗡𝗚: LG Secretly Overhaul This OLED Feature on C3 & G3… Should You Buy C2 Instead?"
|
||||||
|
|
||||||
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
|
file_path = str(Path(temp_dir) / f"{base_file_name}{ext}")
|
||||||
|
|
||||||
|
formatter = StringFormatterFileNameValidator(name="test", value=str(file_path))
|
||||||
|
truncated_file_path = formatter.apply_formatter({})
|
||||||
|
|
||||||
|
assert truncated_file_path == str(
|
||||||
|
Path(temp_dir)
|
||||||
|
/ f"s2023.e031701 - 𝗪𝗔𝗥𝗡𝗜𝗡𝗚: LG Secretly Overhaul This OLED Feature on C3 & G3… Should You Buy C2 Instead?{ext}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Ensure it can actually open the file
|
||||||
|
with open(truncated_file_path, "w", encoding="utf-8"):
|
||||||
|
# Make sure the file is actually in the directory
|
||||||
|
dir_paths = list(Path(temp_dir).rglob("*"))
|
||||||
|
|
||||||
|
assert len(dir_paths) == 1
|
||||||
|
assert Path(truncated_file_path) == dir_paths[0]
|
||||||
|
|||||||
Reference in New Issue
Block a user