From ca0ac787b0db25a27a31ab1f571b8a7413051e34 Mon Sep 17 00:00:00 2001 From: Jesse Bannon Date: Mon, 29 Aug 2022 22:50:42 -0700 Subject: [PATCH] [FEATURE] Ability to write .info.json files (#201) --- examples/kodi_music_videos_config.yaml | 1 + examples/kodi_tv_shows_config.yaml | 1 + examples/soundcloud_discography_config.yaml | 7 +- examples/youtube_extract_and_tag_audio.yaml | 1 + src/ytdl_sub/config/preset_options.py | 14 + src/ytdl_sub/entries/entry.py | 29 ++ .../entries/variables/entry_variables.py | 10 + .../subscriptions/base_subscription.py | 136 +++++++ src/ytdl_sub/subscriptions/subscription.py | 381 +----------------- .../subscriptions/subscription_download.py | 271 +++++++++++++ tests/e2e/expected_download.py | 10 +- .../date_range/test_channel_recent.json | 4 +- .../test_channel_rolling_recent.json | 3 +- .../plugins/split_by_chapters_video.json | 11 + ...ters_with_regex_no_chapters_video_pass.txt | 1 + .../split_by_chapters_with_regex_video.json | 13 +- .../plugins/test_audio_extract_playlist.json | 3 + .../plugins/test_audio_extract_single.json | 1 + .../test_chapters_from_ts_with_subs.json | 1 + .../test_chapters_sb_and_embedded_subs.json | 1 + .../plugins/test_subtitles_embedded.json | 1 + .../test_subtitles_embedded_and_file.json | 1 + .../test_soundcloud_discography.json | 15 +- .../youtube/test_channel_full.json | 14 +- .../youtube/test_merge_playlist.json | 1 + .../youtube/test_playlist.json | 5 +- .../youtube/test_split_video.json | 6 + .../youtube/test_video.json | 1 + .../date_range/test_channel_recent.txt | 2 + .../test_channel_rolling_recent.txt | 1 + .../plugins/nfo_tags/test_nfo.txt | 1 + .../plugins/nfo_tags/test_nfo_kodi_safe.txt | 1 + .../split_by_chapters_video-dry-run.txt | 11 + .../plugins/split_by_chapters_video.txt | 11 + ...ters_with_regex_no_chapters_video_pass.txt | 1 + ...t_by_chapters_with_regex_video-dry-run.txt | 13 +- .../split_by_chapters_with_regex_video.txt | 13 +- .../plugins/test_audio_extract_playlist.txt | 3 + .../plugins/test_audio_extract_single.txt | 1 + .../test_chapters_from_ts_with_subs.txt | 1 + .../test_chapters_sb_and_embedded_subs.txt | 1 + .../plugins/test_regex.txt | 2 + .../plugins/test_subtitles_embedded.txt | 1 + .../test_subtitles_embedded_and_file.txt | 1 + .../test_soundcloud_discography.txt | 13 + .../youtube/test_channel_full.txt | 12 + .../youtube/test_merge_playlist.txt | 1 + .../youtube/test_playlist.txt | 3 + .../youtube/test_split_video.txt | 6 + .../youtube/test_video.txt | 1 + tests/unit/entries/conftest.py | 1 + 51 files changed, 650 insertions(+), 394 deletions(-) create mode 100644 src/ytdl_sub/subscriptions/base_subscription.py create mode 100644 src/ytdl_sub/subscriptions/subscription_download.py diff --git a/examples/kodi_music_videos_config.yaml b/examples/kodi_music_videos_config.yaml index 0ce8d1d8..0beaf1b8 100644 --- a/examples/kodi_music_videos_config.yaml +++ b/examples/kodi_music_videos_config.yaml @@ -38,6 +38,7 @@ presets: output_directory: "{music_video_directory}" file_name: "{music_video_name}.{ext}" thumbnail_name: "{music_video_name}-thumb.jpg" + info_json_name: "{music_video_name}.{info_json_ext}" # For each video downloaded, add a music video NFO file for it. Populate it # with tags that Kodi will read and use to display it in the music or music diff --git a/examples/kodi_tv_shows_config.yaml b/examples/kodi_tv_shows_config.yaml index 2d4536cf..04e8bc9c 100644 --- a/examples/kodi_tv_shows_config.yaml +++ b/examples/kodi_tv_shows_config.yaml @@ -53,6 +53,7 @@ presets: output_directory: "{youtube_tv_shows_directory}/{tv_show_name_sanitized}" file_name: "{episode_name}.{ext}" thumbnail_name: "{episode_name}-thumb.jpg" + info_json_name: "{episode_name}.{info_json_ext}" maintain_download_archive: True # For each video downloaded, add an episode NFO file for it. We give it diff --git a/examples/soundcloud_discography_config.yaml b/examples/soundcloud_discography_config.yaml index 5b10b3c8..bfc03416 100644 --- a/examples/soundcloud_discography_config.yaml +++ b/examples/soundcloud_discography_config.yaml @@ -44,8 +44,9 @@ presets: # them on a successive invocation. output_options: output_directory: "{music_directory}" - file_name: "{artist_sanitized}/{album_directory_name}/{track_number_padded} - {title_sanitized}.{ext}" - thumbnail_name: "{artist_sanitized}/{album_directory_name}/folder.jpg" + file_name: "{album_path}/{track_file_name}.{ext}" + thumbnail_name: "{album_path}/folder.{thumbnail_ext}" + info_json_name: "{album_path}/{track_file_name}.{info_json_ext}" maintain_download_archive: True # For each song downloaded, populate the audio file with music tags. @@ -67,4 +68,6 @@ presets: # which gets reused above for the audio file name and album art path. overrides: album_directory_name: "[{album_year}] {album_sanitized}" + track_file_name: "{track_number_padded} - {title_sanitized}" + album_path: "{artist_sanitized}/{album_directory_name}" music_directory: "/path/to/music" \ No newline at end of file diff --git a/examples/youtube_extract_and_tag_audio.yaml b/examples/youtube_extract_and_tag_audio.yaml index 223fcfb6..b18aaf53 100644 --- a/examples/youtube_extract_and_tag_audio.yaml +++ b/examples/youtube_extract_and_tag_audio.yaml @@ -10,6 +10,7 @@ presets: output_options: output_directory: "{music_directory}" file_name: "{custom_track_name_sanitized}.{ext}" + info_json_name: "{custom_track_name_sanitized}.{info_json_ext}" audio_extract: codec: "mp3" diff --git a/src/ytdl_sub/config/preset_options.py b/src/ytdl_sub/config/preset_options.py index 7ae03041..9a2803a9 100644 --- a/src/ytdl_sub/config/preset_options.py +++ b/src/ytdl_sub/config/preset_options.py @@ -118,6 +118,7 @@ class OutputOptions(StrictDictValidator): file_name: "{title_sanitized}.{ext}" # optional thumbnail_name: "{title_sanitized}.{thumbnail_ext}" + info_json_name: "{title_sanitized}.{info_json_ext}" maintain_download_archive: True keep_files_before: now keep_files_after: 19000101 @@ -126,6 +127,7 @@ class OutputOptions(StrictDictValidator): _required_keys = {"output_directory", "file_name"} _optional_keys = { "thumbnail_name", + "info_json_name", "subtitles_name", "maintain_download_archive", "keep_files_before", @@ -148,6 +150,9 @@ class OutputOptions(StrictDictValidator): self._thumbnail_name = self._validate_key_if_present( key="thumbnail_name", validator=StringFormatterValidator ) + self._info_json_name = self._validate_key_if_present( + key="info_json_name", validator=StringFormatterValidator + ) self._maintain_download_archive = self._validate_key_if_present( key="maintain_download_archive", validator=BoolValidator, default=False @@ -191,6 +196,15 @@ class OutputOptions(StrictDictValidator): """ return self._thumbnail_name + @property + def info_json_name(self) -> Optional[StringFormatterValidator]: + """ + Optional. The file name for the media's info json file. This can include directories such + as ``"Season {upload_year}/{title}.{info_json_ext}"``, and will be placed in the output + directory. + """ + return self._info_json_name + @property def maintain_download_archive(self) -> bool: """ diff --git a/src/ytdl_sub/entries/entry.py b/src/ytdl_sub/entries/entry.py index 47236464..9298a611 100644 --- a/src/ytdl_sub/entries/entry.py +++ b/src/ytdl_sub/entries/entry.py @@ -1,3 +1,5 @@ +import copy +import json import os from pathlib import Path from typing import Dict @@ -59,6 +61,33 @@ class Entry(EntryVariables, BaseEntry): return None + def get_download_info_json_name(self) -> str: + """ + Returns + ------- + The download info json's file name + """ + return f"{self.uid}.{self.info_json_ext}" + + def get_download_info_json_path(self) -> str: + """ + Returns + ------- + Entry's downloaded info json file path + """ + return str(Path(self.working_directory()) / self.get_download_info_json_name()) + + def write_info_json(self) -> None: + """ + Write the entry's _kwargs back into the info.json file as well as its source variables + """ + kwargs_dict = copy.deepcopy(self._kwargs) + kwargs_dict["ytdl_sub_entry_variables"] = self.to_dict() + kwargs_json = json.dumps(kwargs_dict, ensure_ascii=False, sort_keys=True, indent=2) + + with open(self.get_download_info_json_path(), "w", encoding="utf-8") as file: + file.write(kwargs_json) + @final def is_downloaded(self) -> bool: """ diff --git a/src/ytdl_sub/entries/variables/entry_variables.py b/src/ytdl_sub/entries/variables/entry_variables.py index faa3b646..c4f42fe5 100644 --- a/src/ytdl_sub/entries/variables/entry_variables.py +++ b/src/ytdl_sub/entries/variables/entry_variables.py @@ -304,3 +304,13 @@ class EntryVariables(SourceVariables): The uploaded date formatted as YYYY-MM-DD """ return f"{self.upload_year}-{self.upload_month_padded}-{self.upload_day_padded}" + + @property + def info_json_ext(self) -> str: + """ + Returns + ------- + str + The "info.json" extension + """ + return "info.json" diff --git a/src/ytdl_sub/subscriptions/base_subscription.py b/src/ytdl_sub/subscriptions/base_subscription.py new file mode 100644 index 00000000..03f7b6f5 --- /dev/null +++ b/src/ytdl_sub/subscriptions/base_subscription.py @@ -0,0 +1,136 @@ +from abc import ABC +from pathlib import Path +from typing import Type + +from ytdl_sub.config.config_file import ConfigOptions +from ytdl_sub.config.preset import Preset +from ytdl_sub.config.preset import PresetPlugins +from ytdl_sub.config.preset_options import OutputOptions +from ytdl_sub.config.preset_options import Overrides +from ytdl_sub.config.preset_options import YTDLOptions +from ytdl_sub.downloaders.downloader import Downloader +from ytdl_sub.downloaders.downloader import DownloaderValidator +from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive + + +class BaseSubscription(ABC): + """ + Subscription classes are the 'controllers' that perform... + + - Downloading via ytdlp + - Adding metadata + - Placing files in the output directory + + while configuring each step with provided configs. Child classes are expected to + provide SourceValidator (SourceT), which defines the source and its configurable options. + In addition, they should provide in the init an Entry type (EntryT), which is the entry that + will be returned after downloading. + """ + + def __init__( + self, + name: str, + config_options: ConfigOptions, + preset_options: Preset, + ): + """ + Parameters + ---------- + name: str + Name of the subscription + config_options: ConfigOptions + preset_options: Preset + """ + self.name = name + self._config_options = config_options + self._preset_options = preset_options + + self._enhanced_download_archive = EnhancedDownloadArchive( + subscription_name=name, + working_directory=self.working_directory, + output_directory=self.output_directory, + ) + + @property + def downloader_class(self) -> Type[Downloader]: + """ + Returns + ------- + This subscription's downloader class + """ + return self._preset_options.downloader + + @property + def downloader_options(self) -> DownloaderValidator: + """ + Returns + ------- + The download options for this subscription's downloader + """ + return self._preset_options.downloader_options + + @property + def plugins(self) -> PresetPlugins: + """ + Returns + ------- + List of tuples containing (plugin class, plugin options) + """ + return self._preset_options.plugins + + @property + def ytdl_options(self) -> YTDLOptions: + """ + Returns + ------- + YTDL options for this subscription + """ + return self._preset_options.ytdl_options + + @property + def output_options(self) -> OutputOptions: + """ + Returns + ------- + The output options defined for this subscription + """ + return self._preset_options.output_options + + @property + def overrides(self) -> Overrides: + """ + Returns + ------- + The overrides defined for this subscription + """ + return self._preset_options.overrides + + @property + def working_directory(self) -> str: + """ + Returns + ------- + The directory that the downloader saves files to + """ + return str(Path(self._config_options.working_directory) / Path(self.name)) + + @property + def output_directory(self) -> str: + """ + Returns + ------- + The formatted output directory + """ + return self.overrides.apply_formatter(formatter=self.output_options.output_directory) + + @property + def maintain_download_archive(self) -> bool: + """ + Returns + ------- + Whether to maintain a download archive + """ + return ( + self.output_options.maintain_download_archive + and self.downloader_class.supports_download_archive + ) diff --git a/src/ytdl_sub/subscriptions/subscription.py b/src/ytdl_sub/subscriptions/subscription.py index 251d4caf..c70a3a27 100644 --- a/src/ytdl_sub/subscriptions/subscription.py +++ b/src/ytdl_sub/subscriptions/subscription.py @@ -1,388 +1,11 @@ -import contextlib -import os -import shutil -from pathlib import Path from typing import Dict -from typing import List -from typing import Optional -from typing import Type from ytdl_sub.config.config_file import ConfigFile -from ytdl_sub.config.config_file import ConfigOptions from ytdl_sub.config.preset import Preset -from ytdl_sub.config.preset import PresetPlugins -from ytdl_sub.config.preset_options import OutputOptions -from ytdl_sub.config.preset_options import Overrides -from ytdl_sub.config.preset_options import YTDLOptions -from ytdl_sub.downloaders.downloader import Downloader -from ytdl_sub.downloaders.downloader import DownloaderValidator -from ytdl_sub.entries.entry import Entry -from ytdl_sub.plugins.plugin import Plugin -from ytdl_sub.subscriptions.subscription_ytdl_options import SubscriptionYTDLOptions -from ytdl_sub.utils.datetime import to_date_range -from ytdl_sub.utils.exceptions import ValidationException -from ytdl_sub.utils.file_handler import FileHandlerTransactionLog -from ytdl_sub.utils.file_handler import FileMetadata -from ytdl_sub.utils.thumbnail import convert_download_thumbnail -from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive +from ytdl_sub.subscriptions.subscription_download import SubscriptionDownload -def _get_split_plugin(plugins: List[Plugin]) -> Optional[Plugin]: - split_plugins = [plugin for plugin in plugins if plugin.is_split_plugin] - - if len(split_plugins) == 1: - return split_plugins[0] - if len(split_plugins) > 1: - raise ValidationException("Can not use more than one split plugins at a time") - return None - - -class Subscription: - """ - Subscription classes are the 'controllers' that perform... - - - Downloading via ytdlp - - Adding metadata - - Placing files in the output directory - - while configuring each step with provided configs. Child classes are expected to - provide SourceValidator (SourceT), which defines the source and its configurable options. - In addition, they should provide in the init an Entry type (EntryT), which is the entry that - will be returned after downloading. - """ - - def __init__( - self, - name: str, - config_options: ConfigOptions, - preset_options: Preset, - ): - """ - Parameters - ---------- - name: str - Name of the subscription - config_options: ConfigOptions - preset_options: Preset - """ - self.name = name - self.__config_options = config_options - self.__preset_options = preset_options - - self._enhanced_download_archive = EnhancedDownloadArchive( - subscription_name=name, - working_directory=self.working_directory, - output_directory=self.output_directory, - ) - - @property - def downloader_class(self) -> Type[Downloader]: - """ - Returns - ------- - This subscription's downloader class - """ - return self.__preset_options.downloader - - @property - def downloader_options(self) -> DownloaderValidator: - """ - Returns - ------- - The download options for this subscription's downloader - """ - return self.__preset_options.downloader_options - - @property - def plugins(self) -> PresetPlugins: - """ - Returns - ------- - List of tuples containing (plugin class, plugin options) - """ - return self.__preset_options.plugins - - @property - def ytdl_options(self) -> YTDLOptions: - """ - Returns - ------- - YTDL options for this subscription - """ - return self.__preset_options.ytdl_options - - @property - def output_options(self) -> OutputOptions: - """ - Returns - ------- - The output options defined for this subscription - """ - return self.__preset_options.output_options - - @property - def overrides(self) -> Overrides: - """ - Returns - ------- - The overrides defined for this subscription - """ - return self.__preset_options.overrides - - @property - def working_directory(self) -> str: - """ - Returns - ------- - The directory that the downloader saves files to - """ - return str(Path(self.__config_options.working_directory) / Path(self.name)) - - @property - def output_directory(self) -> str: - """ - Returns - ------- - The formatted output directory - """ - return self.overrides.apply_formatter(formatter=self.output_options.output_directory) - - @property - def maintain_download_archive(self) -> bool: - """ - Returns - ------- - Whether to maintain a download archive - """ - return ( - self.output_options.maintain_download_archive - and self.downloader_class.supports_download_archive - ) - - def _move_entry_files_to_output_directory( - self, - dry_run: bool, - entry: Entry, - entry_metadata: Optional[FileMetadata] = None, - ): - """ - Helper function to move the media file and optionally thumbnail file to the output directory - for a single entry. - - Parameters - ---------- - dry_run - Whether this session is a dry-run or not - entry: - The entry with files to move - entry_metadata - Optional. Metadata to record to the transaction log for this entry - """ - # Move the file after all direct file modifications are complete - output_file_name = self.overrides.apply_formatter( - formatter=self.output_options.file_name, entry=entry - ) - self._enhanced_download_archive.save_file_to_output_directory( - file_name=entry.get_download_file_name(), - file_metadata=entry_metadata, - output_file_name=output_file_name, - entry=entry, - ) - - # TODO: see if entry even has a thumbnail - if self.output_options.thumbnail_name: - output_thumbnail_name = self.overrides.apply_formatter( - formatter=self.output_options.thumbnail_name, entry=entry - ) - - # We always convert entry thumbnails to jpgs, and is performed here - if not dry_run: - convert_download_thumbnail(entry=entry) - - self._enhanced_download_archive.save_file_to_output_directory( - file_name=entry.get_download_thumbnail_name(), - output_file_name=output_thumbnail_name, - entry=entry, - ) - - @contextlib.contextmanager - def _prepare_working_directory(self): - """ - Context manager to create all directories to the working directory. Deletes the entire - working directory when cleaning up. - """ - os.makedirs(self.working_directory, exist_ok=True) - - try: - yield - finally: - shutil.rmtree(self.working_directory) - - @contextlib.contextmanager - def _maintain_archive_file(self): - """ - Context manager to initialize the enhanced download archive - """ - if self.maintain_download_archive: - self._enhanced_download_archive.prepare_download_archive() - - yield - - # If output options maintains stale file deletion, perform the delete here prior to saving - # the download archive - if self.maintain_download_archive: - date_range_to_keep = to_date_range( - before=self.output_options.keep_files_before, - after=self.output_options.keep_files_after, - overrides=self.overrides, - ) - if date_range_to_keep: - self._enhanced_download_archive.remove_stale_files(date_range=date_range_to_keep) - - self._enhanced_download_archive.save_download_mappings() - - @contextlib.contextmanager - def _subscription_download_context_managers(self) -> None: - with ( - self._prepare_working_directory(), - self._maintain_archive_file(), - ): - yield - - def _initialize_plugins(self) -> List[Plugin]: - """ - Returns - ------- - List of plugins defined in the subscription, initialized and ready to use. - """ - plugins: List[Plugin] = [] - for plugin_type, plugin_options in self.plugins.zipped(): - plugin = plugin_type( - plugin_options=plugin_options, - overrides=self.overrides, - enhanced_download_archive=self._enhanced_download_archive, - ) - - plugins.append(plugin) - - return plugins - - def _post_process_entry( - self, plugins: List[Plugin], dry_run: bool, entry: Entry, entry_metadata: FileMetadata - ): - # Post-process the entry with all plugins - for plugin in sorted(plugins, key=lambda _plugin: _plugin.priority.post_process): - optional_plugin_entry_metadata = plugin.post_process_entry(entry) - if optional_plugin_entry_metadata: - entry_metadata.extend(optional_plugin_entry_metadata) - - # Then, move it to the output directory - self._move_entry_files_to_output_directory( - dry_run=dry_run, entry=entry, entry_metadata=entry_metadata - ) - - # Re-save the download archive after each entry is moved to the output directory - if self.maintain_download_archive: - self._enhanced_download_archive.save_download_mappings() - - def _process_entry( - self, plugins: List[Plugin], dry_run: bool, entry: Entry, entry_metadata: FileMetadata - ) -> None: - # First, modify the entry with all plugins - for plugin in sorted(plugins, key=lambda _plugin: _plugin.priority.modify_entry): - # Return if it is None, it is indicated to not process any further - if (entry := plugin.modify_entry(entry)) is None: - return - - self._post_process_entry( - plugins=plugins, dry_run=dry_run, entry=entry, entry_metadata=entry_metadata - ) - - def _process_split_entry( - self, split_plugin: Plugin, plugins: List[Plugin], dry_run: bool, entry: Entry - ) -> None: - plugins_pre_split = sorted( - [plugin for plugin in plugins if not plugin.priority.modify_entry_after_split], - key=lambda _plugin: _plugin.priority.modify_entry, - ) - - plugins_post_split = sorted( - [plugin for plugin in plugins if plugin.priority.modify_entry_after_split], - key=lambda _plugin: _plugin.priority.modify_entry, - ) - - # First, modify the entry with pre_split plugins - for plugin in plugins_pre_split: - # Return if it is None, it is indicated to not process any further - if (entry := plugin.modify_entry(entry)) is None: - return - - # Then, perform the split - for split_entry, split_entry_metadata in split_plugin.split(entry=entry): - - for plugin in plugins_post_split: - # Return if it is None, it is indicated to not process any further. - # Break out of the plugin loop - if (split_entry := plugin.modify_entry(split_entry)) is None: - break - - # If split_entry is None from modify_entry, do not post process - if split_entry: - self._process_entry( - plugins=plugins, - dry_run=dry_run, - entry=split_entry, - entry_metadata=split_entry_metadata, - ) - - def download(self, dry_run: bool = False) -> FileHandlerTransactionLog: - """ - Performs the subscription download - - Parameters - ---------- - dry_run - If true, do not download any video/audio files or move anything to the output - directory. - """ - self._enhanced_download_archive.reinitialize(dry_run=dry_run) - plugins = self._initialize_plugins() - - ytdl_options_builder = SubscriptionYTDLOptions( - preset=self.__preset_options, - plugins=plugins, - enhanced_download_archive=self._enhanced_download_archive, - working_directory=self.working_directory, - dry_run=dry_run, - ).builder() - - with self._subscription_download_context_managers(): - downloader = self.downloader_class( - download_options=self.downloader_options, - enhanced_download_archive=self._enhanced_download_archive, - ytdl_options_builder=ytdl_options_builder, - ) - - for entry in downloader.download(): - entry_metadata = FileMetadata() - if isinstance(entry, tuple): - entry, entry_metadata = entry - - if split_plugin := _get_split_plugin(plugins): - self._process_split_entry( - split_plugin=split_plugin, plugins=plugins, dry_run=dry_run, entry=entry - ) - else: - self._process_entry( - plugins=plugins, dry_run=dry_run, entry=entry, entry_metadata=entry_metadata - ) - - downloader.post_download(overrides=self.overrides) - for plugin in plugins: - plugin.post_process_subscription() - - return self._enhanced_download_archive.get_file_handler_transaction_log() - +class Subscription(SubscriptionDownload): @classmethod def from_preset(cls, preset: Preset, config: ConfigFile) -> "Subscription": """ diff --git a/src/ytdl_sub/subscriptions/subscription_download.py b/src/ytdl_sub/subscriptions/subscription_download.py new file mode 100644 index 00000000..f4053179 --- /dev/null +++ b/src/ytdl_sub/subscriptions/subscription_download.py @@ -0,0 +1,271 @@ +import contextlib +import os +import shutil +from abc import ABC +from typing import List +from typing import Optional + +from ytdl_sub.entries.entry import Entry +from ytdl_sub.plugins.plugin import Plugin +from ytdl_sub.subscriptions.base_subscription import BaseSubscription +from ytdl_sub.subscriptions.subscription_ytdl_options import SubscriptionYTDLOptions +from ytdl_sub.utils.datetime import to_date_range +from ytdl_sub.utils.exceptions import ValidationException +from ytdl_sub.utils.file_handler import FileHandlerTransactionLog +from ytdl_sub.utils.file_handler import FileMetadata +from ytdl_sub.utils.thumbnail import convert_download_thumbnail + + +def _get_split_plugin(plugins: List[Plugin]) -> Optional[Plugin]: + split_plugins = [plugin for plugin in plugins if plugin.is_split_plugin] + + if len(split_plugins) == 1: + return split_plugins[0] + if len(split_plugins) > 1: + raise ValidationException("Can not use more than one split plugins at a time") + return None + + +class SubscriptionDownload(BaseSubscription, ABC): + """ + Handles the subscription download logic + """ + + def _move_entry_files_to_output_directory( + self, + dry_run: bool, + entry: Entry, + entry_metadata: Optional[FileMetadata] = None, + ): + """ + Helper function to move the media file and optionally thumbnail file to the output directory + for a single entry. + + Parameters + ---------- + dry_run + Whether this session is a dry-run or not + entry: + The entry with files to move + entry_metadata + Optional. Metadata to record to the transaction log for this entry + """ + # Move the file after all direct file modifications are complete + output_file_name = self.overrides.apply_formatter( + formatter=self.output_options.file_name, entry=entry + ) + self._enhanced_download_archive.save_file_to_output_directory( + file_name=entry.get_download_file_name(), + file_metadata=entry_metadata, + output_file_name=output_file_name, + entry=entry, + ) + + # TODO: see if entry even has a thumbnail + if self.output_options.thumbnail_name: + output_thumbnail_name = self.overrides.apply_formatter( + formatter=self.output_options.thumbnail_name, entry=entry + ) + + # We always convert entry thumbnails to jpgs, and is performed here + if not dry_run: + convert_download_thumbnail(entry=entry) + + self._enhanced_download_archive.save_file_to_output_directory( + file_name=entry.get_download_thumbnail_name(), + output_file_name=output_thumbnail_name, + entry=entry, + ) + + if self.output_options.info_json_name: + output_info_json_name = self.overrides.apply_formatter( + formatter=self.output_options.info_json_name, entry=entry + ) + + # if not dry-run, write the info json + if not dry_run: + entry.write_info_json() + + self._enhanced_download_archive.save_file_to_output_directory( + file_name=entry.get_download_info_json_name(), + output_file_name=output_info_json_name, + entry=entry, + ) + + @contextlib.contextmanager + def _prepare_working_directory(self): + """ + Context manager to create all directories to the working directory. Deletes the entire + working directory when cleaning up. + """ + os.makedirs(self.working_directory, exist_ok=True) + + try: + yield + finally: + shutil.rmtree(self.working_directory) + + @contextlib.contextmanager + def _maintain_archive_file(self): + """ + Context manager to initialize the enhanced download archive + """ + if self.maintain_download_archive: + self._enhanced_download_archive.prepare_download_archive() + + yield + + # If output options maintains stale file deletion, perform the delete here prior to saving + # the download archive + if self.maintain_download_archive: + date_range_to_keep = to_date_range( + before=self.output_options.keep_files_before, + after=self.output_options.keep_files_after, + overrides=self.overrides, + ) + if date_range_to_keep: + self._enhanced_download_archive.remove_stale_files(date_range=date_range_to_keep) + + self._enhanced_download_archive.save_download_mappings() + + @contextlib.contextmanager + def _subscription_download_context_managers(self) -> None: + with ( + self._prepare_working_directory(), + self._maintain_archive_file(), + ): + yield + + def _initialize_plugins(self) -> List[Plugin]: + """ + Returns + ------- + List of plugins defined in the subscription, initialized and ready to use. + """ + plugins: List[Plugin] = [] + for plugin_type, plugin_options in self.plugins.zipped(): + plugin = plugin_type( + plugin_options=plugin_options, + overrides=self.overrides, + enhanced_download_archive=self._enhanced_download_archive, + ) + + plugins.append(plugin) + + return plugins + + def _post_process_entry( + self, plugins: List[Plugin], dry_run: bool, entry: Entry, entry_metadata: FileMetadata + ): + # Post-process the entry with all plugins + for plugin in sorted(plugins, key=lambda _plugin: _plugin.priority.post_process): + optional_plugin_entry_metadata = plugin.post_process_entry(entry) + if optional_plugin_entry_metadata: + entry_metadata.extend(optional_plugin_entry_metadata) + + # Then, move it to the output directory + self._move_entry_files_to_output_directory( + dry_run=dry_run, entry=entry, entry_metadata=entry_metadata + ) + + # Re-save the download archive after each entry is moved to the output directory + if self.maintain_download_archive: + self._enhanced_download_archive.save_download_mappings() + + def _process_entry( + self, plugins: List[Plugin], dry_run: bool, entry: Entry, entry_metadata: FileMetadata + ) -> None: + # First, modify the entry with all plugins + for plugin in sorted(plugins, key=lambda _plugin: _plugin.priority.modify_entry): + # Return if it is None, it is indicated to not process any further + if (entry := plugin.modify_entry(entry)) is None: + return + + self._post_process_entry( + plugins=plugins, dry_run=dry_run, entry=entry, entry_metadata=entry_metadata + ) + + def _process_split_entry( + self, split_plugin: Plugin, plugins: List[Plugin], dry_run: bool, entry: Entry + ) -> None: + plugins_pre_split = sorted( + [plugin for plugin in plugins if not plugin.priority.modify_entry_after_split], + key=lambda _plugin: _plugin.priority.modify_entry, + ) + + plugins_post_split = sorted( + [plugin for plugin in plugins if plugin.priority.modify_entry_after_split], + key=lambda _plugin: _plugin.priority.modify_entry, + ) + + # First, modify the entry with pre_split plugins + for plugin in plugins_pre_split: + # Return if it is None, it is indicated to not process any further + if (entry := plugin.modify_entry(entry)) is None: + return + + # Then, perform the split + for split_entry, split_entry_metadata in split_plugin.split(entry=entry): + + for plugin in plugins_post_split: + # Return if it is None, it is indicated to not process any further. + # Break out of the plugin loop + if (split_entry := plugin.modify_entry(split_entry)) is None: + break + + # If split_entry is None from modify_entry, do not post process + if split_entry: + self._process_entry( + plugins=plugins, + dry_run=dry_run, + entry=split_entry, + entry_metadata=split_entry_metadata, + ) + + def download(self, dry_run: bool = False) -> FileHandlerTransactionLog: + """ + Performs the subscription download + + Parameters + ---------- + dry_run + If true, do not download any video/audio files or move anything to the output + directory. + """ + self._enhanced_download_archive.reinitialize(dry_run=dry_run) + plugins = self._initialize_plugins() + + ytdl_options_builder = SubscriptionYTDLOptions( + preset=self._preset_options, + plugins=plugins, + enhanced_download_archive=self._enhanced_download_archive, + working_directory=self.working_directory, + dry_run=dry_run, + ).builder() + + with self._subscription_download_context_managers(): + downloader = self.downloader_class( + download_options=self.downloader_options, + enhanced_download_archive=self._enhanced_download_archive, + ytdl_options_builder=ytdl_options_builder, + ) + + for entry in downloader.download(): + entry_metadata = FileMetadata() + if isinstance(entry, tuple): + entry, entry_metadata = entry + + if split_plugin := _get_split_plugin(plugins): + self._process_split_entry( + split_plugin=split_plugin, plugins=plugins, dry_run=dry_run, entry=entry + ) + else: + self._process_entry( + plugins=plugins, dry_run=dry_run, entry=entry, entry_metadata=entry_metadata + ) + + downloader.post_download(overrides=self.overrides) + for plugin in plugins: + plugin.post_process_subscription() + + return self._enhanced_download_archive.get_file_handler_transaction_log() diff --git a/tests/e2e/expected_download.py b/tests/e2e/expected_download.py index 657422c5..1c996dee 100644 --- a/tests/e2e/expected_download.py +++ b/tests/e2e/expected_download.py @@ -54,6 +54,7 @@ class ExpectedDownloads: ): """ Assert each expected file exists and that its respective md5 hash matches. + Ignores .info.json files by default since metadata can easily change """ if ignore_md5_hashes_for is None: ignore_md5_hashes_for = [] @@ -66,12 +67,11 @@ class ExpectedDownloads: assert len(relative_file_paths) == self.file_count, "Mismatch in number of created files" for expected_download in self.expected_downloads: - full_path = Path(relative_directory) / expected_download.path - assert os.path.isfile( - full_path - ), f"Expected {str(expected_download.path)} to be a file but it is not" + path = str(expected_download.path) + full_path = Path(relative_directory) / path + assert os.path.isfile(full_path), f"Expected {path} to be a file but it is not" - if str(expected_download.path) in ignore_md5_hashes_for: + if path in ignore_md5_hashes_for or path.endswith(".info.json"): continue md5_hash = _get_file_md5_hash(full_file_path=full_path) diff --git a/tests/e2e/resources/expected_downloads_summaries/plugins/date_range/test_channel_recent.json b/tests/e2e/resources/expected_downloads_summaries/plugins/date_range/test_channel_recent.json index 8890ede2..edc4e784 100644 --- a/tests/e2e/resources/expected_downloads_summaries/plugins/date_range/test_channel_recent.json +++ b/tests/e2e/resources/expected_downloads_summaries/plugins/date_range/test_channel_recent.json @@ -1,10 +1,12 @@ { - ".ytdl-sub-recent-download-archive.json": "756b60d7a6c47d8163e3283404493a8d", + ".ytdl-sub-recent-download-archive.json": "23520634f7908081f3d1333a1441a578", "Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer-thumb.jpg": "705ca4e0d99b37e9ecdf6bfe4b90c59b", + "Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer.info.json": "ad68ce82c78f1a0a757fc1fbd4d6b531", "Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer.mp4": "82f6ee7253e1dbb83ae7215af08ffacc", "Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer.nfo": "368d68db0cbe9eb4f43ece0517445e82", "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id-thumb.jpg": "28d852ede73b879b9ebf9a061cfc7d46", "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.en.srt": "3d2c4e7f65d2ca5e96da38ce7eecfc4e", + "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.info.json": "b085dea1c06975464acc5bdc1b950e4c", "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.mp4": "e733b4cc385b953b08c8eb0f47e03c1e", "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.nfo": "d9114d43d87907b2afc06eb089a8ac0a", "fanart.jpg": "129c6639b47299bc48062f0365e670ee", diff --git a/tests/e2e/resources/expected_downloads_summaries/plugins/date_range/test_channel_rolling_recent.json b/tests/e2e/resources/expected_downloads_summaries/plugins/date_range/test_channel_rolling_recent.json index 9e2d28bf..ad684ad2 100644 --- a/tests/e2e/resources/expected_downloads_summaries/plugins/date_range/test_channel_rolling_recent.json +++ b/tests/e2e/resources/expected_downloads_summaries/plugins/date_range/test_channel_rolling_recent.json @@ -1,7 +1,8 @@ { - ".ytdl-sub-recent-download-archive.json": "68e164a35d1541ce761a6d7fef19ee08", + ".ytdl-sub-recent-download-archive.json": "3bbf72c014d055ecf672c8ea603140f7", "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id-thumb.jpg": "28d852ede73b879b9ebf9a061cfc7d46", "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.en.srt": "3d2c4e7f65d2ca5e96da38ce7eecfc4e", + "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.info.json": "b085dea1c06975464acc5bdc1b950e4c", "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.mp4": "e733b4cc385b953b08c8eb0f47e03c1e", "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.nfo": "d9114d43d87907b2afc06eb089a8ac0a", "fanart.jpg": "129c6639b47299bc48062f0365e670ee", diff --git a/tests/e2e/resources/expected_downloads_summaries/plugins/split_by_chapters_video.json b/tests/e2e/resources/expected_downloads_summaries/plugins/split_by_chapters_video.json index dbaab7d0..bd62db62 100644 --- a/tests/e2e/resources/expected_downloads_summaries/plugins/split_by_chapters_video.json +++ b/tests/e2e/resources/expected_downloads_summaries/plugins/split_by_chapters_video.json @@ -1,4 +1,15 @@ { + "01. Intro (Feat. Racheal Ofori & Barney Artist).info.json": "4ec926da9b74eee3f9bf9e1895d3af30", + "02. Answers (Feat. Rick David & Kaya Thomas - Dyke).info.json": "ae183114899d0b7bac8bfa01a09f6b36", + "03. Blaze (Feat. Kaya Thomas - Dyke).info.json": "86bff845b087dfc240d63a65afed9117", + "04. What If (Interlude).info.json": "d2e92735fcb8eaccaf2e28c8f2a0ab1f", + "05. No Peace (Feat. Tom Misch).info.json": "ed2a9ec8a833dd90bb6681d62c68ff3a", + "06. Closer (Feat. Lester Duval).info.json": "aa29efd172bb6afd27e948761087d01e", + "07. Delusions: Rumination (Interlude) (Feat. Racheal Ofori).info.json": "79c0626f28d0a02074f14eac90e0670e", + "08. Dreams (Feat. Carmody).info.json": "c7bb7c910c0d74492ef62e4a32922f17", + "09. Dreaming (Interlude) (Feat. Racheal Ofori).info.json": "077efa0aa1d25afb05fb3285f139b77b", + "10. Hopeful (Feat. Jordan Rakei).info.json": "4541ba99f9b683f34652a60bc3c34ff5", + "11. Sunrise (Pillows) (Feat. Emmavie).info.json": "41a7ceb520a7d9e6736cba3f4be6a9c4", "Alfa Mist - Nocturne [Full Album]/01 - 01. Intro (Feat. Racheal Ofori & Barney Artist).mp3": "ddc24257729f24055bf1b8dc06f8224c", "Alfa Mist - Nocturne [Full Album]/02 - 02. Answers (Feat. Rick David & Kaya Thomas - Dyke).mp3": "10dd7f13c469bd51ffcf3f8ff3ed3d69", "Alfa Mist - Nocturne [Full Album]/03 - 03. Blaze (Feat. Kaya Thomas - Dyke).mp3": "376722aaf08d1ef6dcba0aaf7a3b7a79", diff --git a/tests/e2e/resources/expected_downloads_summaries/plugins/split_by_chapters_with_regex_no_chapters_video_pass.txt b/tests/e2e/resources/expected_downloads_summaries/plugins/split_by_chapters_with_regex_no_chapters_video_pass.txt index 1df20954..0657054e 100644 --- a/tests/e2e/resources/expected_downloads_summaries/plugins/split_by_chapters_with_regex_no_chapters_video_pass.txt +++ b/tests/e2e/resources/expected_downloads_summaries/plugins/split_by_chapters_with_regex_no_chapters_video_pass.txt @@ -1,4 +1,5 @@ { + "Oblivion Mod \"Falcor\" p.1.info.json": "358e43cb1c00e7f4c960690994092e9e", "Oblivion Mod \"Falcor\" p.1/01 - Oblivion Mod \"Falcor\" p.1.mp3": "703ffb93964ac025ee66221b98ee4d49", "Oblivion Mod \"Falcor\" p.1/folder.jpg": "fb95b510681676e81c321171fc23143e" } \ No newline at end of file diff --git a/tests/e2e/resources/expected_downloads_summaries/plugins/split_by_chapters_with_regex_video.json b/tests/e2e/resources/expected_downloads_summaries/plugins/split_by_chapters_with_regex_video.json index ddc24bc7..18eb59df 100644 --- a/tests/e2e/resources/expected_downloads_summaries/plugins/split_by_chapters_with_regex_video.json +++ b/tests/e2e/resources/expected_downloads_summaries/plugins/split_by_chapters_with_regex_video.json @@ -1,4 +1,13 @@ { + "Answers (Feat. Rick David & Kaya Thomas - Dyke).info.json": "b4d6ae81fd1313c5ce962e88ab027782", + "Blaze (Feat. Kaya Thomas - Dyke).info.json": "05857a128e229ac9b364e8f5f09ff4b4", + "Closer (Feat. Lester Duval).info.json": "00c3e84f0b5506051ed31071208ff33d", + "Delusions: Rumination (Interlude) (Feat. Racheal Ofori).info.json": "b360033980fda9bcc3056aed2c3265b1", + "Dreaming (Interlude) (Feat. Racheal Ofori).info.json": "fd3df9675d2b01ad88a6d12d75ab526e", + "Dreams (Feat. Carmody).info.json": "402fb9066d25db35f801a6b94524bb38", + "Hopeful (Feat. Jordan Rakei).info.json": "ab750e7c550aac184f3ef82c3cf64212", + "Intro (Feat. Racheal Ofori & Barney Artist).info.json": "0777ecaaac9ffb1c4df3989e618dedf7", + "No Peace (Feat. Tom Misch).info.json": "0de13987489e4a8f9a94dd91dcbc4cf5", "Nocturne/01 - Intro (Feat. Racheal Ofori & Barney Artist).mp3": "15157be58e0f72485de1e7e10961321f", "Nocturne/02 - Answers (Feat. Rick David & Kaya Thomas - Dyke).mp3": "28ff5e2dda45771f1c6d5265dd03095e", "Nocturne/03 - Blaze (Feat. Kaya Thomas - Dyke).mp3": "705d7fc1799c1a14aa0656bd6e2bf260", @@ -10,5 +19,7 @@ "Nocturne/09 - Dreaming (Interlude) (Feat. Racheal Ofori).mp3": "cd213379cf53a8c1e4eb9134da257cd8", "Nocturne/10 - Hopeful (Feat. Jordan Rakei).mp3": "ef7e06690ac849e1dd35771936d6ddb6", "Nocturne/11 - Sunrise (Pillows) (Feat. Emmavie).mp3": "56293fb70edc1ef7decc2d417d87ff1d", - "Nocturne/folder.jpg": "bd3685acc53072e591bae2505ecb0648" + "Nocturne/folder.jpg": "bd3685acc53072e591bae2505ecb0648", + "Sunrise (Pillows) (Feat. Emmavie).info.json": "09f9975e3355e2d5888c07900f54f895", + "What If (Interlude).info.json": "328c05aeb45892d7ad6368e81d0947a5" } \ No newline at end of file diff --git a/tests/e2e/resources/expected_downloads_summaries/plugins/test_audio_extract_playlist.json b/tests/e2e/resources/expected_downloads_summaries/plugins/test_audio_extract_playlist.json index 28b65c30..b357b31a 100644 --- a/tests/e2e/resources/expected_downloads_summaries/plugins/test_audio_extract_playlist.json +++ b/tests/e2e/resources/expected_downloads_summaries/plugins/test_audio_extract_playlist.json @@ -1,5 +1,8 @@ { + "Jesse's Minecraft Server [Trailer - Feb.1].info.json": "0a484e88b6d37b20017615aa6df3b5d9", "Jesse's Minecraft Server [Trailer - Feb.1].ogg": "16f66f1d81541a1f18b62bc08ad01d16", + "Jesse's Minecraft Server [Trailer - Feb.27].info.json": "807c9f35c97beac21d8b3ca64df50860", "Jesse's Minecraft Server [Trailer - Feb.27].ogg": "6f322d842a1e43b4c9981b42423d9b4c", + "Jesse's Minecraft Server [Trailer - Mar.21].info.json": "b87e89258f04fb3acb669e5b1e0fa468", "Jesse's Minecraft Server [Trailer - Mar.21].ogg": "fe1dc3361a102661c27020d5b95a2a81" } \ No newline at end of file diff --git a/tests/e2e/resources/expected_downloads_summaries/plugins/test_audio_extract_single.json b/tests/e2e/resources/expected_downloads_summaries/plugins/test_audio_extract_single.json index f6a639ae..03192e80 100644 --- a/tests/e2e/resources/expected_downloads_summaries/plugins/test_audio_extract_single.json +++ b/tests/e2e/resources/expected_downloads_summaries/plugins/test_audio_extract_single.json @@ -1,3 +1,4 @@ { + "YouTube Rewind 2019: For the Record | #YouTubeRewind.info.json": "ebc30f897906fa0f04738089c7e7715d", "YouTube Rewind 2019: For the Record | #YouTubeRewind.mp3": "3a156b122bd79c956cce5079d3530cc3" } \ No newline at end of file diff --git a/tests/e2e/resources/expected_downloads_summaries/plugins/test_chapters_from_ts_with_subs.json b/tests/e2e/resources/expected_downloads_summaries/plugins/test_chapters_from_ts_with_subs.json index efcc7060..ccae4743 100644 --- a/tests/e2e/resources/expected_downloads_summaries/plugins/test_chapters_from_ts_with_subs.json +++ b/tests/e2e/resources/expected_downloads_summaries/plugins/test_chapters_from_ts_with_subs.json @@ -1,5 +1,6 @@ { "JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case-thumb.jpg": "b5353a824a4800cc26f884e3025ed969", + "JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.info.json": "89d611e4f61a72204b9658acd492468d", "JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.mp4": "2d40822bf4c0527f9080f00357b26ce0", "JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.nfo": "b9bd35e4f260c728774d8dd31f83637c" } \ No newline at end of file diff --git a/tests/e2e/resources/expected_downloads_summaries/plugins/test_chapters_sb_and_embedded_subs.json b/tests/e2e/resources/expected_downloads_summaries/plugins/test_chapters_sb_and_embedded_subs.json index 32f7cda8..68ad2956 100644 --- a/tests/e2e/resources/expected_downloads_summaries/plugins/test_chapters_sb_and_embedded_subs.json +++ b/tests/e2e/resources/expected_downloads_summaries/plugins/test_chapters_sb_and_embedded_subs.json @@ -1,5 +1,6 @@ { "JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case-thumb.jpg": "b5353a824a4800cc26f884e3025ed969", + "JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.info.json": "c0ad8fd87d9a70bd66ce069ae0acd490", "JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.mp4": "6f0bac1c364ff3bb13d3e8a955aaa002", "JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.nfo": "b9bd35e4f260c728774d8dd31f83637c" } \ No newline at end of file diff --git a/tests/e2e/resources/expected_downloads_summaries/plugins/test_subtitles_embedded.json b/tests/e2e/resources/expected_downloads_summaries/plugins/test_subtitles_embedded.json index 90f8b68f..00c0f979 100644 --- a/tests/e2e/resources/expected_downloads_summaries/plugins/test_subtitles_embedded.json +++ b/tests/e2e/resources/expected_downloads_summaries/plugins/test_subtitles_embedded.json @@ -1,5 +1,6 @@ { "JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind-thumb.jpg": "50ee47c80f679029f5d3503bb91b045a", + "JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.info.json": "eedd73b78d8a9d3b129049e87eb17b6c", "JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.mp4": "8562853314b75c1e47abd4f5ba97315c", "JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.nfo": "c64964fab07574080e5da3242e3bfd48" } \ No newline at end of file diff --git a/tests/e2e/resources/expected_downloads_summaries/plugins/test_subtitles_embedded_and_file.json b/tests/e2e/resources/expected_downloads_summaries/plugins/test_subtitles_embedded_and_file.json index a71b8498..c376b9d0 100644 --- a/tests/e2e/resources/expected_downloads_summaries/plugins/test_subtitles_embedded_and_file.json +++ b/tests/e2e/resources/expected_downloads_summaries/plugins/test_subtitles_embedded_and_file.json @@ -2,6 +2,7 @@ "JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind-thumb.jpg": "50ee47c80f679029f5d3503bb91b045a", "JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.de.srt": "b343c3bb9257b7ee7ba38f570a115b37", "JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.en.srt": "fe8c6ee92cae6e059fd80fd61691adbe", + "JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.info.json": "577038a7e5a9833ebbd33562f5d6b376", "JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.mp4": "8562853314b75c1e47abd4f5ba97315c", "JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.nfo": "c64964fab07574080e5da3242e3bfd48" } \ No newline at end of file diff --git a/tests/e2e/resources/expected_downloads_summaries/soundcloud/test_soundcloud_discography.json b/tests/e2e/resources/expected_downloads_summaries/soundcloud/test_soundcloud_discography.json index f3ce14cd..47dcb24d 100644 --- a/tests/e2e/resources/expected_downloads_summaries/soundcloud/test_soundcloud_discography.json +++ b/tests/e2e/resources/expected_downloads_summaries/soundcloud/test_soundcloud_discography.json @@ -1,19 +1,32 @@ { - ".ytdl-sub-jb-download-archive.json": "1a99156e9ece62539fb2608416a07200", + ".ytdl-sub-jb-download-archive.json": "1114f07090dfb35eea6848efeaf9755a", + "j_b/[2021] Baby Santana's Dorian Groove/01 - Baby Santana's Dorian Groove.info.json": "8f736aac8bbaa732e89efdcb61c3bc3d", "j_b/[2021] Baby Santana's Dorian Groove/01 - Baby Santana's Dorian Groove.mp3": "bffbd558e12c6a9e029dc136a88342c4", "j_b/[2021] Baby Santana's Dorian Groove/folder.jpg": "967892be44b8c47e1be73f055a7c6f08", + "j_b/[2021] Purple Clouds/01 - Purple Clouds.info.json": "da0a923a6d0272e4dc726ac997360b28", "j_b/[2021] Purple Clouds/01 - Purple Clouds.mp3": "038db58aebe2ba875b733932b42a94d6", "j_b/[2021] Purple Clouds/folder.jpg": "967892be44b8c47e1be73f055a7c6f08", + "j_b/[2022] Acoustic Treats/01 - 20160426 184214.info.json": "f952fe0830f106fac031d18022213892", "j_b/[2022] Acoustic Treats/01 - 20160426 184214.mp3": "e145f0a2f6012768280c38655ca58065", + "j_b/[2022] Acoustic Treats/02 - 20160502 123150.info.json": "63f5a211448f95c78b866f048e4f2fc9", "j_b/[2022] Acoustic Treats/02 - 20160502 123150.mp3": "60c8b8817a197a13e4bb90903af612c5", + "j_b/[2022] Acoustic Treats/03 - 20160504 143832.info.json": "a363365339ad3ab5139a51a6a6ed256d", "j_b/[2022] Acoustic Treats/03 - 20160504 143832.mp3": "8265b7e4f79878af877bc6ecd9757efe", + "j_b/[2022] Acoustic Treats/04 - 20160601 221234.info.json": "9a1901fbd9761e29173b0fda5654e908", "j_b/[2022] Acoustic Treats/04 - 20160601 221234.mp3": "accf46b76891d2954b893d0f91d82816", + "j_b/[2022] Acoustic Treats/05 - 20160601 222440.info.json": "886716e85228d46ce981aa0ba7bc2947", "j_b/[2022] Acoustic Treats/05 - 20160601 222440.mp3": "e1f584f523336160d5c1104a61de77f3", + "j_b/[2022] Acoustic Treats/06 - 20170604 190236.info.json": "d23e769c83bc3303709b64432400a60d", "j_b/[2022] Acoustic Treats/06 - 20170604 190236.mp3": "f6885b25901177f0357649afe97328cc", + "j_b/[2022] Acoustic Treats/07 - 20170612 193646.info.json": "04f467b4903aa9f090dc705db432edf2", "j_b/[2022] Acoustic Treats/07 - 20170612 193646.mp3": "fa057f221cbe4cf2442cd2fdb960743e", + "j_b/[2022] Acoustic Treats/08 - 20170628 215206.info.json": "92f027ec29f445566242a82c27ed76ad", "j_b/[2022] Acoustic Treats/08 - 20170628 215206.mp3": "7794ae812c64580e2ac8fc457d5cc85f", + "j_b/[2022] Acoustic Treats/09 - Finding Home.info.json": "f7458eaab93903e1568734ea1b33ee21", "j_b/[2022] Acoustic Treats/09 - Finding Home.mp3": "adbf02eddb2090c008eb497d13ff84b9", + "j_b/[2022] Acoustic Treats/10 - Shallow Water WIP.info.json": "553e676f982b364493fd323e6d886e05", "j_b/[2022] Acoustic Treats/10 - Shallow Water WIP.mp3": "65bb10c84366c71498161734f953e93d", + "j_b/[2022] Acoustic Treats/11 - Untold History.info.json": "8abbad5d0821ed6c64dc632b49a133ec", "j_b/[2022] Acoustic Treats/11 - Untold History.mp3": "6904b2918e5dc38d9a9f72d967eb74bf", "j_b/[2022] Acoustic Treats/folder.jpg": "967892be44b8c47e1be73f055a7c6f08" } \ No newline at end of file diff --git a/tests/e2e/resources/expected_downloads_summaries/youtube/test_channel_full.json b/tests/e2e/resources/expected_downloads_summaries/youtube/test_channel_full.json index d1ae9dac..a49364f2 100644 --- a/tests/e2e/resources/expected_downloads_summaries/youtube/test_channel_full.json +++ b/tests/e2e/resources/expected_downloads_summaries/youtube/test_channel_full.json @@ -1,40 +1,52 @@ { - ".ytdl-sub-pz-download-archive.json": "f0f692ef29653ca8d0af556415bfb065", + ".ytdl-sub-pz-download-archive.json": "70615451318cdb5e018e007c77893a39", "Season 2010/s2010.e0813 - Oblivion Mod "Falcor" p.1-thumb.jpg": "fb95b510681676e81c321171fc23143e", + "Season 2010/s2010.e0813 - Oblivion Mod "Falcor" p.1.info.json": "5d16096bc4256239932db2c2d98161a3", "Season 2010/s2010.e0813 - Oblivion Mod "Falcor" p.1.mp4": "931a705864c57d21d6fedebed4af6bbc", "Season 2010/s2010.e0813 - Oblivion Mod "Falcor" p.1.nfo": "2d0738094d8e649eaebbab16fd647da1", "Season 2010/s2010.e1202 - Oblivion Mod "Falcor" p.2-thumb.jpg": "8b32ee9c037fa669e444a0ac181525a1", + "Season 2010/s2010.e1202 - Oblivion Mod "Falcor" p.2.info.json": "514d2c3eab500f9541910d7573cb495e", "Season 2010/s2010.e1202 - Oblivion Mod "Falcor" p.2.mp4": "d3469b4dca7139cb3dbc38712b6796bf", "Season 2010/s2010.e1202 - Oblivion Mod "Falcor" p.2.nfo": "5c258f9e54854ef292ce3c58331da110", "Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1]-thumb.jpg": "b232d253df621aa770b780c1301d364d", + "Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].info.json": "f9ccc0b104551ecd7b737451051118aa", "Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].mp4": "e66287b9832277b6a4d1554e29d9fdcc", "Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].nfo": "abb3ac33366cc3b86d0467c8fb80a323", "Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27]-thumb.jpg": "d17c379ea8b362f5b97c6b213b0342cb", + "Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].info.json": "6ad149bea780198512d73f075722ef82", "Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].mp4": "04ab5cb3cc12325d0c96a7cd04a8b91d", "Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].nfo": "46190954652c9d9812e061fc0c9e1d92", "Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21]-thumb.jpg": "e7830aa8a64b0cde65ba3f7e5fc56530", + "Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].info.json": "d040165f8ebc346c202605b19ed8e46b", "Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].mp4": "025de6099a5c98e6397153c7a62d517d", "Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].nfo": "30993fa8e00a0e370b4db244f3da8f7d", "Season 2011/s2011.e0529 - Project Zombie |Official Trailer| (IP: mc.projectzombie.beastnode.net)-thumb.jpg": "c956192a379b3661595c9920972d4819", + "Season 2011/s2011.e0529 - Project Zombie |Official Trailer| (IP: mc.projectzombie.beastnode.net).info.json": "331af1c81b1bfa1df62179067a5f06b0", "Season 2011/s2011.e0529 - Project Zombie |Official Trailer| (IP: mc.projectzombie.beastnode.net).mp4": "3d9c19835b03355d6fd5d00cd59dbe5b", "Season 2011/s2011.e0529 - Project Zombie |Official Trailer| (IP: mc.projectzombie.beastnode.net).nfo": "11a0e8754c414875bcd454358683da5f", "Season 2011/s2011.e0630 - Project Zombie |Fin|-thumb.jpg": "00ed383591779ffe98291de60f198fe9", + "Season 2011/s2011.e0630 - Project Zombie |Fin|.info.json": "07d6b5e38b8e03cbe0f1ca795f266a43", "Season 2011/s2011.e0630 - Project Zombie |Fin|.mp4": "4971cb2d4fa29460361031f3fa8e1ea9", "Season 2011/s2011.e0630 - Project Zombie |Fin|.nfo": "a464b9c8c48a9a5d4776436d8108f8f5", "Season 2011/s2011.e1121 - Skyrim 'Ultra HD w⧸Mods' [PC]-thumb.jpg": "1718599d5189c65f7d8cf6acfa5ea851", + "Season 2011/s2011.e1121 - Skyrim 'Ultra HD w⧸Mods' [PC].info.json": "e804c82258849767d5f006627e66ac8f", "Season 2011/s2011.e1121 - Skyrim 'Ultra HD w⧸Mods' [PC].mp4": "55e9b0add08c48c9c66105da0def2426", "Season 2011/s2011.e1121 - Skyrim 'Ultra HD w⧸Mods' [PC].nfo": "3562934ab9a5e802d955eda24ad355de", "Season 2012/s2012.e0123 - Project Zombie |Map Trailer|-thumb.jpg": "54ebe9df801b278fdd17b21afa8373a6", + "Season 2012/s2012.e0123 - Project Zombie |Map Trailer|.info.json": "d81b260f37fbf8499d6ba716f5d1c42a", "Season 2012/s2012.e0123 - Project Zombie |Map Trailer|.mp4": "65e4ce53ed5ec4139995469f99477a50", "Season 2012/s2012.e0123 - Project Zombie |Map Trailer|.nfo": "5e810d839be90dab579400a6177f90b3", "Season 2013/s2013.e0719 - Project Zombie Rewind |Trailer|-thumb.jpg": "e29d49433175de8a761af35c5307791f", + "Season 2013/s2013.e0719 - Project Zombie Rewind |Trailer|.info.json": "4e450b92e57f8c99033b49e3326cdf72", "Season 2013/s2013.e0719 - Project Zombie Rewind |Trailer|.mp4": "18620a8257a686beda65e54add4d4cd1", "Season 2013/s2013.e0719 - Project Zombie Rewind |Trailer|.nfo": "83772bec917bb5d71e1ca0c061c1ec78", "Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer-thumb.jpg": "705ca4e0d99b37e9ecdf6bfe4b90c59b", + "Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer.info.json": "01a181a123d1b92d016dced5615ca67a", "Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer.mp4": "82f6ee7253e1dbb83ae7215af08ffacc", "Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer.nfo": "368d68db0cbe9eb4f43ece0517445e82", "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id-thumb.jpg": "28d852ede73b879b9ebf9a061cfc7d46", "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.en.srt": "3d2c4e7f65d2ca5e96da38ce7eecfc4e", + "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.info.json": "2ca573a5eb58e92df951be0a05e8e49c", "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.mp4": "e733b4cc385b953b08c8eb0f47e03c1e", "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.nfo": "d9114d43d87907b2afc06eb089a8ac0a", "fanart.jpg": "129c6639b47299bc48062f0365e670ee", diff --git a/tests/e2e/resources/expected_downloads_summaries/youtube/test_merge_playlist.json b/tests/e2e/resources/expected_downloads_summaries/youtube/test_merge_playlist.json index 878f5792..b0db8a93 100644 --- a/tests/e2e/resources/expected_downloads_summaries/youtube/test_merge_playlist.json +++ b/tests/e2e/resources/expected_downloads_summaries/youtube/test_merge_playlist.json @@ -1,5 +1,6 @@ { "JMC - Jesse's Minecraft Server-thumb.jpg": "a3f1910f9c51f6442f845a528e190829", + "JMC - Jesse's Minecraft Server.info.json": "604a3e1f5b0f27524772a90869fbbe06", "JMC - Jesse's Minecraft Server.mkv": "21f246b1c922e11add509ea26c43c53d", "JMC - Jesse's Minecraft Server.nfo": "d16396c60b63c06a4f2c9239553bdf61" } \ No newline at end of file diff --git a/tests/e2e/resources/expected_downloads_summaries/youtube/test_playlist.json b/tests/e2e/resources/expected_downloads_summaries/youtube/test_playlist.json index e00ef28a..6e62ce00 100644 --- a/tests/e2e/resources/expected_downloads_summaries/youtube/test_playlist.json +++ b/tests/e2e/resources/expected_downloads_summaries/youtube/test_playlist.json @@ -1,12 +1,15 @@ { - ".ytdl-sub-music_video_playlist_test-download-archive.json": "9f785c29194a6ecfba6a6b4018763ddc", + ".ytdl-sub-music_video_playlist_test-download-archive.json": "25b8e44961343116436584e341c7fe9b", "JMC - Jesse's Minecraft Server [Trailer - Feb.1]-thumb.jpg": "b232d253df621aa770b780c1301d364d", + "JMC - Jesse's Minecraft Server [Trailer - Feb.1].info.json": "7c870aea7df6733ddac1adc190797d6a", "JMC - Jesse's Minecraft Server [Trailer - Feb.1].mp4": "e66287b9832277b6a4d1554e29d9fdcc", "JMC - Jesse's Minecraft Server [Trailer - Feb.1].nfo": "f8fd72bb97ed03938487494ad9094ca0", "JMC - Jesse's Minecraft Server [Trailer - Feb.27]-thumb.jpg": "d17c379ea8b362f5b97c6b213b0342cb", + "JMC - Jesse's Minecraft Server [Trailer - Feb.27].info.json": "e1d9ce4f91d4657468bb10de829a76e8", "JMC - Jesse's Minecraft Server [Trailer - Feb.27].mp4": "04ab5cb3cc12325d0c96a7cd04a8b91d", "JMC - Jesse's Minecraft Server [Trailer - Feb.27].nfo": "6de4d997cfb300356072b4ebb09cbe38", "JMC - Jesse's Minecraft Server [Trailer - Mar.21]-thumb.jpg": "e7830aa8a64b0cde65ba3f7e5fc56530", + "JMC - Jesse's Minecraft Server [Trailer - Mar.21].info.json": "c601d4f904e45c8cc73e78c5873eba08", "JMC - Jesse's Minecraft Server [Trailer - Mar.21].mp4": "025de6099a5c98e6397153c7a62d517d", "JMC - Jesse's Minecraft Server [Trailer - Mar.21].nfo": "f000a6ed8caacb62a134a6ca81e3f308" } \ No newline at end of file diff --git a/tests/e2e/resources/expected_downloads_summaries/youtube/test_split_video.json b/tests/e2e/resources/expected_downloads_summaries/youtube/test_split_video.json index 82fbf921..60a8da02 100644 --- a/tests/e2e/resources/expected_downloads_summaries/youtube/test_split_video.json +++ b/tests/e2e/resources/expected_downloads_summaries/youtube/test_split_video.json @@ -6,15 +6,21 @@ "Project Zombie - 5-6.Part 4.mp4": "de9afd0b6fa5f845b086e2d4915f2f14", "Project Zombie - 6-6.Part 5.mp4": "d485c2a5df9a2d5bf9037a7a96a04d10", "Project Zombie - Intro-thumb.jpg": "fb95b510681676e81c321171fc23143e", + "Project Zombie - Intro.info.json": "0aa234ae04a218f18c9aa2eb605ff078", "Project Zombie - Intro.nfo": "3a89bd4707e64b66a22d13bb7f81bf16", "Project Zombie - Part 1-thumb.jpg": "fb95b510681676e81c321171fc23143e", + "Project Zombie - Part 1.info.json": "1d1a70bf1bd9753c7035c9069fb99859", "Project Zombie - Part 1.nfo": "a57a3a98d0b9db655bc4a792953ab96e", "Project Zombie - Part 2-thumb.jpg": "fb95b510681676e81c321171fc23143e", + "Project Zombie - Part 2.info.json": "2781ca7fae971ca7a2825a6f16f432aa", "Project Zombie - Part 2.nfo": "68921dd5386fd90e2c0640127dda5dc2", "Project Zombie - Part 3-thumb.jpg": "fb95b510681676e81c321171fc23143e", + "Project Zombie - Part 3.info.json": "2d79048f59070044e519ab68ef469d62", "Project Zombie - Part 3.nfo": "4198aec2d4cd70e4cb3946f10be205a7", "Project Zombie - Part 4-thumb.jpg": "fb95b510681676e81c321171fc23143e", + "Project Zombie - Part 4.info.json": "4074e8d1fa1c0fccf1fe55ba52cc46a1", "Project Zombie - Part 4.nfo": "8a87fa99c5ba5b11cd14c592a0b97dbb", "Project Zombie - Part 5-thumb.jpg": "fb95b510681676e81c321171fc23143e", + "Project Zombie - Part 5.info.json": "48b519b3867bafb51c8f463293f357c3", "Project Zombie - Part 5.nfo": "73091166bd5bd3d65d7e481e317ed128" } \ No newline at end of file diff --git a/tests/e2e/resources/expected_downloads_summaries/youtube/test_video.json b/tests/e2e/resources/expected_downloads_summaries/youtube/test_video.json index 46ace439..44d92c00 100644 --- a/tests/e2e/resources/expected_downloads_summaries/youtube/test_video.json +++ b/tests/e2e/resources/expected_downloads_summaries/youtube/test_video.json @@ -1,5 +1,6 @@ { "JMC - Oblivion Mod "Falcor" p.1-thumb.jpg": "fb95b510681676e81c321171fc23143e", + "JMC - Oblivion Mod "Falcor" p.1.info.json": "b7e3751fe749817392d2d69be71a391c", "JMC - Oblivion Mod "Falcor" p.1.mp4": "28c14cdac05c803efe71abb9454ab306", "JMC - Oblivion Mod "Falcor" p.1.nfo": "24cc4e17d2bebc89b2759ce5471d403e" } \ No newline at end of file diff --git a/tests/e2e/resources/transaction_log_summaries/plugins/date_range/test_channel_recent.txt b/tests/e2e/resources/transaction_log_summaries/plugins/date_range/test_channel_recent.txt index 248f1b9c..70a34864 100644 --- a/tests/e2e/resources/transaction_log_summaries/plugins/date_range/test_channel_recent.txt +++ b/tests/e2e/resources/transaction_log_summaries/plugins/date_range/test_channel_recent.txt @@ -2,6 +2,7 @@ Files created in '{output_directory}' ---------------------------------------- .ytdl-sub-recent-download-archive.json Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer-thumb.jpg +Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer.info.json Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer.mp4 Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer.nfo NFO tags: @@ -23,6 +24,7 @@ Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer.nfo year: 2018 Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id-thumb.jpg Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.en.srt +Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.info.json Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.mp4 Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.nfo NFO tags: diff --git a/tests/e2e/resources/transaction_log_summaries/plugins/date_range/test_channel_rolling_recent.txt b/tests/e2e/resources/transaction_log_summaries/plugins/date_range/test_channel_rolling_recent.txt index 2f549058..44b773e4 100644 --- a/tests/e2e/resources/transaction_log_summaries/plugins/date_range/test_channel_rolling_recent.txt +++ b/tests/e2e/resources/transaction_log_summaries/plugins/date_range/test_channel_rolling_recent.txt @@ -11,5 +11,6 @@ tvshow.nfo Files removed from '{output_directory}' ---------------------------------------- Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer-thumb.jpg +Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer.info.json Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer.mp4 Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer.nfo \ No newline at end of file diff --git a/tests/e2e/resources/transaction_log_summaries/plugins/nfo_tags/test_nfo.txt b/tests/e2e/resources/transaction_log_summaries/plugins/nfo_tags/test_nfo.txt index d5fec37d..a95d6bde 100644 --- a/tests/e2e/resources/transaction_log_summaries/plugins/nfo_tags/test_nfo.txt +++ b/tests/e2e/resources/transaction_log_summaries/plugins/nfo_tags/test_nfo.txt @@ -2,6 +2,7 @@ Files created in '{output_directory}' ---------------------------------------- Rick Beato - Can you hear the difference? 🎸🔥 #shorts-thumb.jpg Rick Beato - Can you hear the difference? 🎸🔥 #shorts.3gp +Rick Beato - Can you hear the difference? 🎸🔥 #shorts.info.json Rick Beato - Can you hear the difference? 🎸🔥 #shorts.nfo NFO tags: musicvideo: diff --git a/tests/e2e/resources/transaction_log_summaries/plugins/nfo_tags/test_nfo_kodi_safe.txt b/tests/e2e/resources/transaction_log_summaries/plugins/nfo_tags/test_nfo_kodi_safe.txt index b54bdf34..3076ae3f 100644 --- a/tests/e2e/resources/transaction_log_summaries/plugins/nfo_tags/test_nfo_kodi_safe.txt +++ b/tests/e2e/resources/transaction_log_summaries/plugins/nfo_tags/test_nfo_kodi_safe.txt @@ -2,6 +2,7 @@ Files created in '{output_directory}' ---------------------------------------- Rick Beato - Can you hear the difference? 🎸🔥 #shorts-thumb.jpg Rick Beato - Can you hear the difference? 🎸🔥 #shorts.3gp +Rick Beato - Can you hear the difference? 🎸🔥 #shorts.info.json Rick Beato - Can you hear the difference? 🎸🔥 #shorts.nfo NFO tags: musicvideo: diff --git a/tests/e2e/resources/transaction_log_summaries/plugins/split_by_chapters_video-dry-run.txt b/tests/e2e/resources/transaction_log_summaries/plugins/split_by_chapters_video-dry-run.txt index e8ad7dbb..0bf96738 100644 --- a/tests/e2e/resources/transaction_log_summaries/plugins/split_by_chapters_video-dry-run.txt +++ b/tests/e2e/resources/transaction_log_summaries/plugins/split_by_chapters_video-dry-run.txt @@ -1,5 +1,16 @@ Files created in '{output_directory}' ---------------------------------------- +01. Intro (Feat. Racheal Ofori & Barney Artist).info.json +02. Answers (Feat. Rick David & Kaya Thomas - Dyke).info.json +03. Blaze (Feat. Kaya Thomas - Dyke).info.json +04. What If (Interlude).info.json +05. No Peace (Feat. Tom Misch).info.json +06. Closer (Feat. Lester Duval).info.json +07. Delusions: Rumination (Interlude) (Feat. Racheal Ofori).info.json +08. Dreams (Feat. Carmody).info.json +09. Dreaming (Interlude) (Feat. Racheal Ofori).info.json +10. Hopeful (Feat. Jordan Rakei).info.json +11. Sunrise (Pillows) (Feat. Emmavie).info.json Alfa Mist - Nocturne [Full Album]/01 - 01. Intro (Feat. Racheal Ofori & Barney Artist).mp3 From Chapter Split: Warning: Dry-run assumes embedded chapters with no modifications diff --git a/tests/e2e/resources/transaction_log_summaries/plugins/split_by_chapters_video.txt b/tests/e2e/resources/transaction_log_summaries/plugins/split_by_chapters_video.txt index 80c73b91..793a1533 100644 --- a/tests/e2e/resources/transaction_log_summaries/plugins/split_by_chapters_video.txt +++ b/tests/e2e/resources/transaction_log_summaries/plugins/split_by_chapters_video.txt @@ -1,5 +1,16 @@ Files created in '{output_directory}' ---------------------------------------- +01. Intro (Feat. Racheal Ofori & Barney Artist).info.json +02. Answers (Feat. Rick David & Kaya Thomas - Dyke).info.json +03. Blaze (Feat. Kaya Thomas - Dyke).info.json +04. What If (Interlude).info.json +05. No Peace (Feat. Tom Misch).info.json +06. Closer (Feat. Lester Duval).info.json +07. Delusions: Rumination (Interlude) (Feat. Racheal Ofori).info.json +08. Dreams (Feat. Carmody).info.json +09. Dreaming (Interlude) (Feat. Racheal Ofori).info.json +10. Hopeful (Feat. Jordan Rakei).info.json +11. Sunrise (Pillows) (Feat. Emmavie).info.json Alfa Mist - Nocturne [Full Album]/01 - 01. Intro (Feat. Racheal Ofori & Barney Artist).mp3 From Chapter Split: Source Title: Alfa Mist - Nocturne [Full Album] diff --git a/tests/e2e/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_no_chapters_video_pass.txt b/tests/e2e/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_no_chapters_video_pass.txt index 3c36afab..0a5742a0 100644 --- a/tests/e2e/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_no_chapters_video_pass.txt +++ b/tests/e2e/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_no_chapters_video_pass.txt @@ -1,5 +1,6 @@ Files created in '{output_directory}' ---------------------------------------- +Oblivion Mod "Falcor" p.1.info.json Oblivion Mod "Falcor" p.1/01 - Oblivion Mod "Falcor" p.1.mp3 Music Tags: album: Oblivion Mod "Falcor" p.1 diff --git a/tests/e2e/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_video-dry-run.txt b/tests/e2e/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_video-dry-run.txt index d26a5384..15f5e407 100644 --- a/tests/e2e/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_video-dry-run.txt +++ b/tests/e2e/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_video-dry-run.txt @@ -1,5 +1,14 @@ Files created in '{output_directory}' ---------------------------------------- +Answers (Feat. Rick David & Kaya Thomas - Dyke).info.json +Blaze (Feat. Kaya Thomas - Dyke).info.json +Closer (Feat. Lester Duval).info.json +Delusions: Rumination (Interlude) (Feat. Racheal Ofori).info.json +Dreaming (Interlude) (Feat. Racheal Ofori).info.json +Dreams (Feat. Carmody).info.json +Hopeful (Feat. Jordan Rakei).info.json +Intro (Feat. Racheal Ofori & Barney Artist).info.json +No Peace (Feat. Tom Misch).info.json Nocturne/01 - Intro (Feat. Racheal Ofori & Barney Artist).mp3 From Chapter Split: Warning: Dry-run assumes embedded chapters with no modifications @@ -143,4 +152,6 @@ Nocturne/11 - Sunrise (Pillows) (Feat. Emmavie).mp3 title: Sunrise (Pillows) (Feat. Emmavie) track: 11 year: 2017 -Nocturne/folder.jpg \ No newline at end of file +Nocturne/folder.jpg +Sunrise (Pillows) (Feat. Emmavie).info.json +What If (Interlude).info.json \ No newline at end of file diff --git a/tests/e2e/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_video.txt b/tests/e2e/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_video.txt index 460cabb3..0efb31dd 100644 --- a/tests/e2e/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_video.txt +++ b/tests/e2e/resources/transaction_log_summaries/plugins/split_by_chapters_with_regex_video.txt @@ -1,5 +1,14 @@ Files created in '{output_directory}' ---------------------------------------- +Answers (Feat. Rick David & Kaya Thomas - Dyke).info.json +Blaze (Feat. Kaya Thomas - Dyke).info.json +Closer (Feat. Lester Duval).info.json +Delusions: Rumination (Interlude) (Feat. Racheal Ofori).info.json +Dreaming (Interlude) (Feat. Racheal Ofori).info.json +Dreams (Feat. Carmody).info.json +Hopeful (Feat. Jordan Rakei).info.json +Intro (Feat. Racheal Ofori & Barney Artist).info.json +No Peace (Feat. Tom Misch).info.json Nocturne/01 - Intro (Feat. Racheal Ofori & Barney Artist).mp3 From Chapter Split: Source Title: Alfa Mist - Nocturne [Full Album] @@ -132,4 +141,6 @@ Nocturne/11 - Sunrise (Pillows) (Feat. Emmavie).mp3 title: Sunrise (Pillows) (Feat. Emmavie) track: 11 year: 2017 -Nocturne/folder.jpg \ No newline at end of file +Nocturne/folder.jpg +Sunrise (Pillows) (Feat. Emmavie).info.json +What If (Interlude).info.json \ No newline at end of file diff --git a/tests/e2e/resources/transaction_log_summaries/plugins/test_audio_extract_playlist.txt b/tests/e2e/resources/transaction_log_summaries/plugins/test_audio_extract_playlist.txt index b02d60ac..e36f5f60 100644 --- a/tests/e2e/resources/transaction_log_summaries/plugins/test_audio_extract_playlist.txt +++ b/tests/e2e/resources/transaction_log_summaries/plugins/test_audio_extract_playlist.txt @@ -1,5 +1,6 @@ Files created in '{output_directory}' ---------------------------------------- +Jesse's Minecraft Server [Trailer - Feb.1].info.json Jesse's Minecraft Server [Trailer - Feb.1].ogg Music Tags: album: Singles @@ -9,6 +10,7 @@ Jesse's Minecraft Server [Trailer - Feb.1].ogg title: Jesse's Minecraft Server [Trailer - Feb.1] track: 3 year: 2011 +Jesse's Minecraft Server [Trailer - Feb.27].info.json Jesse's Minecraft Server [Trailer - Feb.27].ogg Music Tags: album: Singles @@ -18,6 +20,7 @@ Jesse's Minecraft Server [Trailer - Feb.27].ogg title: Jesse's Minecraft Server [Trailer - Feb.27] track: 2 year: 2011 +Jesse's Minecraft Server [Trailer - Mar.21].info.json Jesse's Minecraft Server [Trailer - Mar.21].ogg Music Tags: album: Singles diff --git a/tests/e2e/resources/transaction_log_summaries/plugins/test_audio_extract_single.txt b/tests/e2e/resources/transaction_log_summaries/plugins/test_audio_extract_single.txt index 3046395d..fa01724c 100644 --- a/tests/e2e/resources/transaction_log_summaries/plugins/test_audio_extract_single.txt +++ b/tests/e2e/resources/transaction_log_summaries/plugins/test_audio_extract_single.txt @@ -1,5 +1,6 @@ Files created in '{output_directory}' ---------------------------------------- +YouTube Rewind 2019: For the Record | #YouTubeRewind.info.json YouTube Rewind 2019: For the Record | #YouTubeRewind.mp3 Music Tags: album: Singles diff --git a/tests/e2e/resources/transaction_log_summaries/plugins/test_chapters_from_ts_with_subs.txt b/tests/e2e/resources/transaction_log_summaries/plugins/test_chapters_from_ts_with_subs.txt index 374daef1..6fa3cad8 100644 --- a/tests/e2e/resources/transaction_log_summaries/plugins/test_chapters_from_ts_with_subs.txt +++ b/tests/e2e/resources/transaction_log_summaries/plugins/test_chapters_from_ts_with_subs.txt @@ -1,6 +1,7 @@ Files created in '{output_directory}' ---------------------------------------- JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case-thumb.jpg +JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.info.json JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.mp4 Chapters embedded from timestamp file: 0:00: Intro diff --git a/tests/e2e/resources/transaction_log_summaries/plugins/test_chapters_sb_and_embedded_subs.txt b/tests/e2e/resources/transaction_log_summaries/plugins/test_chapters_sb_and_embedded_subs.txt index 127e6543..3db149e6 100644 --- a/tests/e2e/resources/transaction_log_summaries/plugins/test_chapters_sb_and_embedded_subs.txt +++ b/tests/e2e/resources/transaction_log_summaries/plugins/test_chapters_sb_and_embedded_subs.txt @@ -1,6 +1,7 @@ Files created in '{output_directory}' ---------------------------------------- JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case-thumb.jpg +JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.info.json JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.mp4 Embedded Chapters Removed Chapter(s): Intro, Outro diff --git a/tests/e2e/resources/transaction_log_summaries/plugins/test_regex.txt b/tests/e2e/resources/transaction_log_summaries/plugins/test_regex.txt index 97fd64dc..2d13155a 100644 --- a/tests/e2e/resources/transaction_log_summaries/plugins/test_regex.txt +++ b/tests/e2e/resources/transaction_log_summaries/plugins/test_regex.txt @@ -2,6 +2,7 @@ Files created in '{output_directory}' ---------------------------------------- .ytdl-sub-regex_capture_playlist_test-download-archive.json Project Zombie - Jesse's Minecraft Server [Trailer - Feb.1]-thumb.jpg +Project Zombie - Jesse's Minecraft Server [Trailer - Feb.1].info.json Project Zombie - Jesse's Minecraft Server [Trailer - Feb.1].mp4 Project Zombie - Jesse's Minecraft Server [Trailer - Feb.1].nfo NFO tags: @@ -20,6 +21,7 @@ Project Zombie - Jesse's Minecraft Server [Trailer - Feb.1].nfo upload_date_both_caps: First and Second containing in regex default year: 2011 Project Zombie - Jesse's Minecraft Server [Trailer - Feb.27]-thumb.jpg +Project Zombie - Jesse's Minecraft Server [Trailer - Feb.27].info.json Project Zombie - Jesse's Minecraft Server [Trailer - Feb.27].mp4 Project Zombie - Jesse's Minecraft Server [Trailer - Feb.27].nfo NFO tags: diff --git a/tests/e2e/resources/transaction_log_summaries/plugins/test_subtitles_embedded.txt b/tests/e2e/resources/transaction_log_summaries/plugins/test_subtitles_embedded.txt index 03daf6ee..3f4f5222 100644 --- a/tests/e2e/resources/transaction_log_summaries/plugins/test_subtitles_embedded.txt +++ b/tests/e2e/resources/transaction_log_summaries/plugins/test_subtitles_embedded.txt @@ -1,6 +1,7 @@ Files created in '{output_directory}' ---------------------------------------- JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind-thumb.jpg +JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.info.json JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.mp4 Embedded subtitles with lang(s) en, de JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.nfo diff --git a/tests/e2e/resources/transaction_log_summaries/plugins/test_subtitles_embedded_and_file.txt b/tests/e2e/resources/transaction_log_summaries/plugins/test_subtitles_embedded_and_file.txt index d47900c3..c1dc9ad3 100644 --- a/tests/e2e/resources/transaction_log_summaries/plugins/test_subtitles_embedded_and_file.txt +++ b/tests/e2e/resources/transaction_log_summaries/plugins/test_subtitles_embedded_and_file.txt @@ -3,6 +3,7 @@ Files created in '{output_directory}' JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind-thumb.jpg JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.de.srt JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.en.srt +JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.info.json JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.mp4 Embedded subtitles with lang(s) en, de JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.nfo diff --git a/tests/e2e/resources/transaction_log_summaries/soundcloud/test_soundcloud_discography.txt b/tests/e2e/resources/transaction_log_summaries/soundcloud/test_soundcloud_discography.txt index 27e66c04..f34f9c00 100644 --- a/tests/e2e/resources/transaction_log_summaries/soundcloud/test_soundcloud_discography.txt +++ b/tests/e2e/resources/transaction_log_summaries/soundcloud/test_soundcloud_discography.txt @@ -1,6 +1,7 @@ Files created in '{output_directory}' ---------------------------------------- .ytdl-sub-jb-download-archive.json +j_b/[2021] Baby Santana's Dorian Groove/01 - Baby Santana's Dorian Groove.info.json j_b/[2021] Baby Santana's Dorian Groove/01 - Baby Santana's Dorian Groove.mp3 Music Tags: album: Baby Santana's Dorian Groove @@ -11,6 +12,7 @@ j_b/[2021] Baby Santana's Dorian Groove/01 - Baby Santana's Dorian Groove.mp3 track: 1 year: 2021 j_b/[2021] Baby Santana's Dorian Groove/folder.jpg +j_b/[2021] Purple Clouds/01 - Purple Clouds.info.json j_b/[2021] Purple Clouds/01 - Purple Clouds.mp3 Music Tags: album: Purple Clouds @@ -21,6 +23,7 @@ j_b/[2021] Purple Clouds/01 - Purple Clouds.mp3 track: 1 year: 2021 j_b/[2021] Purple Clouds/folder.jpg +j_b/[2022] Acoustic Treats/01 - 20160426 184214.info.json j_b/[2022] Acoustic Treats/01 - 20160426 184214.mp3 Music Tags: album: Acoustic Treats @@ -30,6 +33,7 @@ j_b/[2022] Acoustic Treats/01 - 20160426 184214.mp3 title: 20160426 184214 track: 1 year: 2022 +j_b/[2022] Acoustic Treats/02 - 20160502 123150.info.json j_b/[2022] Acoustic Treats/02 - 20160502 123150.mp3 Music Tags: album: Acoustic Treats @@ -39,6 +43,7 @@ j_b/[2022] Acoustic Treats/02 - 20160502 123150.mp3 title: 20160502 123150 track: 2 year: 2022 +j_b/[2022] Acoustic Treats/03 - 20160504 143832.info.json j_b/[2022] Acoustic Treats/03 - 20160504 143832.mp3 Music Tags: album: Acoustic Treats @@ -48,6 +53,7 @@ j_b/[2022] Acoustic Treats/03 - 20160504 143832.mp3 title: 20160504 143832 track: 3 year: 2022 +j_b/[2022] Acoustic Treats/04 - 20160601 221234.info.json j_b/[2022] Acoustic Treats/04 - 20160601 221234.mp3 Music Tags: album: Acoustic Treats @@ -57,6 +63,7 @@ j_b/[2022] Acoustic Treats/04 - 20160601 221234.mp3 title: 20160601 221234 track: 4 year: 2022 +j_b/[2022] Acoustic Treats/05 - 20160601 222440.info.json j_b/[2022] Acoustic Treats/05 - 20160601 222440.mp3 Music Tags: album: Acoustic Treats @@ -66,6 +73,7 @@ j_b/[2022] Acoustic Treats/05 - 20160601 222440.mp3 title: 20160601 222440 track: 5 year: 2022 +j_b/[2022] Acoustic Treats/06 - 20170604 190236.info.json j_b/[2022] Acoustic Treats/06 - 20170604 190236.mp3 Music Tags: album: Acoustic Treats @@ -75,6 +83,7 @@ j_b/[2022] Acoustic Treats/06 - 20170604 190236.mp3 title: 20170604 190236 track: 6 year: 2022 +j_b/[2022] Acoustic Treats/07 - 20170612 193646.info.json j_b/[2022] Acoustic Treats/07 - 20170612 193646.mp3 Music Tags: album: Acoustic Treats @@ -84,6 +93,7 @@ j_b/[2022] Acoustic Treats/07 - 20170612 193646.mp3 title: 20170612 193646 track: 7 year: 2022 +j_b/[2022] Acoustic Treats/08 - 20170628 215206.info.json j_b/[2022] Acoustic Treats/08 - 20170628 215206.mp3 Music Tags: album: Acoustic Treats @@ -93,6 +103,7 @@ j_b/[2022] Acoustic Treats/08 - 20170628 215206.mp3 title: 20170628 215206 track: 8 year: 2022 +j_b/[2022] Acoustic Treats/09 - Finding Home.info.json j_b/[2022] Acoustic Treats/09 - Finding Home.mp3 Music Tags: album: Acoustic Treats @@ -102,6 +113,7 @@ j_b/[2022] Acoustic Treats/09 - Finding Home.mp3 title: Finding Home track: 9 year: 2022 +j_b/[2022] Acoustic Treats/10 - Shallow Water WIP.info.json j_b/[2022] Acoustic Treats/10 - Shallow Water WIP.mp3 Music Tags: album: Acoustic Treats @@ -111,6 +123,7 @@ j_b/[2022] Acoustic Treats/10 - Shallow Water WIP.mp3 title: Shallow Water WIP track: 10 year: 2022 +j_b/[2022] Acoustic Treats/11 - Untold History.info.json j_b/[2022] Acoustic Treats/11 - Untold History.mp3 Music Tags: album: Acoustic Treats diff --git a/tests/e2e/resources/transaction_log_summaries/youtube/test_channel_full.txt b/tests/e2e/resources/transaction_log_summaries/youtube/test_channel_full.txt index 4888db8a..b339a15e 100644 --- a/tests/e2e/resources/transaction_log_summaries/youtube/test_channel_full.txt +++ b/tests/e2e/resources/transaction_log_summaries/youtube/test_channel_full.txt @@ -2,6 +2,7 @@ Files created in '{output_directory}' ---------------------------------------- .ytdl-sub-pz-download-archive.json Season 2010/s2010.e0813 - Oblivion Mod "Falcor" p.1-thumb.jpg +Season 2010/s2010.e0813 - Oblivion Mod "Falcor" p.1.info.json Season 2010/s2010.e0813 - Oblivion Mod "Falcor" p.1.mp4 Season 2010/s2010.e0813 - Oblivion Mod "Falcor" p.1.nfo NFO tags: @@ -19,6 +20,7 @@ Season 2010/s2010.e0813 - Oblivion Mod "Falcor" p.1.nfo title: Oblivion Mod "Falcor" p.1 year: 2010 Season 2010/s2010.e1202 - Oblivion Mod "Falcor" p.2-thumb.jpg +Season 2010/s2010.e1202 - Oblivion Mod "Falcor" p.2.info.json Season 2010/s2010.e1202 - Oblivion Mod "Falcor" p.2.mp4 Season 2010/s2010.e1202 - Oblivion Mod "Falcor" p.2.nfo NFO tags: @@ -36,6 +38,7 @@ Season 2010/s2010.e1202 - Oblivion Mod "Falcor" p.2.nfo title: Oblivion Mod "Falcor" p.2 year: 2010 Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1]-thumb.jpg +Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].info.json Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].mp4 Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].nfo NFO tags: @@ -54,6 +57,7 @@ Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].nfo title: Jesse's Minecraft Server [Trailer - Feb.1] year: 2011 Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27]-thumb.jpg +Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].info.json Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].mp4 Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].nfo NFO tags: @@ -91,6 +95,7 @@ Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].nfo title: Jesse's Minecraft Server [Trailer - Feb.27] year: 2011 Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21]-thumb.jpg +Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].info.json Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].mp4 Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].nfo NFO tags: @@ -128,6 +133,7 @@ Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].nfo title: Jesse's Minecraft Server [Trailer - Mar.21] year: 2011 Season 2011/s2011.e0529 - Project Zombie |Official Trailer| (IP: mc.projectzombie.beastnode.net)-thumb.jpg +Season 2011/s2011.e0529 - Project Zombie |Official Trailer| (IP: mc.projectzombie.beastnode.net).info.json Season 2011/s2011.e0529 - Project Zombie |Official Trailer| (IP: mc.projectzombie.beastnode.net).mp4 Season 2011/s2011.e0529 - Project Zombie |Official Trailer| (IP: mc.projectzombie.beastnode.net).nfo NFO tags: @@ -155,6 +161,7 @@ Season 2011/s2011.e0529 - Project Zombie |Official Trailer| (IP: mc.projec title: Project Zombie |Official Trailer| (IP: mc.projectzombie.beastnode.net) year: 2011 Season 2011/s2011.e0630 - Project Zombie |Fin|-thumb.jpg +Season 2011/s2011.e0630 - Project Zombie |Fin|.info.json Season 2011/s2011.e0630 - Project Zombie |Fin|.mp4 Season 2011/s2011.e0630 - Project Zombie |Fin|.nfo NFO tags: @@ -168,6 +175,7 @@ Season 2011/s2011.e0630 - Project Zombie |Fin|.nfo title: Project Zombie |Fin| year: 2011 Season 2011/s2011.e1121 - Skyrim 'Ultra HD w⧸Mods' [PC]-thumb.jpg +Season 2011/s2011.e1121 - Skyrim 'Ultra HD w⧸Mods' [PC].info.json Season 2011/s2011.e1121 - Skyrim 'Ultra HD w⧸Mods' [PC].mp4 Season 2011/s2011.e1121 - Skyrim 'Ultra HD w⧸Mods' [PC].nfo NFO tags: @@ -188,6 +196,7 @@ Season 2011/s2011.e1121 - Skyrim 'Ultra HD w⧸Mods' [PC].nfo title: Skyrim 'Ultra HD w/Mods' [PC] year: 2011 Season 2012/s2012.e0123 - Project Zombie |Map Trailer|-thumb.jpg +Season 2012/s2012.e0123 - Project Zombie |Map Trailer|.info.json Season 2012/s2012.e0123 - Project Zombie |Map Trailer|.mp4 Season 2012/s2012.e0123 - Project Zombie |Map Trailer|.nfo NFO tags: @@ -208,6 +217,7 @@ Season 2012/s2012.e0123 - Project Zombie |Map Trailer|.nfo title: Project Zombie |Map Trailer| year: 2012 Season 2013/s2013.e0719 - Project Zombie Rewind |Trailer|-thumb.jpg +Season 2013/s2013.e0719 - Project Zombie Rewind |Trailer|.info.json Season 2013/s2013.e0719 - Project Zombie Rewind |Trailer|.mp4 Season 2013/s2013.e0719 - Project Zombie Rewind |Trailer|.nfo NFO tags: @@ -223,6 +233,7 @@ Season 2013/s2013.e0719 - Project Zombie Rewind |Trailer|.nfo title: Project Zombie Rewind |Trailer| year: 2013 Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer-thumb.jpg +Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer.info.json Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer.mp4 Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer.nfo NFO tags: @@ -244,6 +255,7 @@ Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer.nfo year: 2018 Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id-thumb.jpg Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.en.srt +Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.info.json Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.mp4 Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.nfo NFO tags: diff --git a/tests/e2e/resources/transaction_log_summaries/youtube/test_merge_playlist.txt b/tests/e2e/resources/transaction_log_summaries/youtube/test_merge_playlist.txt index 8c3fb220..e02577e6 100644 --- a/tests/e2e/resources/transaction_log_summaries/youtube/test_merge_playlist.txt +++ b/tests/e2e/resources/transaction_log_summaries/youtube/test_merge_playlist.txt @@ -1,6 +1,7 @@ Files created in '{output_directory}' ---------------------------------------- JMC - Jesse's Minecraft Server-thumb.jpg +JMC - Jesse's Minecraft Server.info.json JMC - Jesse's Minecraft Server.mkv Timestamps of playlist videos in the merged file: 0:00: Jesse's Minecraft Server [Trailer - Mar.21] diff --git a/tests/e2e/resources/transaction_log_summaries/youtube/test_playlist.txt b/tests/e2e/resources/transaction_log_summaries/youtube/test_playlist.txt index 603789f6..b3f8a9cc 100644 --- a/tests/e2e/resources/transaction_log_summaries/youtube/test_playlist.txt +++ b/tests/e2e/resources/transaction_log_summaries/youtube/test_playlist.txt @@ -2,6 +2,7 @@ Files created in '{output_directory}' ---------------------------------------- .ytdl-sub-music_video_playlist_test-download-archive.json JMC - Jesse's Minecraft Server [Trailer - Feb.1]-thumb.jpg +JMC - Jesse's Minecraft Server [Trailer - Feb.1].info.json JMC - Jesse's Minecraft Server [Trailer - Feb.1].mp4 JMC - Jesse's Minecraft Server [Trailer - Feb.1].nfo NFO tags: @@ -11,6 +12,7 @@ JMC - Jesse's Minecraft Server [Trailer - Feb.1].nfo title: Jesse's Minecraft Server [Trailer - Feb.1] year: 2011 JMC - Jesse's Minecraft Server [Trailer - Feb.27]-thumb.jpg +JMC - Jesse's Minecraft Server [Trailer - Feb.27].info.json JMC - Jesse's Minecraft Server [Trailer - Feb.27].mp4 JMC - Jesse's Minecraft Server [Trailer - Feb.27].nfo NFO tags: @@ -20,6 +22,7 @@ JMC - Jesse's Minecraft Server [Trailer - Feb.27].nfo title: Jesse's Minecraft Server [Trailer - Feb.27] year: 2011 JMC - Jesse's Minecraft Server [Trailer - Mar.21]-thumb.jpg +JMC - Jesse's Minecraft Server [Trailer - Mar.21].info.json JMC - Jesse's Minecraft Server [Trailer - Mar.21].mp4 JMC - Jesse's Minecraft Server [Trailer - Mar.21].nfo NFO tags: diff --git a/tests/e2e/resources/transaction_log_summaries/youtube/test_split_video.txt b/tests/e2e/resources/transaction_log_summaries/youtube/test_split_video.txt index 28ea9910..e8113d7d 100644 --- a/tests/e2e/resources/transaction_log_summaries/youtube/test_split_video.txt +++ b/tests/e2e/resources/transaction_log_summaries/youtube/test_split_video.txt @@ -13,6 +13,7 @@ Project Zombie - 5-6.Part 4.mp4 Project Zombie - 6-6.Part 5.mp4 1:01 - 1:28 Project Zombie - Intro-thumb.jpg +Project Zombie - Intro.info.json Project Zombie - Intro.nfo NFO tags: musicvideo: @@ -21,6 +22,7 @@ Project Zombie - Intro.nfo title: Intro year: 2010 Project Zombie - Part 1-thumb.jpg +Project Zombie - Part 1.info.json Project Zombie - Part 1.nfo NFO tags: musicvideo: @@ -29,6 +31,7 @@ Project Zombie - Part 1.nfo title: Part 1 year: 2010 Project Zombie - Part 2-thumb.jpg +Project Zombie - Part 2.info.json Project Zombie - Part 2.nfo NFO tags: musicvideo: @@ -37,6 +40,7 @@ Project Zombie - Part 2.nfo title: Part 2 year: 2010 Project Zombie - Part 3-thumb.jpg +Project Zombie - Part 3.info.json Project Zombie - Part 3.nfo NFO tags: musicvideo: @@ -45,6 +49,7 @@ Project Zombie - Part 3.nfo title: Part 3 year: 2010 Project Zombie - Part 4-thumb.jpg +Project Zombie - Part 4.info.json Project Zombie - Part 4.nfo NFO tags: musicvideo: @@ -53,6 +58,7 @@ Project Zombie - Part 4.nfo title: Part 4 year: 2010 Project Zombie - Part 5-thumb.jpg +Project Zombie - Part 5.info.json Project Zombie - Part 5.nfo NFO tags: musicvideo: diff --git a/tests/e2e/resources/transaction_log_summaries/youtube/test_video.txt b/tests/e2e/resources/transaction_log_summaries/youtube/test_video.txt index b3e7b13b..eb444bf0 100644 --- a/tests/e2e/resources/transaction_log_summaries/youtube/test_video.txt +++ b/tests/e2e/resources/transaction_log_summaries/youtube/test_video.txt @@ -1,6 +1,7 @@ Files created in '{output_directory}' ---------------------------------------- JMC - Oblivion Mod "Falcor" p.1-thumb.jpg +JMC - Oblivion Mod "Falcor" p.1.info.json JMC - Oblivion Mod "Falcor" p.1.mp4 Video Tags: title: Oblivion Mod "Falcor" p.1 diff --git a/tests/unit/entries/conftest.py b/tests/unit/entries/conftest.py index 1c0fe0bb..012ba56c 100644 --- a/tests/unit/entries/conftest.py +++ b/tests/unit/entries/conftest.py @@ -77,6 +77,7 @@ def mock_entry_to_dict( "upload_day_of_year_reversed": 354, "upload_day_of_year_reversed_padded": "354", "thumbnail_ext": thumbnail_ext, + "info_json_ext": "info.json", }