ytdl-sub 2025.12.31.post4__tar.gz → 2026.1.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/PKG-INFO +1 -1
- ytdl_sub-2026.1.6/src/ytdl_sub/__init__.py +1 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/config/overrides.py +8 -3
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/config/validators/variable_validation.py +3 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/downloaders/url/downloader.py +20 -12
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/downloaders/url/validators.py +14 -1
- ytdl_sub-2026.1.6/src/ytdl_sub/prebuilt_presets/helpers/url.yaml +177 -0
- ytdl_sub-2026.1.6/src/ytdl_sub/prebuilt_presets/helpers/url_categorized.yaml +111 -0
- ytdl_sub-2026.1.6/src/ytdl_sub/prebuilt_presets/tv_show/tv_show_collection.yaml +1327 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/utils/script.py +17 -1
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/validators/string_formatter_validators.py +9 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub.egg-info/PKG-INFO +1 -1
- ytdl_sub-2025.12.31.post4/src/ytdl_sub/__init__.py +0 -1
- ytdl_sub-2025.12.31.post4/src/ytdl_sub/prebuilt_presets/helpers/url.yaml +0 -1049
- ytdl_sub-2025.12.31.post4/src/ytdl_sub/prebuilt_presets/helpers/url_categorized.yaml +0 -210
- ytdl_sub-2025.12.31.post4/src/ytdl_sub/prebuilt_presets/tv_show/tv_show_collection.yaml +0 -5693
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/LICENSE +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/README.md +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/pyproject.toml +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/setup.cfg +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/cli/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/cli/entrypoint.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/cli/output_summary.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/cli/output_transaction_log.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/cli/parsers/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/cli/parsers/cli_to_sub.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/cli/parsers/dl.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/cli/parsers/main.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/config/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/config/config_file.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/config/config_validator.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/config/defaults.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/config/plugin/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/config/plugin/plugin.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/config/plugin/plugin_mapping.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/config/plugin/plugin_operation.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/config/plugin/preset_plugins.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/config/preset.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/config/preset_options.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/config/validators/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/config/validators/options.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/downloaders/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/downloaders/info_json/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/downloaders/info_json/info_json_downloader.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/downloaders/source_plugin.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/downloaders/url/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/downloaders/ytdl_options_builder.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/downloaders/ytdlp.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/entries/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/entries/base_entry.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/entries/entry.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/entries/entry_parent.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/entries/script/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/entries/script/custom_functions.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/entries/script/function_scripts.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/entries/script/variable_definitions.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/entries/script/variable_types.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/entries/variables/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/entries/variables/override_variables.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/main.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/plugins/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/plugins/audio_extract.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/plugins/chapters.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/plugins/date_range.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/plugins/embed_thumbnail.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/plugins/file_convert.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/plugins/filter_exclude.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/plugins/filter_include.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/plugins/format.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/plugins/internal/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/plugins/internal/view.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/plugins/match_filters.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/plugins/music_tags.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/plugins/nfo_tags.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/plugins/output_directory_nfo_tags.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/plugins/split_by_chapters.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/plugins/square_thumbnail.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/plugins/static_nfo_tags.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/plugins/subtitles.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/plugins/throttle_protection.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/plugins/video_tags.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/helpers/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/helpers/download_deletion_options.yaml +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/helpers/filter_duration.yaml +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/helpers/filter_keywords.yaml +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/helpers/media_quality.yaml +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/helpers/players.yaml +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/helpers/throttle_protection.yaml +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/helpers/url_bilateral.yaml +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/internal/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/internal/view.yaml +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/music/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/music/albums_from_chapters.yaml +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/music/albums_from_playlists.yaml +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/music/singles.yaml +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/music/soundcloud.yaml +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/music_videos/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/music_videos/music_video_base.yaml +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/music_videos/music_video_extras.yaml +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/music_videos/music_videos.yaml +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/tv_show/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/tv_show/episode.yaml +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/tv_show/tv_show.yaml +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/prebuilt_presets/tv_show/tv_show_by_date.yaml +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/functions/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/functions/array_functions.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/functions/boolean_functions.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/functions/conditional_functions.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/functions/date_functions.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/functions/error_functions.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/functions/json_functions.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/functions/map_functions.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/functions/numeric_functions.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/functions/print_functions.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/functions/regex_functions.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/functions/string_functions.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/parser.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/script.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/script_output.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/types/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/types/array.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/types/function.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/types/map.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/types/resolvable.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/types/syntax_tree.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/types/variable.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/types/variable_dependency.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/utils/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/utils/exception_formatters.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/utils/exceptions.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/utils/name_validation.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/script/utils/type_checking.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/subscriptions/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/subscriptions/base_subscription.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/subscriptions/subscription.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/subscriptions/subscription_download.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/subscriptions/subscription_validators.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/subscriptions/subscription_ytdl_options.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/thread/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/thread/log_entries_downloaded_listener.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/utils/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/utils/chapters.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/utils/datetime.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/utils/exceptions.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/utils/ffmpeg.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/utils/file_handler.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/utils/file_lock.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/utils/file_path.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/utils/logger.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/utils/retry.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/utils/scriptable.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/utils/subtitles.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/utils/system.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/utils/thumbnail.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/utils/xml.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/utils/yaml.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/validators/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/validators/audo_codec_validator.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/validators/file_path_validators.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/validators/nfo_validators.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/validators/regex_validator.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/validators/source_variable_validator.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/validators/strict_dict_validator.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/validators/string_datetime.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/validators/string_select_validator.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/validators/validators.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/ytdl_additions/__init__.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub/ytdl_additions/enhanced_download_archive.py +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub.egg-info/SOURCES.txt +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub.egg-info/dependency_links.txt +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub.egg-info/entry_points.txt +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub.egg-info/requires.txt +0 -0
- {ytdl_sub-2025.12.31.post4 → ytdl_sub-2026.1.6}/src/ytdl_sub.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__pypi_version__ = "2026.01.06";__local_version__ = "2026.01.06+6b99c31"
|
|
@@ -238,20 +238,25 @@ class Overrides(UnstructuredDictFormatterValidator, Scriptable):
|
|
|
238
238
|
def apply_overrides_formatter_to_native(
|
|
239
239
|
self,
|
|
240
240
|
formatter: OverridesStringFormatterValidator,
|
|
241
|
+
function_overrides: Optional[Dict[str, str]] = None,
|
|
241
242
|
) -> Any:
|
|
242
243
|
"""
|
|
243
244
|
Parameters
|
|
244
245
|
----------
|
|
245
246
|
formatter
|
|
246
247
|
Overrides formatter to apply
|
|
248
|
+
function_overrides
|
|
249
|
+
Optional. Explicit values to override the overrides themselves and source variables
|
|
247
250
|
|
|
248
251
|
Returns
|
|
249
252
|
-------
|
|
250
253
|
The native python form of the resolved variable
|
|
251
254
|
"""
|
|
252
|
-
return
|
|
253
|
-
|
|
254
|
-
|
|
255
|
+
return formatter.post_process_native(
|
|
256
|
+
self._apply_to_resolvable(
|
|
257
|
+
formatter=formatter, entry=None, function_overrides=function_overrides
|
|
258
|
+
).native
|
|
259
|
+
)
|
|
255
260
|
|
|
256
261
|
def evaluate_boolean(
|
|
257
262
|
self, formatter: StringFormatterValidator, entry: Optional[Entry] = None
|
|
@@ -84,6 +84,9 @@ class VariableValidation:
|
|
|
84
84
|
)
|
|
85
85
|
resolved_subscription["download"] = []
|
|
86
86
|
for url_output in raw_download_output["download"]:
|
|
87
|
+
if isinstance(url_output["url"], list):
|
|
88
|
+
url_output["url"] = [url for url in url_output["url"] if bool(url)]
|
|
89
|
+
|
|
87
90
|
if url_output["url"]:
|
|
88
91
|
resolved_subscription["download"].append(url_output)
|
|
89
92
|
|
|
@@ -52,12 +52,12 @@ class UrlDownloaderBasePluginExtension(SourcePluginExtension[MultiUrlValidator])
|
|
|
52
52
|
|
|
53
53
|
if 0 <= input_url_idx < len(self.plugin_options.urls.list):
|
|
54
54
|
validator = self.plugin_options.urls.list[input_url_idx]
|
|
55
|
-
if self.overrides.
|
|
55
|
+
if entry_input_url in self.overrides.apply_overrides_formatter_to_native(validator.url):
|
|
56
56
|
return validator
|
|
57
57
|
|
|
58
58
|
# Match the first validator based on the URL, if one exists
|
|
59
59
|
for validator in self.plugin_options.urls.list:
|
|
60
|
-
if self.overrides.
|
|
60
|
+
if entry_input_url in self.overrides.apply_overrides_formatter_to_native(validator.url):
|
|
61
61
|
return validator
|
|
62
62
|
|
|
63
63
|
# Return the first validator if none exist
|
|
@@ -487,19 +487,27 @@ class MultiUrlDownloader(SourcePlugin[MultiUrlValidator]):
|
|
|
487
487
|
# download the bottom-most urls first since they are top-priority
|
|
488
488
|
for idx, url_validator in reversed(list(enumerate(self.collection.urls.list))):
|
|
489
489
|
# URLs can be empty. If they are, then skip
|
|
490
|
-
if not (
|
|
490
|
+
if not (urls := self.overrides.apply_overrides_formatter_to_native(url_validator.url)):
|
|
491
491
|
continue
|
|
492
492
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
493
|
+
assert isinstance(urls, list)
|
|
494
|
+
|
|
495
|
+
for url in reversed(urls):
|
|
496
|
+
assert isinstance(url, str)
|
|
497
|
+
|
|
498
|
+
if not url:
|
|
499
|
+
continue
|
|
500
|
+
|
|
501
|
+
for entry in self._download_metadata(url=url, validator=url_validator):
|
|
502
|
+
entry.initialize_script(self.overrides).add(
|
|
503
|
+
{
|
|
504
|
+
v.ytdl_sub_input_url: url,
|
|
505
|
+
v.ytdl_sub_input_url_index: idx,
|
|
506
|
+
v.ytdl_sub_input_url_count: len(self.collection.urls.list),
|
|
507
|
+
}
|
|
508
|
+
)
|
|
501
509
|
|
|
502
|
-
|
|
510
|
+
yield entry
|
|
503
511
|
|
|
504
512
|
def download(self, entry: Entry) -> Optional[Entry]:
|
|
505
513
|
"""
|
|
@@ -43,6 +43,19 @@ class UrlThumbnailListValidator(ListValidator[UrlThumbnailValidator]):
|
|
|
43
43
|
_inner_list_type = UrlThumbnailValidator
|
|
44
44
|
|
|
45
45
|
|
|
46
|
+
class OverridesOneOrManyUrlValidator(OverridesStringFormatterValidator):
|
|
47
|
+
def post_process_native(self, resolved: Any) -> Any:
|
|
48
|
+
if isinstance(resolved, str):
|
|
49
|
+
return [resolved]
|
|
50
|
+
if isinstance(resolved, list):
|
|
51
|
+
for value in resolved:
|
|
52
|
+
if not isinstance(value, str):
|
|
53
|
+
raise self._validation_exception("Must be a string or an array of strings.")
|
|
54
|
+
return resolved
|
|
55
|
+
|
|
56
|
+
raise self._validation_exception("Must be a string or an array of strings.")
|
|
57
|
+
|
|
58
|
+
|
|
46
59
|
class UrlValidator(StrictDictValidator):
|
|
47
60
|
_required_keys = {"url"}
|
|
48
61
|
_optional_keys = {
|
|
@@ -68,7 +81,7 @@ class UrlValidator(StrictDictValidator):
|
|
|
68
81
|
super().__init__(name, value)
|
|
69
82
|
|
|
70
83
|
# TODO: url validate using yt-dlp IE
|
|
71
|
-
self._url = self._validate_key(key="url", validator=
|
|
84
|
+
self._url = self._validate_key(key="url", validator=OverridesOneOrManyUrlValidator)
|
|
72
85
|
self._variables = self._validate_key_if_present(
|
|
73
86
|
key="variables", validator=DictFormatterValidator, default={}
|
|
74
87
|
)
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
presets:
|
|
2
|
+
|
|
3
|
+
##################################################################################
|
|
4
|
+
# Multi urls in the form of
|
|
5
|
+
#
|
|
6
|
+
# "Subscription Name":
|
|
7
|
+
# - "url"
|
|
8
|
+
# - "url2"
|
|
9
|
+
# or
|
|
10
|
+
#
|
|
11
|
+
# "Subscription Name": "url"
|
|
12
|
+
#
|
|
13
|
+
# where the first url tries to grab channel avatar + banner
|
|
14
|
+
#
|
|
15
|
+
_multi_url:
|
|
16
|
+
download:
|
|
17
|
+
- url: "{ %array_at(urls, 0) }"
|
|
18
|
+
playlist_thumbnails:
|
|
19
|
+
- name: "{avatar_uncropped_thumbnail_file_name}"
|
|
20
|
+
uid: "avatar_uncropped"
|
|
21
|
+
- name: "{banner_uncropped_thumbnail_file_name}"
|
|
22
|
+
uid: "banner_uncropped"
|
|
23
|
+
source_thumbnails:
|
|
24
|
+
- name: "{avatar_uncropped_thumbnail_file_name}"
|
|
25
|
+
uid: "avatar_uncropped"
|
|
26
|
+
- name: "{banner_uncropped_thumbnail_file_name}"
|
|
27
|
+
uid: "banner_uncropped"
|
|
28
|
+
include_sibling_metadata: "{include_sibling_metadata}"
|
|
29
|
+
webpage_url: "{modified_webpage_url}"
|
|
30
|
+
|
|
31
|
+
- url: "{ %array_slice(urls, 1) }"
|
|
32
|
+
include_sibling_metadata: "{include_sibling_metadata}"
|
|
33
|
+
webpage_url: "{modified_webpage_url}"
|
|
34
|
+
overrides:
|
|
35
|
+
avatar_uncropped_thumbnail_file_name: ""
|
|
36
|
+
banner_uncropped_thumbnail_file_name: ""
|
|
37
|
+
include_sibling_metadata: False
|
|
38
|
+
modified_webpage_url: "{webpage_url}"
|
|
39
|
+
|
|
40
|
+
subscription_array: >-
|
|
41
|
+
{
|
|
42
|
+
[
|
|
43
|
+
url, url2, url3, url4, url5, url6, url7, url8, url9, url10,
|
|
44
|
+
url11, url12, url13, url14, url15, url16, url17, url18, url19, url20,
|
|
45
|
+
url21, url22, url23, url24, url25, url26, url27, url28, url29, url30,
|
|
46
|
+
url31, url32, url33, url34, url35, url36, url37, url38, url39, url40,
|
|
47
|
+
url41, url42, url43, url44, url45, url46, url47, url48, url49, url50,
|
|
48
|
+
url51, url52, url53, url54, url55, url56, url57, url58, url59, url60,
|
|
49
|
+
url61, url62, url63, url64, url65, url66, url67, url68, url69, url70,
|
|
50
|
+
url71, url72, url73, url74, url75, url76, url77, url78, url79, url80,
|
|
51
|
+
url81, url82, url83, url84, url85, url86, url87, url88, url89, url90,
|
|
52
|
+
url91, url92, url93, url94, url95, url96, url97, url98, url99, url100
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
urls: "{subscription_array}"
|
|
56
|
+
|
|
57
|
+
subscription_value: ""
|
|
58
|
+
url: "{subscription_value}"
|
|
59
|
+
url2: ""
|
|
60
|
+
url3: ""
|
|
61
|
+
url4: ""
|
|
62
|
+
url5: ""
|
|
63
|
+
url6: ""
|
|
64
|
+
url7: ""
|
|
65
|
+
url8: ""
|
|
66
|
+
url9: ""
|
|
67
|
+
url10: ""
|
|
68
|
+
url11: ""
|
|
69
|
+
url12: ""
|
|
70
|
+
url13: ""
|
|
71
|
+
url14: ""
|
|
72
|
+
url15: ""
|
|
73
|
+
url16: ""
|
|
74
|
+
url17: ""
|
|
75
|
+
url18: ""
|
|
76
|
+
url19: ""
|
|
77
|
+
url20: ""
|
|
78
|
+
url21: ""
|
|
79
|
+
url22: ""
|
|
80
|
+
url23: ""
|
|
81
|
+
url24: ""
|
|
82
|
+
url25: ""
|
|
83
|
+
url26: ""
|
|
84
|
+
url27: ""
|
|
85
|
+
url28: ""
|
|
86
|
+
url29: ""
|
|
87
|
+
url30: ""
|
|
88
|
+
url31: ""
|
|
89
|
+
url32: ""
|
|
90
|
+
url33: ""
|
|
91
|
+
url34: ""
|
|
92
|
+
url35: ""
|
|
93
|
+
url36: ""
|
|
94
|
+
url37: ""
|
|
95
|
+
url38: ""
|
|
96
|
+
url39: ""
|
|
97
|
+
url40: ""
|
|
98
|
+
url41: ""
|
|
99
|
+
url42: ""
|
|
100
|
+
url43: ""
|
|
101
|
+
url44: ""
|
|
102
|
+
url45: ""
|
|
103
|
+
url46: ""
|
|
104
|
+
url47: ""
|
|
105
|
+
url48: ""
|
|
106
|
+
url49: ""
|
|
107
|
+
url50: ""
|
|
108
|
+
url51: ""
|
|
109
|
+
url52: ""
|
|
110
|
+
url53: ""
|
|
111
|
+
url54: ""
|
|
112
|
+
url55: ""
|
|
113
|
+
url56: ""
|
|
114
|
+
url57: ""
|
|
115
|
+
url58: ""
|
|
116
|
+
url59: ""
|
|
117
|
+
url60: ""
|
|
118
|
+
url61: ""
|
|
119
|
+
url62: ""
|
|
120
|
+
url63: ""
|
|
121
|
+
url64: ""
|
|
122
|
+
url65: ""
|
|
123
|
+
url66: ""
|
|
124
|
+
url67: ""
|
|
125
|
+
url68: ""
|
|
126
|
+
url69: ""
|
|
127
|
+
url70: ""
|
|
128
|
+
url71: ""
|
|
129
|
+
url72: ""
|
|
130
|
+
url73: ""
|
|
131
|
+
url74: ""
|
|
132
|
+
url75: ""
|
|
133
|
+
url76: ""
|
|
134
|
+
url77: ""
|
|
135
|
+
url78: ""
|
|
136
|
+
url79: ""
|
|
137
|
+
url80: ""
|
|
138
|
+
url81: ""
|
|
139
|
+
url82: ""
|
|
140
|
+
url83: ""
|
|
141
|
+
url84: ""
|
|
142
|
+
url85: ""
|
|
143
|
+
url86: ""
|
|
144
|
+
url87: ""
|
|
145
|
+
url88: ""
|
|
146
|
+
url89: ""
|
|
147
|
+
url90: ""
|
|
148
|
+
url91: ""
|
|
149
|
+
url92: ""
|
|
150
|
+
url93: ""
|
|
151
|
+
url94: ""
|
|
152
|
+
url95: ""
|
|
153
|
+
url96: ""
|
|
154
|
+
url97: ""
|
|
155
|
+
url98: ""
|
|
156
|
+
url99: ""
|
|
157
|
+
url100: ""
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
# multi-url with bilateral scraping built into it via
|
|
161
|
+
# inspection of the URL and conditionally adding another
|
|
162
|
+
# ytdl-sub url download with the scraping and download reversed
|
|
163
|
+
_multi_url_bilateral_inner:
|
|
164
|
+
preset:
|
|
165
|
+
- "_url_bilateral_overrides"
|
|
166
|
+
|
|
167
|
+
download:
|
|
168
|
+
- url: "{ %array_apply(urls, %bilateral_url) }"
|
|
169
|
+
download_reverse: False
|
|
170
|
+
ytdl_options:
|
|
171
|
+
playlist_items: "-1:0:-1"
|
|
172
|
+
webpage_url: "{modified_webpage_url}"
|
|
173
|
+
|
|
174
|
+
_multi_url_bilateral:
|
|
175
|
+
preset:
|
|
176
|
+
- "_multi_url_bilateral_inner"
|
|
177
|
+
- "_multi_url"
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
presets:
|
|
2
|
+
# Preset for categorizing URls like so
|
|
3
|
+
#
|
|
4
|
+
# subscription_name:
|
|
5
|
+
# category_1:
|
|
6
|
+
# - https://...1
|
|
7
|
+
# - https://...2
|
|
8
|
+
# category_2:
|
|
9
|
+
# - url: https://...1
|
|
10
|
+
# metadata_field_1: 2011
|
|
11
|
+
# metadata_field_2: 'abc"
|
|
12
|
+
# ...
|
|
13
|
+
#
|
|
14
|
+
# Metadata field of `url` must exist, other ones can be anything.
|
|
15
|
+
# Only supports a single level of nesting.
|
|
16
|
+
_url_categorized:
|
|
17
|
+
preset:
|
|
18
|
+
- "_multi_url_bilateral"
|
|
19
|
+
|
|
20
|
+
overrides:
|
|
21
|
+
# Parameters:
|
|
22
|
+
# $0: url string or map containing url + metadata fields
|
|
23
|
+
# $1: category key
|
|
24
|
+
#
|
|
25
|
+
# Output:
|
|
26
|
+
# Map containing { url: ..., category: ..., metadata_field_1: ... }
|
|
27
|
+
"%flat_array__url_to_map_format": >-
|
|
28
|
+
{
|
|
29
|
+
%elif(
|
|
30
|
+
%is_map($0),
|
|
31
|
+
%map_extend( $0, { "category": $1 } ),
|
|
32
|
+
%is_string($0),
|
|
33
|
+
{ "url": $0, "category": $1 },
|
|
34
|
+
%throw("If using album categories, each URL must be either a string or map with metadata fields")
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
# Parameters:
|
|
39
|
+
# $0: category key
|
|
40
|
+
# $1: array of URLs in either string or map form
|
|
41
|
+
#
|
|
42
|
+
# Output:
|
|
43
|
+
# Array containing [{ url: ..., category: ... }, ... ]
|
|
44
|
+
"%flat_array__category_to_map_format": >-
|
|
45
|
+
{
|
|
46
|
+
%array_apply_fixed(
|
|
47
|
+
%assert_then(
|
|
48
|
+
%is_array( $1 ),
|
|
49
|
+
$1,
|
|
50
|
+
"If using album categories, each category must map to an array"
|
|
51
|
+
),
|
|
52
|
+
$0,
|
|
53
|
+
%flat_array__url_to_map_format
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
# Parameters:
|
|
58
|
+
# $0: map containing fields { url: <url_value>, category: ... }
|
|
59
|
+
#
|
|
60
|
+
# Output:
|
|
61
|
+
# Nested map containing { <url_value>: { url: <url_value>, category: ... } }
|
|
62
|
+
"%flat_array__url_keyed_map_format": >-
|
|
63
|
+
{ { %map_get($0, "url"): $0 } }
|
|
64
|
+
|
|
65
|
+
# Creates an array in the form of [ { url: ..., category: ..., metadata_field_1: ... }, ... ]
|
|
66
|
+
category_url_array: >-
|
|
67
|
+
{ %array_flatten( %map_apply( subscription_map, %flat_array__category_to_map_format ) ) }
|
|
68
|
+
|
|
69
|
+
# Creates a map in the form of { <url value>: { category: ..., metadata_field_1: ... }, ... }
|
|
70
|
+
category_url_map: >-
|
|
71
|
+
{
|
|
72
|
+
%array_reduce(
|
|
73
|
+
%array_apply( category_url_array, %flat_array__url_keyed_map_format ),
|
|
74
|
+
%map_extend
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
# Parameters:
|
|
79
|
+
# $0: metadata field to fetch for the current url
|
|
80
|
+
# $1: default value
|
|
81
|
+
#
|
|
82
|
+
# Output:
|
|
83
|
+
# Metadata field value if it exists. Otherwise, return default value
|
|
84
|
+
"%get_url_field": >-
|
|
85
|
+
{ %map_get( %map( %map_get( category_url_map, ytdl_sub_input_url, {} ) ), $0, $1 ) }
|
|
86
|
+
|
|
87
|
+
# Parameters:
|
|
88
|
+
# $0: metadata field to fetch for the current url
|
|
89
|
+
#
|
|
90
|
+
# Output:
|
|
91
|
+
# True if field is specified. False otherwise.
|
|
92
|
+
"%contains_url_field": >-
|
|
93
|
+
{ %not( %is_null( %get_url_field( $0, null ) ) ) }
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
# Parameters:
|
|
97
|
+
# $0: integer to fetch the i'th url using 1-based indexing
|
|
98
|
+
#
|
|
99
|
+
# Output:
|
|
100
|
+
# i'th url in the category map
|
|
101
|
+
"%get_url_i": >-
|
|
102
|
+
{
|
|
103
|
+
%map_get(
|
|
104
|
+
%map( %array_at( category_url_array, %int( %sub($0, 1) ), {} ) ),
|
|
105
|
+
"url",
|
|
106
|
+
%array_at(subscription_array, %int( %sub($0, 1) ), null)
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
subscription_map: "{ {} }"
|
|
111
|
+
urls: "{ %array_apply(%range(100, 1), %get_url_i) }"
|