diff --git a/docs/source/config_reference/scripting/scripting_functions.rst b/docs/source/config_reference/scripting/scripting_functions.rst index e2a200ef..9c5a43ea 100644 --- a/docs/source/config_reference/scripting/scripting_functions.rst +++ b/docs/source/config_reference/scripting/scripting_functions.rst @@ -837,7 +837,7 @@ behavior. sanitize ~~~~~~~~ -:spec: ``sanitize(value: AnyArgument) -> String`` +:spec: ``sanitize(value: AnyArgument, ...) -> String`` Sanitize a string using yt-dlp's ``sanitize_filename`` method to ensure it's safe to use for file/directory names on any OS. diff --git a/pyproject.toml b/pyproject.toml index c59b7b16..f211856f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,7 @@ classifiers = [ "Programming Language :: Python :: 3.11", ] dependencies = [ - "yt-dlp[default]==2026.3.3", + "yt-dlp[default]==2026.3.13", "colorama~=0.4", "mergedeep~=1.3", "mediafile~=0.12", @@ -48,7 +48,7 @@ test = [ ] lint = [ "pylint==4.0.5", - "ruff==0.15.5", + "ruff==0.15.6", ] docs = [ "sphinx>=7,<10", diff --git a/src/ytdl_sub/entries/script/custom_functions.py b/src/ytdl_sub/entries/script/custom_functions.py index 0bfc90ec..dfefb547 100644 --- a/src/ytdl_sub/entries/script/custom_functions.py +++ b/src/ytdl_sub/entries/script/custom_functions.py @@ -46,12 +46,12 @@ class CustomFunctions: return String(FilePathTruncater.maybe_truncate_file_path(filepath.value)) @staticmethod - def sanitize(value: AnyArgument) -> String: + def sanitize(*value: AnyArgument) -> String: """ Sanitize a string using yt-dlp's ``sanitize_filename`` method to ensure it's safe to use for file/directory names on any OS. """ - return String(sanitize_filename(str(value))) + return String("".join(sanitize_filename(str(val)) for val in value)) @staticmethod def sanitize_plex_episode(string: String) -> String: diff --git a/src/ytdl_sub/entries/script/variable_definitions.py b/src/ytdl_sub/entries/script/variable_definitions.py index a436060d..cb6ad612 100644 --- a/src/ytdl_sub/entries/script/variable_definitions.py +++ b/src/ytdl_sub/entries/script/variable_definitions.py @@ -1,6 +1,6 @@ from abc import ABC from functools import cache, cached_property -from typing import Dict, Set +from typing import Dict, Optional, Set from ytdl_sub.entries.script.custom_functions import CustomFunctions from ytdl_sub.entries.script.variable_types import ( @@ -1215,6 +1215,14 @@ class VariableDefinitions( VARIABLES.entry_metadata, } | self.injected_variables() + def get(self, name: str) -> Optional[Variable]: + """ + Returns the variable attribute if it exists. None otherwise. + """ + if not hasattr(self, name): + return None + return getattr(self, name) + # Singletons to use externally VARIABLES: VariableDefinitions = VariableDefinitions() diff --git a/src/ytdl_sub/utils/script.py b/src/ytdl_sub/utils/script.py index 5c9e7707..0e228327 100644 --- a/src/ytdl_sub/utils/script.py +++ b/src/ytdl_sub/utils/script.py @@ -2,6 +2,9 @@ import json import re from typing import Any, Dict, Optional +from ytdl_sub.entries.script.custom_functions import CustomFunctions +from ytdl_sub.entries.script.variable_definitions import VARIABLES +from ytdl_sub.entries.script.variable_types import BooleanVariable, IntegerVariable from ytdl_sub.script.parser import parse from ytdl_sub.script.types.array import Array, UnresolvedArray from ytdl_sub.script.types.function import BuiltInFunction, Function @@ -13,6 +16,7 @@ from ytdl_sub.script.utils.exceptions import UNREACHABLE from ytdl_sub.script.utils.name_validation import is_function # pylint: disable=too-many-return-statements +# pylint: disable=too-many-branches class ScriptUtils: @@ -110,6 +114,62 @@ class ScriptUtils: return '"' return "'''" + @classmethod + def _maybe_to_optimized_sanitize(cls, arg: Argument) -> Argument: + # If it is %sanitize(%concat(...)), return %sanitize(...) + if ( + isinstance(arg, Function) + and arg.name == "sanitize" + and len(arg.args) == 1 + and isinstance(arg.args[0], Function) + and arg.args[0].name == "concat" + ): + return BuiltInFunction(name="sanitize", args=arg.args[0].args) + + return arg + + @classmethod + def _maybe_sanitized_script_code(cls, arg: Argument) -> Optional[str]: + if not (isinstance(arg, Function) and arg.name == "sanitize"): + return None + + output = "" + for sub_arg in arg.args: + if isinstance(sub_arg, Variable): + # No need to sanitize built-in integer variables + if isinstance(VARIABLES.get(sub_arg.name), (IntegerVariable, BooleanVariable)): + output += f"{{ {sub_arg.name} }}" + else: + output += f"{{ {sub_arg.name}_sanitized }}" + elif isinstance(sub_arg, (Integer, Float, Boolean)): + output += str(sub_arg.native) + elif isinstance(sub_arg, String): + output += CustomFunctions.sanitize(sub_arg).native + elif isinstance(sub_arg, BuiltInFunction) and ( + issubclass(sub_arg.function_spec.return_type, (Integer, Float, Boolean)) + or sub_arg.name == "pad_zero" + ): + # If we know the function's output is sanitized, let's not wrap it + output += cls._to_script_code(sub_arg, top_level=True) + else: + # Purposefully do not set top_level to True so we do not recurse + output += ( + f"{{ {cls._to_script_code(BuiltInFunction(name='sanitize', args=[sub_arg]))} }}" + ) + + return output + + @classmethod + def _maybe_concat_script_code(cls, arg: Argument) -> Optional[str]: + if not (isinstance(arg, Function) and arg.name == "concat"): + return None + + out = "" + for sub_arg in arg.args: + out += cls._to_script_code(sub_arg, top_level=True) + + return out + @classmethod def _to_script_code(cls, arg: Argument, top_level: bool = False) -> str: if not top_level and isinstance(arg, (Integer, Boolean, Float)): @@ -122,6 +182,14 @@ class ScriptUtils: quote = cls._get_quote_char(arg.native) return arg.native if top_level else f"{quote}{arg.native}{quote}" + arg = cls._maybe_to_optimized_sanitize(arg) + + if top_level: + if (out := cls._maybe_sanitized_script_code(arg)) is not None: + return out + if (out := cls._maybe_concat_script_code(arg)) is not None: + return out + if isinstance(arg, Integer): out = f"%int({arg.native})" elif isinstance(arg, Boolean): diff --git a/tests/resources/expected_json/music/inspect_sub_fill.json b/tests/resources/expected_json/music/inspect_sub_fill.json index c37eaccf..7202fbef 100644 --- a/tests/resources/expected_json/music/inspect_sub_fill.json +++ b/tests/resources/expected_json/music/inspect_sub_fill.json @@ -79,13 +79,13 @@ "file_name": "{ track_full_path }", "keep_files_date_eval": "{ upload_date_standardized }", "maintain_download_archive": true, - "output_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmp_rq6j0ir", + "output_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmpv_h5mst_", "preserve_mtime": false, "thumbnail_name": "{ album_cover_path }" }, "overrides": { - "album_cover_path": "Lester Young/{ %concat( \"[\", playlist_max_upload_year, \"] \", %sanitize( playlist_title ) ) }/folder.{ thumbnail_ext }", - "album_dir": "[{ playlist_max_upload_year }] { %sanitize( playlist_title ) }", + "album_cover_path": "Lester Young/[{ playlist_max_upload_year }] { playlist_title_sanitized }/folder.{ thumbnail_ext }", + "album_dir": "[{ playlist_max_upload_year }] { playlist_title_sanitized }", "artist_dir": "Lester Young", "avatar_uncropped_thumbnail_file_name": "", "banner_uncropped_thumbnail_file_name": "", @@ -93,7 +93,7 @@ "enable_throttle_protection": true, "include_sibling_metadata": true, "modified_webpage_url": "{ webpage_url }", - "music_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmp_rq6j0ir", + "music_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmpv_h5mst_", "resolution_assert": "{ %if( %and( enable_resolution_assert, %ne( height, 0 ), %not( resolution_assert_is_ignored ) ), %assert( %gte( height, resolution_assert_height_gte ), %concat( \"Entry \", title, \" downloaded at a low resolution (\", resolution_readable, \"), you've probably been throttled. \", \"Stopping further downloads, wait a few hours and try again. \", \"Disable using the override variable `enable_resolution_assert: False`.\" ) ), \"false is no-op\" ) }", "resolution_assert_height_gte": 361, "resolution_assert_ignore_titles": "{ [ ] }", @@ -110,8 +110,8 @@ "track_album_artist": "Lester Young", "track_artist": "Lester Young", "track_date": "{ upload_date_standardized }", - "track_file_name": "{ playlist_index_padded } - { %sanitize( title ) }.{ ext }", - "track_full_path": "Lester Young/{ %concat( \"[\", playlist_max_upload_year, \"] \", %sanitize( playlist_title ) ) }/{ %concat( playlist_index_padded, \" - \", %sanitize( title ), \".\", ext ) }", + "track_file_name": "{ playlist_index_padded } - { title_sanitized }.{ ext }", + "track_full_path": "Lester Young/[{ playlist_max_upload_year }] { playlist_title_sanitized }/{ playlist_index_padded } - { title_sanitized }.{ ext }", "track_genre": "Jazz", "track_genre_default": "Unset", "track_number": "{ playlist_index }", diff --git a/tests/resources/expected_json/music/inspect_sub_internal.json b/tests/resources/expected_json/music/inspect_sub_internal.json index ad65fc0b..7c317568 100644 --- a/tests/resources/expected_json/music/inspect_sub_internal.json +++ b/tests/resources/expected_json/music/inspect_sub_internal.json @@ -76,15 +76,15 @@ }, "output_options": { "download_archive_name": ".ytdl-sub-Lester Young-download-archive.json", - "file_name": "Lester Young/{ %concat( \"[\", %int( %map_get( %to_date_metadata( %array_reduce( %if_passthrough( %extract_field_from_siblings( \"upload_date\" ), [ upload_date ] ), %max ) ), \"year\" ) ), \"] \", %sanitize( %map_get_non_empty( entry_metadata, \"playlist_title\", %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ) ) }/{ %concat( %pad_zero( %map_get_non_empty( entry_metadata, \"playlist_index\", 1 ), 2 ), \" - \", %sanitize( %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ), \".\", ext ) }", + "file_name": "Lester Young/[{ %int( %map_get( %to_date_metadata( %array_reduce( %if_passthrough( %extract_field_from_siblings( \"upload_date\" ), [ upload_date ] ), %max ) ), \"year\" ) ) }] { %sanitize( %map_get_non_empty( entry_metadata, \"playlist_title\", %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ) }/{ %pad_zero( %map_get_non_empty( entry_metadata, \"playlist_index\", 1 ), 2 ) } - { %sanitize( %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) }.{ ext }", "keep_files_date_eval": "{ %string( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"date_standardized\" ) ) }", "maintain_download_archive": true, - "output_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmpiqt5f8bw", + "output_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmp7z9ceu_d", "preserve_mtime": false, - "thumbnail_name": "Lester Young/{ %concat( \"[\", %int( %map_get( %to_date_metadata( %array_reduce( %if_passthrough( %extract_field_from_siblings( \"upload_date\" ), [ upload_date ] ), %max ) ), \"year\" ) ), \"] \", %sanitize( %map_get_non_empty( entry_metadata, \"playlist_title\", %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ) ) }/folder.jpg" + "thumbnail_name": "Lester Young/[{ %int( %map_get( %to_date_metadata( %array_reduce( %if_passthrough( %extract_field_from_siblings( \"upload_date\" ), [ upload_date ] ), %max ) ), \"year\" ) ) }] { %sanitize( %map_get_non_empty( entry_metadata, \"playlist_title\", %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ) }/folder.jpg" }, "overrides": { - "album_cover_path": "Lester Young/{ %concat( \"[\", %int( %map_get( %to_date_metadata( %array_reduce( %if_passthrough( %extract_field_from_siblings( \"upload_date\" ), [ upload_date ] ), %max ) ), \"year\" ) ), \"] \", %sanitize( %map_get_non_empty( entry_metadata, \"playlist_title\", %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ) ) }/folder.jpg", + "album_cover_path": "Lester Young/[{ %int( %map_get( %to_date_metadata( %array_reduce( %if_passthrough( %extract_field_from_siblings( \"upload_date\" ), [ upload_date ] ), %max ) ), \"year\" ) ) }] { %sanitize( %map_get_non_empty( entry_metadata, \"playlist_title\", %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ) }/folder.jpg", "album_dir": "[{ %int( %map_get( %to_date_metadata( %array_reduce( %if_passthrough( %extract_field_from_siblings( \"upload_date\" ), [ upload_date ] ), %max ) ), \"year\" ) ) }] { %sanitize( %map_get_non_empty( entry_metadata, \"playlist_title\", %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ) }", "artist_dir": "Lester Young", "avatar_uncropped_thumbnail_file_name": "", @@ -93,7 +93,7 @@ "enable_throttle_protection": true, "include_sibling_metadata": true, "modified_webpage_url": "{ %map_get( entry_metadata, \"webpage_url\" ) }", - "music_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmpiqt5f8bw", + "music_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmp7z9ceu_d", "resolution_assert": "{ %if( %and( enable_resolution_assert, %ne( height, 0 ), %not( resolution_assert_is_ignored ) ), %assert( %gte( height, resolution_assert_height_gte ), %concat( \"Entry \", title, \" downloaded at a low resolution (\", resolution_readable, \"), you've probably been throttled. \", \"Stopping further downloads, wait a few hours and try again. \", \"Disable using the override variable `enable_resolution_assert: False`.\" ) ), \"false is no-op\" ) }", "resolution_assert_height_gte": 361, "resolution_assert_ignore_titles": "{ [ ] }", @@ -111,7 +111,7 @@ "track_artist": "Lester Young", "track_date": "{ %string( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"date_standardized\" ) ) }", "track_file_name": "{ %pad_zero( %map_get_non_empty( entry_metadata, \"playlist_index\", 1 ), 2 ) } - { %sanitize( %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) }.{ ext }", - "track_full_path": "Lester Young/{ %concat( \"[\", %int( %map_get( %to_date_metadata( %array_reduce( %if_passthrough( %extract_field_from_siblings( \"upload_date\" ), [ upload_date ] ), %max ) ), \"year\" ) ), \"] \", %sanitize( %map_get_non_empty( entry_metadata, \"playlist_title\", %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ) ) }/{ %concat( %pad_zero( %map_get_non_empty( entry_metadata, \"playlist_index\", 1 ), 2 ), \" - \", %sanitize( %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ), \".\", ext ) }", + "track_full_path": "Lester Young/[{ %int( %map_get( %to_date_metadata( %array_reduce( %if_passthrough( %extract_field_from_siblings( \"upload_date\" ), [ upload_date ] ), %max ) ), \"year\" ) ) }] { %sanitize( %map_get_non_empty( entry_metadata, \"playlist_title\", %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ) }/{ %pad_zero( %map_get_non_empty( entry_metadata, \"playlist_index\", 1 ), 2 ) } - { %sanitize( %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) }.{ ext }", "track_genre": "Jazz", "track_genre_default": "Unset", "track_number": "{ %map_get_non_empty( entry_metadata, \"playlist_index\", 1 ) }", diff --git a/tests/resources/expected_json/music/inspect_sub_original.json b/tests/resources/expected_json/music/inspect_sub_original.json index 5f5eaada..7697624f 100644 --- a/tests/resources/expected_json/music/inspect_sub_original.json +++ b/tests/resources/expected_json/music/inspect_sub_original.json @@ -71,7 +71,7 @@ "enable_throttle_protection": true, "include_sibling_metadata": true, "modified_webpage_url": "{webpage_url}", - "music_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmp8f35xgea", + "music_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmpgcphf_8p", "resolution_assert": "{\n %if(\n %and(\n enable_resolution_assert,\n %ne( height, 0 ),\n %not(resolution_assert_is_ignored)\n ),\n %assert(\n %gte( height, resolution_assert_height_gte ),\n %concat(\n \"Entry \",\n title,\n \" downloaded at a low resolution (\",\n resolution_readable,\n \"), you've probably been throttled. \",\n \"Stopping further downloads, wait a few hours and try again. \",\n \"Disable using the override variable `enable_resolution_assert: False`.\"\n )\n ),\n \"false is no-op\"\n )\n}", "resolution_assert_height_gte": 361, "resolution_assert_ignore_titles": "{ [] }", diff --git a/tests/resources/expected_json/music/inspect_sub_resolve.json b/tests/resources/expected_json/music/inspect_sub_resolve.json index 2062208b..88b5c88c 100644 --- a/tests/resources/expected_json/music/inspect_sub_resolve.json +++ b/tests/resources/expected_json/music/inspect_sub_resolve.json @@ -76,16 +76,16 @@ }, "output_options": { "download_archive_name": ".ytdl-sub-Lester Young-download-archive.json", - "file_name": "Lester Young/{ %concat( \"[\", playlist_max_upload_year, \"] \", %sanitize( playlist_title ) ) }/{ %concat( playlist_index_padded, \" - \", %sanitize( title ), \".\", ext ) }", + "file_name": "Lester Young/[{ playlist_max_upload_year }] { playlist_title_sanitized }/{ playlist_index_padded } - { title_sanitized }.{ ext }", "keep_files_date_eval": "{ upload_date_standardized }", "maintain_download_archive": true, - "output_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmp_2ffo1ep", + "output_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmplsyhpyfi", "preserve_mtime": false, - "thumbnail_name": "Lester Young/{ %concat( \"[\", playlist_max_upload_year, \"] \", %sanitize( playlist_title ) ) }/folder.{ thumbnail_ext }" + "thumbnail_name": "Lester Young/[{ playlist_max_upload_year }] { playlist_title_sanitized }/folder.{ thumbnail_ext }" }, "overrides": { - "album_cover_path": "Lester Young/{ %concat( \"[\", playlist_max_upload_year, \"] \", %sanitize( playlist_title ) ) }/folder.{ thumbnail_ext }", - "album_dir": "[{ playlist_max_upload_year }] { %sanitize( playlist_title ) }", + "album_cover_path": "Lester Young/[{ playlist_max_upload_year }] { playlist_title_sanitized }/folder.{ thumbnail_ext }", + "album_dir": "[{ playlist_max_upload_year }] { playlist_title_sanitized }", "artist_dir": "Lester Young", "avatar_uncropped_thumbnail_file_name": "", "banner_uncropped_thumbnail_file_name": "", @@ -93,7 +93,7 @@ "enable_throttle_protection": true, "include_sibling_metadata": true, "modified_webpage_url": "{ webpage_url }", - "music_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmp_2ffo1ep", + "music_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmplsyhpyfi", "resolution_assert": "{ %if( %and( enable_resolution_assert, %ne( height, 0 ), %not( resolution_assert_is_ignored ) ), %assert( %gte( height, resolution_assert_height_gte ), %concat( \"Entry \", title, \" downloaded at a low resolution (\", resolution_readable, \"), you've probably been throttled. \", \"Stopping further downloads, wait a few hours and try again. \", \"Disable using the override variable `enable_resolution_assert: False`.\" ) ), \"false is no-op\" ) }", "resolution_assert_height_gte": 361, "resolution_assert_ignore_titles": "{ [ ] }", @@ -110,8 +110,8 @@ "track_album_artist": "Lester Young", "track_artist": "Lester Young", "track_date": "{ upload_date_standardized }", - "track_file_name": "{ playlist_index_padded } - { %sanitize( title ) }.{ ext }", - "track_full_path": "Lester Young/{ %concat( \"[\", playlist_max_upload_year, \"] \", %sanitize( playlist_title ) ) }/{ %concat( playlist_index_padded, \" - \", %sanitize( title ), \".\", ext ) }", + "track_file_name": "{ playlist_index_padded } - { title_sanitized }.{ ext }", + "track_full_path": "Lester Young/[{ playlist_max_upload_year }] { playlist_title_sanitized }/{ playlist_index_padded } - { title_sanitized }.{ ext }", "track_genre": "Jazz", "track_genre_default": "Unset", "track_number": "{ playlist_index }", diff --git a/tests/resources/expected_json/music_video/inspect_sub_fill.json b/tests/resources/expected_json/music_video/inspect_sub_fill.json index 113391a4..dd59c40d 100644 --- a/tests/resources/expected_json/music_video/inspect_sub_fill.json +++ b/tests/resources/expected_json/music_video/inspect_sub_fill.json @@ -38,7 +38,7 @@ "info_json_name": "{ music_video_file_name }.{ info_json_ext }", "keep_files_date_eval": "{ upload_date_standardized }", "maintain_download_archive": true, - "output_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmpoip4vg8b", + "output_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmp23dslv3t", "preserve_mtime": false, "thumbnail_name": "{ music_video_file_name }.jpg" }, @@ -66,7 +66,7 @@ "music_video_album_default": "Music Videos", "music_video_artist": "Rick Astley", "music_video_date": "{ %elif( %contains_url_field( \"date\" ), %get_url_field( \"date\", upload_date_standardized ), %contains_url_field( \"year\" ), %concat( %get_url_field( \"date\", upload_year ), \"-01-01\" ), upload_date_standardized ) }", - "music_video_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmpoip4vg8b", + "music_video_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmp23dslv3t", "music_video_file_name": "Rick Astley/{ %sanitize( %get_url_field( \"title\", title ) ) }", "music_video_file_name_suffix": "", "music_video_genre": "Pop", diff --git a/tests/resources/expected_json/music_video/inspect_sub_internal.json b/tests/resources/expected_json/music_video/inspect_sub_internal.json index e9da4794..925b8810 100644 --- a/tests/resources/expected_json/music_video/inspect_sub_internal.json +++ b/tests/resources/expected_json/music_video/inspect_sub_internal.json @@ -34,13 +34,13 @@ "format": "(bv*[ext=mp4][vcodec~='^((he|a)vc|h26[45])']+ba[ext=m4a]) / (bv[ext=mp4]*+ba[ext=m4a]/b)", "output_options": { "download_archive_name": ".ytdl-sub-Rick Astley-download-archive.json", - "file_name": "{ %concat( \"Rick Astley\", \"/\", %sanitize( %get_url_field( \"title\", %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ), '' ) }.{ %map_get( entry_metadata, \"ext\" ) }", - "info_json_name": "{ %concat( \"Rick Astley\", \"/\", %sanitize( %get_url_field( \"title\", %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ), '' ) }.info.json", + "file_name": "Rick Astley/{ %sanitize( %get_url_field( \"title\", %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ) }.{ %map_get( entry_metadata, \"ext\" ) }", + "info_json_name": "Rick Astley/{ %sanitize( %get_url_field( \"title\", %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ) }.info.json", "keep_files_date_eval": "{ %string( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"date_standardized\" ) ) }", "maintain_download_archive": true, - "output_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmpfqm9v_z7", + "output_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmpyoug1csk", "preserve_mtime": false, - "thumbnail_name": "{ %concat( \"Rick Astley\", \"/\", %sanitize( %get_url_field( \"title\", %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ), '' ) }.jpg" + "thumbnail_name": "Rick Astley/{ %sanitize( %get_url_field( \"title\", %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ) }.jpg" }, "overrides": { "%bilateral_url": "{ %if( %and( enable_bilateral_scraping, subscription_has_download_archive, %is_bilateral_url( $0 ) ), $0, '' ) }", @@ -66,7 +66,7 @@ "music_video_album_default": "Music Videos", "music_video_artist": "Rick Astley", "music_video_date": "{ %elif( %contains_url_field( \"date\" ), %get_url_field( \"date\", upload_date_standardized ), %contains_url_field( \"year\" ), %concat( %get_url_field( \"date\", upload_year ), \"-01-01\" ), upload_date_standardized ) }", - "music_video_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmpfqm9v_z7", + "music_video_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmpyoug1csk", "music_video_file_name": "Rick Astley/{ %sanitize( %get_url_field( \"title\", %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ) }", "music_video_file_name_suffix": "", "music_video_genre": "Pop", diff --git a/tests/resources/expected_json/music_video/inspect_sub_original.json b/tests/resources/expected_json/music_video/inspect_sub_original.json index da02085b..ebb28778 100644 --- a/tests/resources/expected_json/music_video/inspect_sub_original.json +++ b/tests/resources/expected_json/music_video/inspect_sub_original.json @@ -71,7 +71,7 @@ "music_video_album_default": "Music Videos", "music_video_artist": "{subscription_name}", "music_video_date": "{ \n %elif(\n %contains_url_field(\"date\"),\n %get_url_field(\"date\", upload_date_standardized),\n\n %contains_url_field(\"year\"),\n %concat( %get_url_field(\"date\", upload_year), \"-01-01\"),\n\n upload_date_standardized\n )\n}", - "music_video_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmpjq3ge5bi", + "music_video_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmpsl6aj5hf", "music_video_file_name": "{music_video_artist_sanitized}/{music_video_title_sanitized}{music_video_file_name_suffix}", "music_video_file_name_suffix": "", "music_video_genre": "{subscription_indent_1}", diff --git a/tests/resources/expected_json/music_video/inspect_sub_resolve.json b/tests/resources/expected_json/music_video/inspect_sub_resolve.json index 30cf1e15..0433b0de 100644 --- a/tests/resources/expected_json/music_video/inspect_sub_resolve.json +++ b/tests/resources/expected_json/music_video/inspect_sub_resolve.json @@ -34,13 +34,13 @@ "format": "(bv*[ext=mp4][vcodec~='^((he|a)vc|h26[45])']+ba[ext=m4a]) / (bv[ext=mp4]*+ba[ext=m4a]/b)", "output_options": { "download_archive_name": ".ytdl-sub-Rick Astley-download-archive.json", - "file_name": "{ %concat( \"Rick Astley\", \"/\", %sanitize( %get_url_field( \"title\", title ) ), '' ) }.{ ext }", - "info_json_name": "{ %concat( \"Rick Astley\", \"/\", %sanitize( %get_url_field( \"title\", title ) ), '' ) }.{ info_json_ext }", + "file_name": "Rick Astley/{ %sanitize( %get_url_field( \"title\", title ) ) }.{ ext }", + "info_json_name": "Rick Astley/{ %sanitize( %get_url_field( \"title\", title ) ) }.{ info_json_ext }", "keep_files_date_eval": "{ upload_date_standardized }", "maintain_download_archive": true, - "output_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmpvn6oqvre", + "output_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmprdmerciw", "preserve_mtime": false, - "thumbnail_name": "{ %concat( \"Rick Astley\", \"/\", %sanitize( %get_url_field( \"title\", title ) ), '' ) }.jpg" + "thumbnail_name": "Rick Astley/{ %sanitize( %get_url_field( \"title\", title ) ) }.jpg" }, "overrides": { "%bilateral_url": "{ %if( %and( enable_bilateral_scraping, subscription_has_download_archive, %is_bilateral_url( $0 ) ), $0, '' ) }", @@ -66,7 +66,7 @@ "music_video_album_default": "Music Videos", "music_video_artist": "Rick Astley", "music_video_date": "{ %elif( %contains_url_field( \"date\" ), %get_url_field( \"date\", upload_date_standardized ), %contains_url_field( \"year\" ), %concat( %get_url_field( \"date\", upload_year ), \"-01-01\" ), upload_date_standardized ) }", - "music_video_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmpvn6oqvre", + "music_video_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmprdmerciw", "music_video_file_name": "Rick Astley/{ %sanitize( %get_url_field( \"title\", title ) ) }", "music_video_file_name_suffix": "", "music_video_genre": "Pop", diff --git a/tests/resources/expected_json/tv_show/inspect_sub_fill.json b/tests/resources/expected_json/tv_show/inspect_sub_fill.json index bfa66d03..d839a6ee 100644 --- a/tests/resources/expected_json/tv_show/inspect_sub_fill.json +++ b/tests/resources/expected_json/tv_show/inspect_sub_fill.json @@ -54,7 +54,7 @@ "info_json_name": "{ episode_file_path }.{ info_json_ext }", "keep_files_date_eval": "{ episode_date_standardized }", "maintain_download_archive": true, - "output_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmp8seugdh8/NOVA PBS", + "output_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmp8p_iu2pp/NOVA PBS", "preserve_mtime": false, "thumbnail_name": "{ thumbnail_file_name }" }, @@ -73,7 +73,7 @@ "episode_content_rating": "TV-14", "episode_date_standardized": "{ upload_date_standardized }", "episode_file_name": "s{ upload_year }.e{ %pad_zero( %int( %concat( upload_month, upload_day_padded, upload_date_index_padded ) ), 6 ) } - { title_sanitized_plex }", - "episode_file_path": "{ %sanitize( %concat( \"Season \", upload_year ) ) }/{ %sanitize( %concat( \"s\", upload_year, \".e\", %pad_zero( %int( %concat( upload_month, upload_day_padded, upload_date_index_padded ) ), 6 ), \" - \", title_sanitized_plex ) ) }", + "episode_file_path": "Season { upload_year }/s{ upload_year }.e{ %pad_zero( %int( %concat( upload_month, upload_day_padded, upload_date_index_padded ) ), 6 ) } - { title_sanitized_plex_sanitized }", "episode_number": "{ upload_month }{ upload_day_padded }{ upload_date_index_padded }", "episode_number_and_padded_": "{ [ %concat( upload_month, upload_day_padded, upload_date_index_padded ), 6 ] }", "episode_number_padded": "{ %pad_zero( %int( %concat( upload_month, upload_day_padded, upload_date_index_padded ) ), 6 ) }", @@ -97,7 +97,7 @@ "season_directory_name": "Season { upload_year }", "season_number": "{ upload_year }", "season_number_padded": "{ upload_year }", - "season_poster_file_name": "{ %sanitize( %concat( \"Season \", upload_year ) ) }/Season{ upload_year }.jpg", + "season_poster_file_name": "Season { upload_year }/Season{ upload_year }.jpg", "subscription_array": [ "https://www.youtube.com/@novapbs" ], @@ -105,14 +105,14 @@ "subscription_indent_2": "TV-14", "subscription_value": "https://www.youtube.com/@novapbs", "subscription_value_1": "https://www.youtube.com/@novapbs", - "thumbnail_file_name": "{ %concat( %sanitize( %concat( \"Season \", upload_year ) ), \"/\", %sanitize( %concat( \"s\", upload_year, \".e\", %pad_zero( %int( %concat( upload_month, upload_day_padded, upload_date_index_padded ) ), 6 ), \" - \", title_sanitized_plex ) ) ) }-thumb.jpg", + "thumbnail_file_name": "Season { upload_year }/s{ upload_year }.e{ %pad_zero( %int( %concat( upload_month, upload_day_padded, upload_date_index_padded ) ), 6 ) } - { title_sanitized_plex_sanitized }-thumb.jpg", "tv_show_by_date_episode_ordering": "upload-month-day", "tv_show_by_date_ordering_pair_validation_": "{ [ %concat( upload_month, upload_day_padded, upload_date_index_padded ), 6 ] }", "tv_show_by_date_season_ordering": "upload-year", "tv_show_content_rating": "TV-14", "tv_show_content_rating_default": "TV-14", "tv_show_date_range_type": "upload_date", - "tv_show_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmp8seugdh8", + "tv_show_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmp8p_iu2pp", "tv_show_fanart_file_name": "fanart.jpg", "tv_show_genre": "Documentaries", "tv_show_genre_default": "ytdl-sub", diff --git a/tests/resources/expected_json/tv_show/inspect_sub_internal.json b/tests/resources/expected_json/tv_show/inspect_sub_internal.json index cd67eb15..d7ff96eb 100644 --- a/tests/resources/expected_json/tv_show/inspect_sub_internal.json +++ b/tests/resources/expected_json/tv_show/inspect_sub_internal.json @@ -50,13 +50,13 @@ "format": "(bv*[ext=mp4][vcodec~='^((he|a)vc|h26[45])']+ba[ext=m4a]) / (bv[ext=mp4]*+ba[ext=m4a]/b)", "output_options": { "download_archive_name": ".ytdl-sub-NOVA PBS-download-archive.json", - "file_name": "{ %concat( %sanitize( %concat( \"Season \", %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ) ) ), \"/\", %sanitize( %concat( \"s\", %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ), \".e\", %pad_zero( %int( %concat( %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"month\" ) ), %string( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"day_padded\" ) ), %pad_zero( upload_date_index, 2 ) ) ), 6 ), \" - \", %sanitize_plex_episode( %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ) ) ) }.{ ext }", - "info_json_name": "{ %concat( %sanitize( %concat( \"Season \", %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ) ) ), \"/\", %sanitize( %concat( \"s\", %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ), \".e\", %pad_zero( %int( %concat( %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"month\" ) ), %string( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"day_padded\" ) ), %pad_zero( upload_date_index, 2 ) ) ), 6 ), \" - \", %sanitize_plex_episode( %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ) ) ) }.info.json", + "file_name": "Season { %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ) }/s{ %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ) }.e{ %pad_zero( %int( %concat( %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"month\" ) ), %string( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"day_padded\" ) ), %pad_zero( upload_date_index, 2 ) ) ), 6 ) } - { %sanitize( %sanitize_plex_episode( %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ) }.{ ext }", + "info_json_name": "Season { %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ) }/s{ %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ) }.e{ %pad_zero( %int( %concat( %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"month\" ) ), %string( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"day_padded\" ) ), %pad_zero( upload_date_index, 2 ) ) ), 6 ) } - { %sanitize( %sanitize_plex_episode( %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ) }.info.json", "keep_files_date_eval": "{ %string( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"date_standardized\" ) ) }", "maintain_download_archive": true, - "output_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmp33ooazwa/NOVA PBS", + "output_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmpup1qibc_/NOVA PBS", "preserve_mtime": false, - "thumbnail_name": "{ %concat( %sanitize( %concat( \"Season \", %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ) ) ), \"/\", %sanitize( %concat( \"s\", %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ), \".e\", %pad_zero( %int( %concat( %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"month\" ) ), %string( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"day_padded\" ) ), %pad_zero( upload_date_index, 2 ) ) ), 6 ), \" - \", %sanitize_plex_episode( %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ) ) ) }-thumb.jpg" + "thumbnail_name": "Season { %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ) }/s{ %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ) }.e{ %pad_zero( %int( %concat( %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"month\" ) ), %string( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"day_padded\" ) ), %pad_zero( upload_date_index, 2 ) ) ), 6 ) } - { %sanitize( %sanitize_plex_episode( %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ) }-thumb.jpg" }, "overrides": { "%bilateral_url": "{ %if( %and( enable_bilateral_scraping, subscription_has_download_archive, %is_bilateral_url( $0 ) ), $0, '' ) }", @@ -73,7 +73,7 @@ "episode_content_rating": "TV-14", "episode_date_standardized": "{ %string( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"date_standardized\" ) ) }", "episode_file_name": "s{ %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ) }.e{ %pad_zero( %int( %concat( %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"month\" ) ), %string( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"day_padded\" ) ), %pad_zero( upload_date_index, 2 ) ) ), 6 ) } - { %sanitize_plex_episode( %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) }", - "episode_file_path": "{ %sanitize( %concat( \"Season \", %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ) ) ) }/{ %sanitize( %concat( \"s\", %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ), \".e\", %pad_zero( %int( %concat( %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"month\" ) ), %string( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"day_padded\" ) ), %pad_zero( upload_date_index, 2 ) ) ), 6 ), \" - \", %sanitize_plex_episode( %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ) ) }", + "episode_file_path": "Season { %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ) }/s{ %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ) }.e{ %pad_zero( %int( %concat( %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"month\" ) ), %string( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"day_padded\" ) ), %pad_zero( upload_date_index, 2 ) ) ), 6 ) } - { %sanitize( %sanitize_plex_episode( %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ) }", "episode_number": "{ %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"month\" ) ) }{ %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"day_padded\" ) }{ %pad_zero( upload_date_index, 2 ) }", "episode_number_and_padded_": "{ [ %concat( %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"month\" ) ), %string( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"day_padded\" ) ), %pad_zero( upload_date_index, 2 ) ), 6 ] }", "episode_number_padded": "{ %pad_zero( %int( %concat( %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"month\" ) ), %string( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"day_padded\" ) ), %pad_zero( upload_date_index, 2 ) ) ), 6 ) }", @@ -97,7 +97,7 @@ "season_directory_name": "Season { %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ) }", "season_number": "{ %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ) }", "season_number_padded": "{ %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ) }", - "season_poster_file_name": "{ %sanitize( %concat( \"Season \", %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ) ) ) }/Season{ %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ) }.jpg", + "season_poster_file_name": "Season { %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ) }/Season{ %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ) }.jpg", "subscription_array": [ "https://www.youtube.com/@novapbs" ], @@ -105,14 +105,14 @@ "subscription_indent_2": "TV-14", "subscription_value": "https://www.youtube.com/@novapbs", "subscription_value_1": "https://www.youtube.com/@novapbs", - "thumbnail_file_name": "{ %concat( %sanitize( %concat( \"Season \", %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ) ) ), \"/\", %sanitize( %concat( \"s\", %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ), \".e\", %pad_zero( %int( %concat( %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"month\" ) ), %string( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"day_padded\" ) ), %pad_zero( upload_date_index, 2 ) ) ), 6 ), \" - \", %sanitize_plex_episode( %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ) ) ) }-thumb.jpg", + "thumbnail_file_name": "Season { %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ) }/s{ %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"year\" ) ) }.e{ %pad_zero( %int( %concat( %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"month\" ) ), %string( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"day_padded\" ) ), %pad_zero( upload_date_index, 2 ) ) ), 6 ) } - { %sanitize( %sanitize_plex_episode( %map_get_non_empty( entry_metadata, \"title\", %map_get( entry_metadata, \"id\" ) ) ) ) }-thumb.jpg", "tv_show_by_date_episode_ordering": "upload-month-day", "tv_show_by_date_ordering_pair_validation_": "{ [ %concat( %int( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"month\" ) ), %string( %map_get( %to_date_metadata( %map_get_non_empty( entry_metadata, \"upload_date\", %datetime_strftime( %map_get( entry_metadata, \"epoch\" ), \"%Y%m%d\" ) ) ), \"day_padded\" ) ), %pad_zero( upload_date_index, 2 ) ), 6 ] }", "tv_show_by_date_season_ordering": "upload-year", "tv_show_content_rating": "TV-14", "tv_show_content_rating_default": "TV-14", "tv_show_date_range_type": "upload_date", - "tv_show_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmp33ooazwa", + "tv_show_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmpup1qibc_", "tv_show_fanart_file_name": "fanart.jpg", "tv_show_genre": "Documentaries", "tv_show_genre_default": "ytdl-sub", diff --git a/tests/resources/expected_json/tv_show/inspect_sub_original.json b/tests/resources/expected_json/tv_show/inspect_sub_original.json index f665cf58..6f507298 100644 --- a/tests/resources/expected_json/tv_show/inspect_sub_original.json +++ b/tests/resources/expected_json/tv_show/inspect_sub_original.json @@ -109,7 +109,7 @@ "tv_show_content_rating": "{subscription_indent_2}", "tv_show_content_rating_default": "TV-14", "tv_show_date_range_type": "{\n %if(\n %contains(tv_show_by_date_season_ordering, \"release\"),\n \"release_date\",\n \"upload_date\"\n )\n}", - "tv_show_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmpaj6z3dtk", + "tv_show_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmpq08uqzot", "tv_show_fanart_file_name": "fanart.jpg", "tv_show_genre": "{subscription_indent_1}", "tv_show_genre_default": "ytdl-sub", diff --git a/tests/resources/expected_json/tv_show/inspect_sub_resolve.json b/tests/resources/expected_json/tv_show/inspect_sub_resolve.json index a75ebe17..6eeeeec7 100644 --- a/tests/resources/expected_json/tv_show/inspect_sub_resolve.json +++ b/tests/resources/expected_json/tv_show/inspect_sub_resolve.json @@ -50,13 +50,13 @@ "format": "(bv*[ext=mp4][vcodec~='^((he|a)vc|h26[45])']+ba[ext=m4a]) / (bv[ext=mp4]*+ba[ext=m4a]/b)", "output_options": { "download_archive_name": ".ytdl-sub-NOVA PBS-download-archive.json", - "file_name": "{ %concat( %sanitize( %concat( \"Season \", upload_year ) ), \"/\", %sanitize( %concat( \"s\", upload_year, \".e\", %pad_zero( %int( %concat( upload_month, upload_day_padded, upload_date_index_padded ) ), 6 ), \" - \", title_sanitized_plex ) ) ) }.{ ext }", - "info_json_name": "{ %concat( %sanitize( %concat( \"Season \", upload_year ) ), \"/\", %sanitize( %concat( \"s\", upload_year, \".e\", %pad_zero( %int( %concat( upload_month, upload_day_padded, upload_date_index_padded ) ), 6 ), \" - \", title_sanitized_plex ) ) ) }.{ info_json_ext }", + "file_name": "Season { upload_year }/s{ upload_year }.e{ %pad_zero( %int( %concat( upload_month, upload_day_padded, upload_date_index_padded ) ), 6 ) } - { title_sanitized_plex_sanitized }.{ ext }", + "info_json_name": "Season { upload_year }/s{ upload_year }.e{ %pad_zero( %int( %concat( upload_month, upload_day_padded, upload_date_index_padded ) ), 6 ) } - { title_sanitized_plex_sanitized }.{ info_json_ext }", "keep_files_date_eval": "{ upload_date_standardized }", "maintain_download_archive": true, - "output_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmp0658rh14/NOVA PBS", + "output_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmp723nds68/NOVA PBS", "preserve_mtime": false, - "thumbnail_name": "{ %concat( %sanitize( %concat( \"Season \", upload_year ) ), \"/\", %sanitize( %concat( \"s\", upload_year, \".e\", %pad_zero( %int( %concat( upload_month, upload_day_padded, upload_date_index_padded ) ), 6 ), \" - \", title_sanitized_plex ) ) ) }-thumb.jpg" + "thumbnail_name": "Season { upload_year }/s{ upload_year }.e{ %pad_zero( %int( %concat( upload_month, upload_day_padded, upload_date_index_padded ) ), 6 ) } - { title_sanitized_plex_sanitized }-thumb.jpg" }, "overrides": { "%bilateral_url": "{ %if( %and( enable_bilateral_scraping, subscription_has_download_archive, %is_bilateral_url( $0 ) ), $0, '' ) }", @@ -73,7 +73,7 @@ "episode_content_rating": "TV-14", "episode_date_standardized": "{ upload_date_standardized }", "episode_file_name": "s{ upload_year }.e{ %pad_zero( %int( %concat( upload_month, upload_day_padded, upload_date_index_padded ) ), 6 ) } - { title_sanitized_plex }", - "episode_file_path": "{ %sanitize( %concat( \"Season \", upload_year ) ) }/{ %sanitize( %concat( \"s\", upload_year, \".e\", %pad_zero( %int( %concat( upload_month, upload_day_padded, upload_date_index_padded ) ), 6 ), \" - \", title_sanitized_plex ) ) }", + "episode_file_path": "Season { upload_year }/s{ upload_year }.e{ %pad_zero( %int( %concat( upload_month, upload_day_padded, upload_date_index_padded ) ), 6 ) } - { title_sanitized_plex_sanitized }", "episode_number": "{ upload_month }{ upload_day_padded }{ upload_date_index_padded }", "episode_number_and_padded_": "{ [ %concat( upload_month, upload_day_padded, upload_date_index_padded ), 6 ] }", "episode_number_padded": "{ %pad_zero( %int( %concat( upload_month, upload_day_padded, upload_date_index_padded ) ), 6 ) }", @@ -97,7 +97,7 @@ "season_directory_name": "Season { upload_year }", "season_number": "{ upload_year }", "season_number_padded": "{ upload_year }", - "season_poster_file_name": "{ %sanitize( %concat( \"Season \", upload_year ) ) }/Season{ upload_year }.jpg", + "season_poster_file_name": "Season { upload_year }/Season{ upload_year }.jpg", "subscription_array": [ "https://www.youtube.com/@novapbs" ], @@ -105,14 +105,14 @@ "subscription_indent_2": "TV-14", "subscription_value": "https://www.youtube.com/@novapbs", "subscription_value_1": "https://www.youtube.com/@novapbs", - "thumbnail_file_name": "{ %concat( %sanitize( %concat( \"Season \", upload_year ) ), \"/\", %sanitize( %concat( \"s\", upload_year, \".e\", %pad_zero( %int( %concat( upload_month, upload_day_padded, upload_date_index_padded ) ), 6 ), \" - \", title_sanitized_plex ) ) ) }-thumb.jpg", + "thumbnail_file_name": "Season { upload_year }/s{ upload_year }.e{ %pad_zero( %int( %concat( upload_month, upload_day_padded, upload_date_index_padded ) ), 6 ) } - { title_sanitized_plex_sanitized }-thumb.jpg", "tv_show_by_date_episode_ordering": "upload-month-day", "tv_show_by_date_ordering_pair_validation_": "{ [ %concat( upload_month, upload_day_padded, upload_date_index_padded ), 6 ] }", "tv_show_by_date_season_ordering": "upload-year", "tv_show_content_rating": "TV-14", "tv_show_content_rating_default": "TV-14", "tv_show_date_range_type": "upload_date", - "tv_show_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmp0658rh14", + "tv_show_directory": "/var/folders/rw/hl1xmkmj68zdl2kjx3l0dwzc0000gn/T/tmp723nds68", "tv_show_fanart_file_name": "fanart.jpg", "tv_show_genre": "Documentaries", "tv_show_genre_default": "ytdl-sub", diff --git a/tests/unit/validators/test_string_formatter_validator.py b/tests/unit/validators/test_string_formatter_validator.py index a1a05b85..44b2194f 100644 --- a/tests/unit/validators/test_string_formatter_validator.py +++ b/tests/unit/validators/test_string_formatter_validator.py @@ -113,12 +113,12 @@ class TestUnstructuredDictFormatterValidator(object): assert len(validator.dict) == 8 assert all(isinstance(val, expected_formatter_class) for val in validator.dict.values()) assert validator.dict_with_format_strings == { - "key1": '{ %concat( "string with ", variable ) }', + "key1": "string with { variable }", "key2": "no variables", "key3": "{ %int(3) }", "key4": "{ %float(4.132) }", "key5": "{ %bool(True) }", "key6": '{ { %concat( variable, "_key" ): "value", "static_key": %concat( variable, "_value" ) } }', "key7": '{ [ "list_1", %concat( "list_", variable_2 ) ] }', - "key8": '{ %concat( "string ", variable1, " with multiple ", variable2 ) }', + "key8": "string { variable1 } with multiple { variable2 }", }