test in tv show collection

This commit is contained in:
Jesse Bannon 2024-03-27 23:43:35 -07:00
parent 052db8704b
commit de1e68e5aa
5 changed files with 50 additions and 12 deletions

View file

@ -25,6 +25,7 @@ from ytdl_sub.entries.script.variable_definitions import VARIABLES
from ytdl_sub.entries.script.variable_definitions import VariableDefinitions from ytdl_sub.entries.script.variable_definitions import VariableDefinitions
from ytdl_sub.utils.file_handler import FileHandler from ytdl_sub.utils.file_handler import FileHandler
from ytdl_sub.utils.logger import Logger from ytdl_sub.utils.logger import Logger
from ytdl_sub.utils.script import ScriptUtils
from ytdl_sub.utils.thumbnail import ThumbnailTypes from ytdl_sub.utils.thumbnail import ThumbnailTypes
from ytdl_sub.utils.thumbnail import download_and_convert_url_thumbnail from ytdl_sub.utils.thumbnail import download_and_convert_url_thumbnail
from ytdl_sub.utils.thumbnail import try_convert_download_thumbnail from ytdl_sub.utils.thumbnail import try_convert_download_thumbnail
@ -245,9 +246,13 @@ class MultiUrlDownloader(SourcePlugin[MultiUrlValidator]):
.to_dict() .to_dict()
) )
@property def metadata_ytdl_options(self, scrape_reverse: bool) -> Dict:
def metadata_ytdl_options(self) -> Dict:
""" """
Parameters
----------
scrape_reverse
Whether to scrape in reverse order
Returns Returns
------- -------
YTDL options dict for fetching metadata YTDL options dict for fetching metadata
@ -255,6 +260,7 @@ class MultiUrlDownloader(SourcePlugin[MultiUrlValidator]):
return ( return (
self._metadata_ytdl_options_builder.clone() self._metadata_ytdl_options_builder.clone()
.add(self.ytdl_option_defaults(), before=True) .add(self.ytdl_option_defaults(), before=True)
.add({"playlistreverse": scrape_reverse} if scrape_reverse else None, before=True)
.to_dict() .to_dict()
) )
@ -390,16 +396,19 @@ class MultiUrlDownloader(SourcePlugin[MultiUrlValidator]):
yield entry_child yield entry_child
def _download_url_metadata( def _download_url_metadata(
self, url: str, include_sibling_metadata: bool self, url: str, include_sibling_metadata: bool, scrape_reverse: bool
) -> Tuple[List[EntryParent], List[Entry]]: ) -> Tuple[List[EntryParent], List[Entry]]:
""" """
Downloads only info.json files and forms EntryParent trees Downloads only info.json files and forms EntryParent trees
""" """
with self._separate_download_archives(): with self._separate_download_archives():
entry_dicts = YTDLP.extract_info_via_info_json( entry_dicts = YTDLP.extract_info_via_info_json(
working_directory=self.working_directory, working_directory=self.working_directory,
ytdl_options_overrides=self.metadata_ytdl_options, ytdl_options_overrides=self.metadata_ytdl_options(scrape_reverse=scrape_reverse),
log_prefix_on_info_json_dl="Downloading metadata for", log_prefix_on_info_json_dl=(
f"Downloading metadata {'in reverse ' if scrape_reverse else ''}for"
),
url=url, url=url,
) )
@ -448,7 +457,11 @@ class MultiUrlDownloader(SourcePlugin[MultiUrlValidator]):
continue continue
parents, orphan_entries = self._download_url_metadata( parents, orphan_entries = self._download_url_metadata(
url=url, include_sibling_metadata=collection_url.include_sibling_metadata url=url,
include_sibling_metadata=collection_url.include_sibling_metadata,
scrape_reverse=ScriptUtils.bool_formatter_output(
self.overrides.apply_formatter(collection_url.scrape_reverse)
),
) )
# TODO: Encapsulate this logic into its own class # TODO: Encapsulate this logic into its own class
@ -462,7 +475,9 @@ class MultiUrlDownloader(SourcePlugin[MultiUrlValidator]):
for entry in self._iterate_entries( for entry in self._iterate_entries(
parents=parents, parents=parents,
orphans=orphan_entries, orphans=orphan_entries,
download_reversed=collection_url.download_reverse, download_reversed=ScriptUtils.bool_formatter_output(
self.overrides.apply_formatter(collection_url.download_reverse)
),
): ):
entry.initialize_script(self.overrides).add( entry.initialize_script(self.overrides).add(
{v.ytdl_sub_input_url: self.overrides.apply_formatter(collection_url.url)} {v.ytdl_sub_input_url: self.overrides.apply_formatter(collection_url.url)}

View file

@ -8,6 +8,7 @@ from ytdl_sub.config.validators.options import OptionsValidator
from ytdl_sub.script.parser import parse from ytdl_sub.script.parser import parse
from ytdl_sub.validators.strict_dict_validator import StrictDictValidator from ytdl_sub.validators.strict_dict_validator import StrictDictValidator
from ytdl_sub.validators.string_formatter_validators import DictFormatterValidator from ytdl_sub.validators.string_formatter_validators import DictFormatterValidator
from ytdl_sub.validators.string_formatter_validators import OverridesBooleanFormatterValidator
from ytdl_sub.validators.string_formatter_validators import OverridesStringFormatterValidator from ytdl_sub.validators.string_formatter_validators import OverridesStringFormatterValidator
from ytdl_sub.validators.string_formatter_validators import StringFormatterValidator from ytdl_sub.validators.string_formatter_validators import StringFormatterValidator
from ytdl_sub.validators.validators import BoolValidator from ytdl_sub.validators.validators import BoolValidator
@ -49,6 +50,7 @@ class UrlValidator(StrictDictValidator):
"source_thumbnails", "source_thumbnails",
"playlist_thumbnails", "playlist_thumbnails",
"download_reverse", "download_reverse",
"scrape_reverse",
"include_sibling_metadata", "include_sibling_metadata",
} }
@ -77,7 +79,10 @@ class UrlValidator(StrictDictValidator):
key="playlist_thumbnails", validator=UrlThumbnailListValidator, default=[] key="playlist_thumbnails", validator=UrlThumbnailListValidator, default=[]
) )
self._download_reverse = self._validate_key( self._download_reverse = self._validate_key(
key="download_reverse", validator=BoolValidator, default=True key="download_reverse", validator=OverridesBooleanFormatterValidator, default="True"
)
self._scrape_reverse = self._validate_key(
key="scrape_reverse", validator=OverridesBooleanFormatterValidator, default="False"
) )
self._include_sibling_metadata = self._validate_key( self._include_sibling_metadata = self._validate_key(
key="include_sibling_metadata", validator=BoolValidator, default=False key="include_sibling_metadata", validator=BoolValidator, default=False
@ -148,12 +153,20 @@ class UrlValidator(StrictDictValidator):
return self._source_thumbnails return self._source_thumbnails
@property @property
def download_reverse(self) -> bool: def download_reverse(self) -> OverridesBooleanFormatterValidator:
""" """
Optional. Whether to download entries in the reverse order of the metadata downloaded. Optional. Whether to download entries in the reverse order of the metadata downloaded.
Defaults to True. Defaults to True.
""" """
return self._download_reverse.value return self._download_reverse
@property
def scrape_reverse(self) -> OverridesBooleanFormatterValidator:
"""
Optional. Whether to scrape entry metadata in the reverse order.
Defaults to False.
"""
return self._scrape_reverse
@property @property
def include_sibling_metadata(self) -> bool: def include_sibling_metadata(self) -> bool:

View file

@ -30,6 +30,11 @@ class CustomFunctions:
Queries a playlist-based URL using yt-dlp to see if it is ordered from newest Queries a playlist-based URL using yt-dlp to see if it is ordered from newest
(lower playlist number) to oldest. (lower playlist number) to oldest.
""" """
# Top-level allow-list of notorious playlists that can be
# ordered in either direction
if not any(["youtube.com/playlist" in url.value]):
return Boolean("True")
info_only_kwargs = { info_only_kwargs = {
"skip_download": True, "skip_download": True,
"writethumbnail": False, "writethumbnail": False,
@ -47,7 +52,7 @@ class CustomFunctions:
if ( if (
not isinstance(url_info, dict) not isinstance(url_info, dict)
or not isinstance(url_info.get("entries"), list) or not isinstance(url_info.get("entries"), list)
or not len(url_info["entries"]) or len(url_info["entries"]) == 0
): ):
return Boolean(False) return Boolean(False)
@ -66,7 +71,7 @@ class CustomFunctions:
return Boolean(True) return Boolean(True)
except Exception: except Exception: # pylint: disable=broad-except
return Boolean(False) return Boolean(False)
@staticmethod @staticmethod

View file

@ -5,6 +5,7 @@ from ytdl_sub.entries.script.variable_definitions import VariableDefinitions
v: VariableDefinitions = VARIABLES v: VariableDefinitions = VARIABLES
# TODO: Make this a proper class with docstrings
CUSTOM_FUNCTION_SCRIPTS: Dict[str, str] = { CUSTOM_FUNCTION_SCRIPTS: Dict[str, str] = {
############################################################################################# #############################################################################################
# SIBLING GETTER # SIBLING GETTER

View file

@ -38,6 +38,10 @@ presets:
uid: "avatar_uncropped" uid: "avatar_uncropped"
- name: "{tv_show_fanart_file_name}" - name: "{tv_show_fanart_file_name}"
uid: "banner_uncropped" uid: "banner_uncropped"
scrape_reverse: >-
{ %not( %is_playlist_ordered_by_newest( collection_season_1_url )) }
download_reverse: >-
{ %is_playlist_ordered_by_newest( collection_season_1_url ) }
output_directory_nfo_tags: output_directory_nfo_tags:
tags: tags: