diff --git a/src/ytdl_sub/cli/entrypoint.py b/src/ytdl_sub/cli/entrypoint.py index 86a98e57e..c19baf335 100644 --- a/src/ytdl_sub/cli/entrypoint.py +++ b/src/ytdl_sub/cli/entrypoint.py @@ -161,7 +161,7 @@ def _download_subscription_from_cli( extra_arguments=extra_args, config_options=config.config_options ) subscription_args_dict = dl_args_parser.to_subscription_dict() - subscription_name = f"cli-dl-{dl_args_parser.get_args_hash()}" + subscription_name = dl_args_parser.get_dl_subscription_name() subscription = Subscription.from_dict( config=config, preset_name=subscription_name, preset_dict=subscription_args_dict diff --git a/src/ytdl_sub/cli/parsers/dl.py b/src/ytdl_sub/cli/parsers/dl.py index d9e1eb1ad..7fbf7ac42 100644 --- a/src/ytdl_sub/cli/parsers/dl.py +++ b/src/ytdl_sub/cli/parsers/dl.py @@ -242,12 +242,13 @@ def to_subscription_dict(self) -> Dict: return subscription_dict - def get_args_hash(self) -> str: + def get_dl_subscription_name(self) -> str: """ - :return: Hash of the arguments provided + Returns a deterministic name based on input args """ - hash_string = str(sorted(self._unknown_arguments)) - return hashlib.sha256(hash_string.encode()).hexdigest()[-8:] + to_hash = str(sorted(self._unknown_arguments)) + hash_str = hashlib.sha256(to_hash.encode()).hexdigest()[-8:] + return f"cli-dl-{hash_str}" @classmethod def from_dl_override(cls, override: str, config: ConfigFile) -> "DownloadArgsParser": diff --git a/tests/conftest.py b/tests/conftest.py index 522ddb3ba..12ba38a91 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,7 +2,9 @@ import json import logging import os +import shlex import shutil +import sys import tempfile from pathlib import Path from typing import Any @@ -18,8 +20,10 @@ from resources import file_fixture_path from yt_dlp.utils import sanitize_filename +from ytdl_sub.cli.entrypoint import main from ytdl_sub.config.config_file import ConfigFile from ytdl_sub.entries.script.custom_functions import CustomFunctions +from ytdl_sub.subscriptions.subscription import Subscription from ytdl_sub.subscriptions.subscription_download import SubscriptionDownload from ytdl_sub.utils.file_handler import FileHandler from ytdl_sub.utils.logger import Logger @@ -262,3 +266,9 @@ def default_config_path(default_config) -> str: @pytest.fixture() def music_subscriptions_path() -> Path: return Path("examples/music_subscriptions.yaml") + + +def mock_run_from_cli(args: str) -> List[Subscription]: + args_list = ["ytdl-sub"] + shlex.split(args) + with patch.object(sys, "argv", args_list): + return main() diff --git a/tests/e2e/conftest.py b/tests/e2e/conftest.py index d2957a276..99ef3f92f 100644 --- a/tests/e2e/conftest.py +++ b/tests/e2e/conftest.py @@ -1,13 +1,7 @@ -import shlex -import sys import tempfile -from typing import List -from unittest.mock import patch import pytest -from ytdl_sub.cli.entrypoint import main -from ytdl_sub.subscriptions.subscription import Subscription from ytdl_sub.utils.file_handler import FileHandler @@ -31,9 +25,3 @@ def timestamps_file_path(): yield tmp.name finally: FileHandler.delete(tmp.name) - - -def mock_run_from_cli(args: str) -> List[Subscription]: - args_list = ["ytdl-sub"] + shlex.split(args) - with patch.object(sys, "argv", args_list): - return main() diff --git a/tests/e2e/plugins/internal/test_view.py b/tests/e2e/plugins/internal/test_view.py index dbfcd13b8..88951250e 100644 --- a/tests/e2e/plugins/internal/test_view.py +++ b/tests/e2e/plugins/internal/test_view.py @@ -1,7 +1,7 @@ from typing import Optional import pytest -from e2e.conftest import mock_run_from_cli +from conftest import mock_run_from_cli from ytdl_sub.utils.file_handler import FileMetadata diff --git a/tests/e2e/youtube/test_playlist.py b/tests/e2e/youtube/test_playlist.py index e173c568e..c3a364a6d 100644 --- a/tests/e2e/youtube/test_playlist.py +++ b/tests/e2e/youtube/test_playlist.py @@ -1,17 +1,13 @@ -from pathlib import Path from typing import Dict import pytest from conftest import assert_logs -from e2e.conftest import mock_run_from_cli from expected_download import assert_expected_downloads from expected_transaction_log import assert_transaction_log_matches -from mergedeep import mergedeep from ytdl_sub.config.config_file import ConfigFile from ytdl_sub.downloaders.ytdlp import YTDLP from ytdl_sub.subscriptions.subscription import Subscription -from ytdl_sub.utils.system import IS_WINDOWS @pytest.fixture @@ -100,50 +96,6 @@ class TestPlaylist: files exist and have the expected md5 file hashes. """ - @classmethod - def _ensure_subscription_migrates( - cls, - config: ConfigFile, - subscription_name: str, - subscription_dict: Dict, - output_directory: Path, - ): - # Ensure download archive migrates - mergedeep.merge( - subscription_dict, - { - "output_options": { - "migrated_download_archive_name": ".ytdl-sub-{tv_show_name_sanitized}-download-archive.json" - } - }, - ) - migrated_subscription = Subscription.from_dict( - config=config, - preset_name=subscription_name, - preset_dict=subscription_dict, - ) - transaction_log = migrated_subscription.download() - - assert_transaction_log_matches( - output_directory=output_directory, - transaction_log=transaction_log, - transaction_log_summary_file_name="youtube/test_playlist_archive_migrated.txt", - ) - assert_expected_downloads( - output_directory=output_directory, - dry_run=False, - expected_download_summary_file_name="youtube/test_playlist_archive_migrated.json", - ) - - # Ensure no changes after migration - transaction_log = migrated_subscription.download() - assert transaction_log.is_empty - assert_expected_downloads( - output_directory=output_directory, - dry_run=False, - expected_download_summary_file_name="youtube/test_playlist_archive_migrated.json", - ) - @pytest.mark.parametrize("dry_run", [True, False]) def test_playlist_download( self, @@ -186,86 +138,6 @@ def test_playlist_download( expected_download_summary_file_name="youtube/test_playlist.json", ) - self._ensure_subscription_migrates( - config=default_config, - subscription_name="music_video_playlist_test", - subscription_dict=playlist_preset_dict, - output_directory=output_directory, - ) - - @pytest.mark.parametrize("dry_run", [True, False]) - def test_playlist_download_from_cli_sub_no_provided_config( - self, - preset_dict_to_subscription_yaml_generator, - playlist_preset_dict, - output_directory, - dry_run, - ): - # TODO: Fix CLI parsing on windows when dealing with spaces - if IS_WINDOWS: - return - - # No config needed when using only prebuilt presets - with preset_dict_to_subscription_yaml_generator( - subscription_name="music_video_playlist_test", preset_dict=playlist_preset_dict - ) as subscription_path: - args = "--dry-run " if dry_run else "" - args += f"sub '{subscription_path}'" - subscriptions = mock_run_from_cli(args=args) - - assert len(subscriptions) == 1 - transaction_log = subscriptions[0].transaction_log - - assert_transaction_log_matches( - output_directory=output_directory, - transaction_log=transaction_log, - transaction_log_summary_file_name="youtube/test_playlist.txt", - ) - assert_expected_downloads( - output_directory=output_directory, - dry_run=dry_run, - expected_download_summary_file_name="youtube/test_playlist.json", - ) - - if not dry_run: - # Ensure another invocation will hit ExistingVideoReached - with assert_logs( - logger=YTDLP.logger, - expected_message="ExistingVideoReached, stopping additional downloads", - log_level="debug", - ): - transaction_log = mock_run_from_cli(args=args)[0].transaction_log - - assert transaction_log.is_empty - assert_expected_downloads( - output_directory=output_directory, - dry_run=dry_run, - expected_download_summary_file_name="youtube/test_playlist.json", - ) - - def test_playlist_download_from_cli_sub_with_override_arg( - self, - preset_dict_to_subscription_yaml_generator, - playlist_preset_dict, - output_directory, - ): - # TODO: Fix CLI parsing on windows when dealing with spaces - if IS_WINDOWS: - return - - # No config needed when using only prebuilt presets - with preset_dict_to_subscription_yaml_generator( - subscription_name="music_video_playlist_test", preset_dict=playlist_preset_dict - ) as subscription_path: - args = ( - f"--dry-run sub '{subscription_path}' --dl-override '--date_range.after 20240101'" - ) - - subscriptions = mock_run_from_cli(args=args) - - assert len(subscriptions) == 1 - assert subscriptions[0].transaction_log.is_empty - def test_tv_show_by_date_downloads_bilateral( self, tv_show_by_date_bilateral_dict: Dict, diff --git a/tests/e2e/youtube/test_video.py b/tests/e2e/youtube/test_video.py index 8753a157c..10b4e9745 100644 --- a/tests/e2e/youtube/test_video.py +++ b/tests/e2e/youtube/test_video.py @@ -1,17 +1,9 @@ -from unittest.mock import patch - import pytest from conftest import preset_dict_to_dl_args -from e2e.conftest import mock_run_from_cli from expected_download import assert_expected_downloads from expected_transaction_log import assert_transaction_log_matches -from ytdl_sub.downloaders.ytdlp import YTDLP -from ytdl_sub.entries.entry import Entry from ytdl_sub.subscriptions.subscription import Subscription -from ytdl_sub.utils.file_handler import FileHandler -from ytdl_sub.utils.system import IS_WINDOWS -from ytdl_sub.utils.thumbnail import try_convert_download_thumbnail @pytest.fixture @@ -69,72 +61,3 @@ def test_single_video_download( dry_run=dry_run, expected_download_summary_file_name="youtube/test_video.json", ) - - def test_single_video_download_missing_thumbnail( - self, - default_config, - single_video_preset_dict, - working_directory, - output_directory, - ): - single_video_subscription = Subscription.from_dict( - config=default_config, - preset_name="music_video_single_video_test", - preset_dict=single_video_preset_dict, - ) - - def delete_entry_thumb(entry: Entry) -> None: - FileHandler.delete(entry.get_download_thumbnail_path()) - try_convert_download_thumbnail(entry=entry) - - # Pretend the thumbnail did not download via returning nothing for its downloaded path - with ( - patch.object(YTDLP, "_EXTRACT_ENTRY_NUM_RETRIES", 1), - patch.object(Entry, "try_get_ytdlp_download_thumbnail_path") as mock_ytdlp_path, - patch( - "ytdl_sub.downloaders.url.downloader.try_convert_download_thumbnail", - side_effect=delete_entry_thumb, - ), - ): - mock_ytdlp_path.return_value = None - transaction_log = single_video_subscription.download(dry_run=False) - - assert_transaction_log_matches( - output_directory=output_directory, - transaction_log=transaction_log, - transaction_log_summary_file_name="youtube/test_video_missing_thumb.txt", - ) - assert_expected_downloads( - output_directory=output_directory, - dry_run=False, - expected_download_summary_file_name="youtube/test_video_missing_thumb.json", - ) - - @pytest.mark.parametrize("dry_run", [True, False]) - def test_single_video_download_from_cli_dl( - self, - default_config_path, - single_video_preset_dict_dl_args, - output_directory, - dry_run, - ): - # TODO: Fix CLI parsing on windows when dealing with spaces - if IS_WINDOWS: - return - - args = "--dry-run " if dry_run else "" - args += f"--config {default_config_path} " - args += f"dl {single_video_preset_dict_dl_args}" - subscriptions = mock_run_from_cli(args=args) - - assert len(subscriptions) == 1 - assert_transaction_log_matches( - output_directory=output_directory, - transaction_log=subscriptions[0].transaction_log, - transaction_log_summary_file_name="youtube/test_video_cli.txt", - ) - assert_expected_downloads( - output_directory=output_directory, - dry_run=dry_run, - expected_download_summary_file_name="youtube/test_video_cli.json", - ) diff --git a/tests/integration/cli/test_dl.py b/tests/integration/cli/test_dl.py new file mode 100644 index 000000000..013ad4a67 --- /dev/null +++ b/tests/integration/cli/test_dl.py @@ -0,0 +1,73 @@ +from typing import Dict +from unittest.mock import patch + +import pytest +from conftest import mock_run_from_cli +from conftest import preset_dict_to_dl_args +from expected_download import assert_expected_downloads +from expected_transaction_log import assert_transaction_log_matches + +from ytdl_sub.cli.parsers.dl import DownloadArgsParser +from ytdl_sub.utils.system import IS_WINDOWS + + +@pytest.fixture +def dl_subscription_dict(output_directory) -> Dict: + return { + "preset": "Jellyfin Music Videos", + "overrides": { + "music_video_artist": "JMC", + "music_video_directory": output_directory, + "url": "https://your.name.here", + }, + "nfo_tags": {"tags": {"custom_tag": "{%array_at( ['hi', 'mom'], 1 )}"}}, + } + + +class TestCliDl: + @pytest.mark.parametrize("config_provided", [True, False]) + @pytest.mark.parametrize("dry_run", [True, False]) + def test_cli_dl_command( + self, + default_config_path: str, + subscription_name: str, + dl_subscription_dict: Dict, + output_directory: str, + mock_download_collection_entries, + config_provided: bool, + dry_run: bool, + ): + # Skip this combo to save time and to avoid mocking working dir + if not config_provided and not dry_run: + return + + # TODO: Fix CLI parsing on windows when dealing with spaces + if IS_WINDOWS: + return + + args = "--dry-run " if dry_run else "" + args += f"--config {default_config_path} " if config_provided else "" + args += f"dl {preset_dict_to_dl_args(dl_subscription_dict)} " + + with ( + patch.object(DownloadArgsParser, "get_dl_subscription_name") as mock_subscription_name, + mock_download_collection_entries( + is_youtube_channel=False, + num_urls=1, + is_extracted_audio=False, + is_dry_run=dry_run, + ), + ): + mock_subscription_name.return_value = subscription_name + subscriptions = mock_run_from_cli(args=args) + + assert_transaction_log_matches( + output_directory=output_directory, + transaction_log=subscriptions[0].transaction_log, + transaction_log_summary_file_name="dl/test_cli_dl_command.txt", + ) + assert_expected_downloads( + output_directory=output_directory, + dry_run=dry_run, + expected_download_summary_file_name="dl/test_cli_dl_command.json", + ) diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 8c0793552..31e7ac51a 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -145,6 +145,8 @@ def _write_entries_to_working_dir(*args, **kwargs) -> List[Dict]: # Second TV URL or second soundcloud URL, which downloads first is_second_url = "2" in kwargs["url"] or kwargs["url"].endswith("/albums") + if num_urls == 0: + return [] if num_urls == 1 or (is_second_url and num_urls > 1): return [ mock_entry_dict_factory( diff --git a/tests/integration/plugins/test_output_options.py b/tests/integration/plugins/test_output_options.py index e834c793b..c8665c1e8 100644 --- a/tests/integration/plugins/test_output_options.py +++ b/tests/integration/plugins/test_output_options.py @@ -1,11 +1,18 @@ +from pathlib import Path from typing import Dict +from unittest.mock import patch import pytest from expected_download import assert_expected_downloads from expected_transaction_log import assert_transaction_log_matches +from mergedeep import mergedeep from ytdl_sub.config.config_file import ConfigFile +from ytdl_sub.downloaders.ytdlp import YTDLP +from ytdl_sub.entries.entry import Entry from ytdl_sub.subscriptions.subscription import Subscription +from ytdl_sub.utils.file_handler import FileHandler +from ytdl_sub.utils.thumbnail import try_convert_download_thumbnail @pytest.fixture @@ -27,6 +34,110 @@ def output_options_subscription_dict(output_directory) -> Dict: class TestOutputOptions: + + @classmethod + def _ensure_subscription_migrates( + cls, + config: ConfigFile, + subscription_name: str, + subscription_dict: Dict, + output_directory: Path, + ): + # Ensure download archive migrates + mergedeep.merge( + subscription_dict, + { + "output_options": { + "migrated_download_archive_name": ".ytdl-sub-{tv_show_name_sanitized}-download-archive.json" + } + }, + ) + migrated_subscription = Subscription.from_dict( + config=config, + preset_name=subscription_name, + preset_dict=subscription_dict, + ) + transaction_log = migrated_subscription.download() + + assert_transaction_log_matches( + output_directory=output_directory, + transaction_log=transaction_log, + transaction_log_summary_file_name="youtube/test_playlist_archive_migrated.txt", + ) + assert_expected_downloads( + output_directory=output_directory, + dry_run=False, + expected_download_summary_file_name="youtube/test_playlist_archive_migrated.json", + ) + + # Ensure no changes after migration + transaction_log = migrated_subscription.download() + assert transaction_log.is_empty + assert_expected_downloads( + output_directory=output_directory, + dry_run=False, + expected_download_summary_file_name="youtube/test_playlist_archive_migrated.json", + ) + + def test_download_archive_migration( + self, + config: ConfigFile, + subscription_name: str, + output_options_subscription_dict: Dict, + output_directory: str, + mock_download_collection_entries, + ): + subscription = Subscription.from_dict( + config=config, + preset_name=subscription_name, + preset_dict=output_options_subscription_dict, + ) + + with mock_download_collection_entries( + is_youtube_channel=False, + num_urls=1, + is_extracted_audio=False, + is_dry_run=False, + ): + transaction_log = subscription.download(dry_run=False) + + assert_transaction_log_matches( + output_directory=output_directory, + transaction_log=transaction_log, + transaction_log_summary_file_name="plugins/output_options/pre_migration.txt", + ) + assert_expected_downloads( + output_directory=output_directory, + dry_run=False, + expected_download_summary_file_name="plugins/output_options/pre_migration.json", + ) + + output_options_subscription_dict["output_options"][ + "migrated_download_archive_name" + ] = ".ytdl-sub-{tv_show_name_sanitized}-migrated-download-archive.json" + subscription = Subscription.from_dict( + config=config, + preset_name=subscription_name, + preset_dict=output_options_subscription_dict, + ) + + with mock_download_collection_entries( + is_youtube_channel=False, + num_urls=0, + ): + transaction_log = subscription.download(dry_run=False) + + assert_transaction_log_matches( + output_directory=output_directory, + transaction_log=transaction_log, + transaction_log_summary_file_name="plugins/output_options/post_migration.txt", + ) + assert_expected_downloads( + output_directory=output_directory, + dry_run=False, + expected_download_summary_file_name="plugins/output_options/post_migration.json", + ) + @pytest.mark.parametrize("dry_run", [True, False]) def test_empty_info_json_and_thumb( self, @@ -64,3 +175,51 @@ def test_empty_info_json_and_thumb( dry_run=dry_run, expected_download_summary_file_name="plugins/output_options/empty_info_json_thumb.json", ) + + def test_missing_thumbnail( + self, + config: ConfigFile, + subscription_name: str, + output_options_subscription_dict: Dict, + working_directory, + output_directory, + mock_download_collection_entries, + ): + single_video_subscription = Subscription.from_dict( + config=config, + preset_name=subscription_name, + preset_dict=output_options_subscription_dict, + ) + + def delete_entry_thumb(entry: Entry) -> None: + FileHandler.delete(entry.get_download_thumbnail_path()) + try_convert_download_thumbnail(entry=entry) + + # Pretend the thumbnail did not download via returning nothing for its downloaded path + with ( + mock_download_collection_entries( + is_youtube_channel=False, + num_urls=1, + is_extracted_audio=False, + is_dry_run=False, + ), + patch.object(YTDLP, "_EXTRACT_ENTRY_NUM_RETRIES", 1), + patch.object(Entry, "try_get_ytdlp_download_thumbnail_path") as mock_ytdlp_path, + patch( + "ytdl_sub.downloaders.url.downloader.try_convert_download_thumbnail", + side_effect=delete_entry_thumb, + ), + ): + mock_ytdlp_path.return_value = None + transaction_log = single_video_subscription.download(dry_run=False) + + assert_transaction_log_matches( + output_directory=output_directory, + transaction_log=transaction_log, + transaction_log_summary_file_name="plugins/output_options/test_missing_thumb.txt", + ) + assert_expected_downloads( + output_directory=output_directory, + dry_run=False, + expected_download_summary_file_name="plugins/output_options/test_missing_thumb.json", + ) diff --git a/tests/resources/expected_downloads_summaries/dl/test_cli_dl_command.json b/tests/resources/expected_downloads_summaries/dl/test_cli_dl_command.json new file mode 100644 index 000000000..ab305abf2 --- /dev/null +++ b/tests/resources/expected_downloads_summaries/dl/test_cli_dl_command.json @@ -0,0 +1,19 @@ +{ + ".ytdl-sub-subscription_test-download-archive.json": "76e202bd03ceef93daaffffee2cfa193", + "JMC/Mock Entry 20-1.info.json": "INFO_JSON", + "JMC/Mock Entry 20-1.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "JMC/Mock Entry 20-1.mp4": "dbaeb2a3bfd1de1c7e9615e8bdacb910", + "JMC/Mock Entry 20-1.nfo": "5d001a105d2380844db181911d5df5c6", + "JMC/Mock Entry 20-2.info.json": "INFO_JSON", + "JMC/Mock Entry 20-2.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "JMC/Mock Entry 20-2.mp4": "76c2c70572489c684923a51cb1b50687", + "JMC/Mock Entry 20-2.nfo": "dccdded1ca7ebb38d2c9a0e5130bea33", + "JMC/Mock Entry 20-3.info.json": "INFO_JSON", + "JMC/Mock Entry 20-3.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "JMC/Mock Entry 20-3.mp4": "7bb4f21d59a6fb91836537b27a24e776", + "JMC/Mock Entry 20-3.nfo": "7b1eab48693161e83c21203b1308b64e", + "JMC/Mock Entry 21-1.info.json": "INFO_JSON", + "JMC/Mock Entry 21-1.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "JMC/Mock Entry 21-1.mp4": "7b008531ca5660b51fb8adc83c799084", + "JMC/Mock Entry 21-1.nfo": "3b4b0e6820f80370d6738ce828f14a89" +} \ No newline at end of file diff --git a/tests/resources/expected_downloads_summaries/plugins/output_options/post_migration.json b/tests/resources/expected_downloads_summaries/plugins/output_options/post_migration.json new file mode 100644 index 000000000..f66f74561 --- /dev/null +++ b/tests/resources/expected_downloads_summaries/plugins/output_options/post_migration.json @@ -0,0 +1,20 @@ +{ + ".ytdl-sub-JMC-migrated-download-archive.json": "456d8882fc5e35d74f19b386d1d9a059", + "Season 2020/s2020.e000001 - Mock Entry 20-3-thumb.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "Season 2020/s2020.e000001 - Mock Entry 20-3.info.json": "INFO_JSON", + "Season 2020/s2020.e000001 - Mock Entry 20-3.mp4": "7d2ee7fe8003ea63ece37dd2a441c123", + "Season 2020/s2020.e000001 - Mock Entry 20-3.nfo": "dbe61f2c8ae41041773f713ba5376726", + "Season 2020/s2020.e000002 - Mock Entry 20-2-thumb.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "Season 2020/s2020.e000002 - Mock Entry 20-2.info.json": "INFO_JSON", + "Season 2020/s2020.e000002 - Mock Entry 20-2.mp4": "699017cd1b67ae216eda769bef413415", + "Season 2020/s2020.e000002 - Mock Entry 20-2.nfo": "0f071078c9fa2569bbcb998664d40681", + "Season 2020/s2020.e000003 - Mock Entry 20-1-thumb.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "Season 2020/s2020.e000003 - Mock Entry 20-1.info.json": "INFO_JSON", + "Season 2020/s2020.e000003 - Mock Entry 20-1.mp4": "a16741d4fbf657d1de4c50493db14062", + "Season 2020/s2020.e000003 - Mock Entry 20-1.nfo": "837a61dca11bbe1874ea07cb8ef8a7c9", + "Season 2021/s2021.e000004 - Mock Entry 21-1-thumb.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "Season 2021/s2021.e000004 - Mock Entry 21-1.info.json": "INFO_JSON", + "Season 2021/s2021.e000004 - Mock Entry 21-1.mp4": "7433153952b069a5674e2a3ed529b49b", + "Season 2021/s2021.e000004 - Mock Entry 21-1.nfo": "8ee3845c514a411425b7e9198666b61c", + "tvshow.nfo": "cccca1086b41af04d8ea004b1aa250e8" +} \ No newline at end of file diff --git a/tests/resources/expected_downloads_summaries/plugins/output_options/pre_migration.json b/tests/resources/expected_downloads_summaries/plugins/output_options/pre_migration.json new file mode 100644 index 000000000..61c1c9245 --- /dev/null +++ b/tests/resources/expected_downloads_summaries/plugins/output_options/pre_migration.json @@ -0,0 +1,20 @@ +{ + ".ytdl-sub-subscription_test-download-archive.json": "456d8882fc5e35d74f19b386d1d9a059", + "Season 2020/s2020.e000001 - Mock Entry 20-3-thumb.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "Season 2020/s2020.e000001 - Mock Entry 20-3.info.json": "INFO_JSON", + "Season 2020/s2020.e000001 - Mock Entry 20-3.mp4": "7d2ee7fe8003ea63ece37dd2a441c123", + "Season 2020/s2020.e000001 - Mock Entry 20-3.nfo": "dbe61f2c8ae41041773f713ba5376726", + "Season 2020/s2020.e000002 - Mock Entry 20-2-thumb.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "Season 2020/s2020.e000002 - Mock Entry 20-2.info.json": "INFO_JSON", + "Season 2020/s2020.e000002 - Mock Entry 20-2.mp4": "699017cd1b67ae216eda769bef413415", + "Season 2020/s2020.e000002 - Mock Entry 20-2.nfo": "0f071078c9fa2569bbcb998664d40681", + "Season 2020/s2020.e000003 - Mock Entry 20-1-thumb.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "Season 2020/s2020.e000003 - Mock Entry 20-1.info.json": "INFO_JSON", + "Season 2020/s2020.e000003 - Mock Entry 20-1.mp4": "a16741d4fbf657d1de4c50493db14062", + "Season 2020/s2020.e000003 - Mock Entry 20-1.nfo": "837a61dca11bbe1874ea07cb8ef8a7c9", + "Season 2021/s2021.e000004 - Mock Entry 21-1-thumb.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "Season 2021/s2021.e000004 - Mock Entry 21-1.info.json": "INFO_JSON", + "Season 2021/s2021.e000004 - Mock Entry 21-1.mp4": "7433153952b069a5674e2a3ed529b49b", + "Season 2021/s2021.e000004 - Mock Entry 21-1.nfo": "8ee3845c514a411425b7e9198666b61c", + "tvshow.nfo": "cccca1086b41af04d8ea004b1aa250e8" +} \ No newline at end of file diff --git a/tests/resources/expected_downloads_summaries/plugins/output_options/test_missing_thumb.json b/tests/resources/expected_downloads_summaries/plugins/output_options/test_missing_thumb.json new file mode 100644 index 000000000..21967d074 --- /dev/null +++ b/tests/resources/expected_downloads_summaries/plugins/output_options/test_missing_thumb.json @@ -0,0 +1,16 @@ +{ + ".ytdl-sub-subscription_test-download-archive.json": "e049068ba7f5bdc27c474b18f4c6b402", + "Season 2020/s2020.e000001 - Mock Entry 20-3.info.json": "INFO_JSON", + "Season 2020/s2020.e000001 - Mock Entry 20-3.mp4": "7d2ee7fe8003ea63ece37dd2a441c123", + "Season 2020/s2020.e000001 - Mock Entry 20-3.nfo": "dbe61f2c8ae41041773f713ba5376726", + "Season 2020/s2020.e000002 - Mock Entry 20-2.info.json": "INFO_JSON", + "Season 2020/s2020.e000002 - Mock Entry 20-2.mp4": "699017cd1b67ae216eda769bef413415", + "Season 2020/s2020.e000002 - Mock Entry 20-2.nfo": "0f071078c9fa2569bbcb998664d40681", + "Season 2020/s2020.e000003 - Mock Entry 20-1.info.json": "INFO_JSON", + "Season 2020/s2020.e000003 - Mock Entry 20-1.mp4": "a16741d4fbf657d1de4c50493db14062", + "Season 2020/s2020.e000003 - Mock Entry 20-1.nfo": "837a61dca11bbe1874ea07cb8ef8a7c9", + "Season 2021/s2021.e000004 - Mock Entry 21-1.info.json": "INFO_JSON", + "Season 2021/s2021.e000004 - Mock Entry 21-1.mp4": "7433153952b069a5674e2a3ed529b49b", + "Season 2021/s2021.e000004 - Mock Entry 21-1.nfo": "8ee3845c514a411425b7e9198666b61c", + "tvshow.nfo": "cccca1086b41af04d8ea004b1aa250e8" +} \ No newline at end of file diff --git a/tests/resources/expected_downloads_summaries/youtube/test_playlist_archive_migrated.json b/tests/resources/expected_downloads_summaries/youtube/test_playlist_archive_migrated.json deleted file mode 100644 index 50f911334..000000000 --- a/tests/resources/expected_downloads_summaries/youtube/test_playlist_archive_migrated.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "JMC/.ytdl-sub-JMC-download-archive.json": "3fdab8d103e51aa70430b6da0ceb07e2", - "JMC/Season 01/s01.e11020101 - Jesse's Minecraft Server [Trailer - Feb.1]-thumb.jpg": "b232d253df621aa770b780c1301d364d", - "JMC/Season 01/s01.e11020101 - Jesse's Minecraft Server [Trailer - Feb.1].info.json": "INFO_JSON", - "JMC/Season 01/s01.e11020101 - Jesse's Minecraft Server [Trailer - Feb.1].mp4": "7fa67dd3a895da12c17669b0fa2f3763", - "JMC/Season 01/s01.e11020101 - Jesse's Minecraft Server [Trailer - Feb.1].nfo": "2a2997cbf16fb6b943d9933ad267331e", - "JMC/Season 01/s01.e11022701 - Jesse's Minecraft Server [Trailer - Feb.27]-thumb.jpg": "d17c379ea8b362f5b97c6b213b0342cb", - "JMC/Season 01/s01.e11022701 - Jesse's Minecraft Server [Trailer - Feb.27].info.json": "INFO_JSON", - "JMC/Season 01/s01.e11022701 - Jesse's Minecraft Server [Trailer - Feb.27].mp4": "5a3ffa5cee2f58f5001502ab3823d130", - "JMC/Season 01/s01.e11022701 - Jesse's Minecraft Server [Trailer - Feb.27].nfo": "da7645e8826586388ae0d8278ef6a1c1", - "JMC/Season 01/s01.e11032101 - Jesse's Minecraft Server [Trailer - Mar.21]-thumb.jpg": "e7830aa8a64b0cde65ba3f7e5fc56530", - "JMC/Season 01/s01.e11032101 - Jesse's Minecraft Server [Trailer - Mar.21].info.json": "INFO_JSON", - "JMC/Season 01/s01.e11032101 - Jesse's Minecraft Server [Trailer - Mar.21].mp4": "91f22944f797513fcda9856e244dd3b3", - "JMC/Season 01/s01.e11032101 - Jesse's Minecraft Server [Trailer - Mar.21].nfo": "c56083e2f3545fa2cafc4d67cbfdacf8", - "JMC/fanart.jpg": "129c6639b47299bc48062f0365e670ee", - "JMC/poster.jpg": "5de28eea5a921a041452ab3ce1041f73", - "JMC/season01-poster.jpg": "e7830aa8a64b0cde65ba3f7e5fc56530", - "JMC/tvshow.nfo": "e92e4a2c01522dd9a9c3423f0f9304dc" -} \ No newline at end of file diff --git a/tests/resources/expected_downloads_summaries/youtube/test_video_cli.json b/tests/resources/expected_downloads_summaries/youtube/test_video_cli.json deleted file mode 100644 index f4690775a..000000000 --- a/tests/resources/expected_downloads_summaries/youtube/test_video_cli.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "JMC/Oblivion Mod "Falcor" p.1.info.json": "INFO_JSON", - "JMC/Oblivion Mod "Falcor" p.1.jpg": "fb95b510681676e81c321171fc23143e", - "JMC/Oblivion Mod "Falcor" p.1.mp4": "318faf3eb1d7666491553cdfd2a2e9fb", - "JMC/Oblivion Mod "Falcor" p.1.nfo": "58c2be339869b5d071c1758d55c72ddb" -} \ No newline at end of file diff --git a/tests/resources/expected_downloads_summaries/youtube/test_video_missing_thumb.json b/tests/resources/expected_downloads_summaries/youtube/test_video_missing_thumb.json deleted file mode 100644 index b1eec149f..000000000 --- a/tests/resources/expected_downloads_summaries/youtube/test_video_missing_thumb.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "JMC/Oblivion Mod "Falcor" p.1.info.json": "INFO_JSON", - "JMC/Oblivion Mod "Falcor" p.1.mp4": "d3bdda5ec6822ea3b4b4bd8908eb327a", - "JMC/Oblivion Mod "Falcor" p.1.nfo": "58c2be339869b5d071c1758d55c72ddb" -} \ No newline at end of file diff --git a/tests/resources/transaction_log_summaries/dl/test_cli_dl_command.txt b/tests/resources/transaction_log_summaries/dl/test_cli_dl_command.txt new file mode 100644 index 000000000..25b8112b0 --- /dev/null +++ b/tests/resources/transaction_log_summaries/dl/test_cli_dl_command.txt @@ -0,0 +1,81 @@ +Files created: +---------------------------------------- +{output_directory} + .ytdl-sub-subscription_test-download-archive.json +{output_directory}/JMC + Mock Entry 20-1.info.json + Mock Entry 20-1.jpg + Mock Entry 20-1.mp4 + Video Tags: + album: Music Videos + artist: JMC + genre: ytdl-sub + premiered: 2020-08-08 + title: Mock Entry 20-1 + year: 2020 + Mock Entry 20-1.nfo + NFO tags: + musicvideo: + album: Music Videos + artist: JMC + custom_tag: mom + genre: ytdl-sub + premiered: 2020-08-08 + title: Mock Entry 20-1 + Mock Entry 20-2.info.json + Mock Entry 20-2.jpg + Mock Entry 20-2.mp4 + Video Tags: + album: Music Videos + artist: JMC + genre: ytdl-sub + premiered: 2020-08-08 + title: Mock Entry 20-2 + year: 2020 + Mock Entry 20-2.nfo + NFO tags: + musicvideo: + album: Music Videos + artist: JMC + custom_tag: mom + genre: ytdl-sub + premiered: 2020-08-08 + title: Mock Entry 20-2 + Mock Entry 20-3.info.json + Mock Entry 20-3.jpg + Mock Entry 20-3.mp4 + Video Tags: + album: Music Videos + artist: JMC + genre: ytdl-sub + premiered: 2020-08-07 + title: Mock Entry 20-3 + year: 2020 + Mock Entry 20-3.nfo + NFO tags: + musicvideo: + album: Music Videos + artist: JMC + custom_tag: mom + genre: ytdl-sub + premiered: 2020-08-07 + title: Mock Entry 20-3 + Mock Entry 21-1.info.json + Mock Entry 21-1.jpg + Mock Entry 21-1.mp4 + Video Tags: + album: Music Videos + artist: JMC + genre: ytdl-sub + premiered: 2021-08-08 + title: Mock Entry 21-1 + year: 2021 + Mock Entry 21-1.nfo + NFO tags: + musicvideo: + album: Music Videos + artist: JMC + custom_tag: mom + genre: ytdl-sub + premiered: 2021-08-08 + title: Mock Entry 21-1 \ No newline at end of file diff --git a/tests/resources/transaction_log_summaries/youtube/test_playlist_archive_migrated.txt b/tests/resources/transaction_log_summaries/plugins/output_options/post_migration.txt similarity index 60% rename from tests/resources/transaction_log_summaries/youtube/test_playlist_archive_migrated.txt rename to tests/resources/transaction_log_summaries/plugins/output_options/post_migration.txt index 056ae6436..9abe6ebad 100644 --- a/tests/resources/transaction_log_summaries/youtube/test_playlist_archive_migrated.txt +++ b/tests/resources/transaction_log_summaries/plugins/output_options/post_migration.txt @@ -1,9 +1,9 @@ Files created: ---------------------------------------- {output_directory} - .ytdl-sub-JMC-download-archive.json + .ytdl-sub-JMC-migrated-download-archive.json Files removed: ---------------------------------------- {output_directory} - .ytdl-sub-music_video_playlist_test-download-archive.json \ No newline at end of file + .ytdl-sub-subscription_test-download-archive.json \ No newline at end of file diff --git a/tests/resources/transaction_log_summaries/plugins/output_options/pre_migration.txt b/tests/resources/transaction_log_summaries/plugins/output_options/pre_migration.txt new file mode 100644 index 000000000..91954dec0 --- /dev/null +++ b/tests/resources/transaction_log_summaries/plugins/output_options/pre_migration.txt @@ -0,0 +1,128 @@ +Files created: +---------------------------------------- +{output_directory} + .ytdl-sub-subscription_test-download-archive.json + tvshow.nfo + NFO tags: + tvshow: + genre: ytdl-sub + mpaa: TV-14 + title: JMC +{output_directory}/Season 2020 + s2020.e000001 - Mock Entry 20-3-thumb.jpg + s2020.e000001 - Mock Entry 20-3.info.json + s2020.e000001 - Mock Entry 20-3.mp4 + Video Tags: + contentRating: TV-14 + date: 2020-08-07 + episode_id: 1 + genre: ytdl-sub + show: JMC + synopsis: + https://20-3.com + + The Description + title: 2020-08-07 - Mock Entry 20-3 + year: 2020 + s2020.e000001 - Mock Entry 20-3.nfo + NFO tags: + episodedetails: + aired: 2020-08-07 + episode: 1 + genre: ytdl-sub + mpaa: TV-14 + plot: + https://20-3.com + + The Description + season: 2020 + title: 2020-08-07 - Mock Entry 20-3 + year: 2020 + s2020.e000002 - Mock Entry 20-2-thumb.jpg + s2020.e000002 - Mock Entry 20-2.info.json + s2020.e000002 - Mock Entry 20-2.mp4 + Video Tags: + contentRating: TV-14 + date: 2020-08-08 + episode_id: 2 + genre: ytdl-sub + show: JMC + synopsis: + https://20-2.com + + The Description + title: 2020-08-08 - Mock Entry 20-2 + year: 2020 + s2020.e000002 - Mock Entry 20-2.nfo + NFO tags: + episodedetails: + aired: 2020-08-08 + episode: 2 + genre: ytdl-sub + mpaa: TV-14 + plot: + https://20-2.com + + The Description + season: 2020 + title: 2020-08-08 - Mock Entry 20-2 + year: 2020 + s2020.e000003 - Mock Entry 20-1-thumb.jpg + s2020.e000003 - Mock Entry 20-1.info.json + s2020.e000003 - Mock Entry 20-1.mp4 + Video Tags: + contentRating: TV-14 + date: 2020-08-08 + episode_id: 3 + genre: ytdl-sub + show: JMC + synopsis: + https://20-1.com + + The Description + title: 2020-08-08 - Mock Entry 20-1 + year: 2020 + s2020.e000003 - Mock Entry 20-1.nfo + NFO tags: + episodedetails: + aired: 2020-08-08 + episode: 3 + genre: ytdl-sub + mpaa: TV-14 + plot: + https://20-1.com + + The Description + season: 2020 + title: 2020-08-08 - Mock Entry 20-1 + year: 2020 +{output_directory}/Season 2021 + s2021.e000004 - Mock Entry 21-1-thumb.jpg + s2021.e000004 - Mock Entry 21-1.info.json + s2021.e000004 - Mock Entry 21-1.mp4 + Video Tags: + contentRating: TV-14 + date: 2021-08-08 + episode_id: 4 + genre: ytdl-sub + show: JMC + synopsis: + https://21-1.com + + The Description + title: 2021-08-08 - Mock Entry 21-1 + year: 2021 + s2021.e000004 - Mock Entry 21-1.nfo + NFO tags: + episodedetails: + aired: 2021-08-08 + episode: 4 + genre: ytdl-sub + mpaa: TV-14 + plot: + https://21-1.com + + The Description + season: 2021 + title: 2021-08-08 - Mock Entry 21-1 + year: 2021 \ No newline at end of file diff --git a/tests/resources/transaction_log_summaries/plugins/output_options/test_missing_thumb.txt b/tests/resources/transaction_log_summaries/plugins/output_options/test_missing_thumb.txt new file mode 100644 index 000000000..7d0a1d587 --- /dev/null +++ b/tests/resources/transaction_log_summaries/plugins/output_options/test_missing_thumb.txt @@ -0,0 +1,124 @@ +Files created: +---------------------------------------- +{output_directory} + .ytdl-sub-subscription_test-download-archive.json + tvshow.nfo + NFO tags: + tvshow: + genre: ytdl-sub + mpaa: TV-14 + title: JMC +{output_directory}/Season 2020 + s2020.e000001 - Mock Entry 20-3.info.json + s2020.e000001 - Mock Entry 20-3.mp4 + Video Tags: + contentRating: TV-14 + date: 2020-08-07 + episode_id: 1 + genre: ytdl-sub + show: JMC + synopsis: + https://20-3.com + + The Description + title: 2020-08-07 - Mock Entry 20-3 + year: 2020 + s2020.e000001 - Mock Entry 20-3.nfo + NFO tags: + episodedetails: + aired: 2020-08-07 + episode: 1 + genre: ytdl-sub + mpaa: TV-14 + plot: + https://20-3.com + + The Description + season: 2020 + title: 2020-08-07 - Mock Entry 20-3 + year: 2020 + s2020.e000002 - Mock Entry 20-2.info.json + s2020.e000002 - Mock Entry 20-2.mp4 + Video Tags: + contentRating: TV-14 + date: 2020-08-08 + episode_id: 2 + genre: ytdl-sub + show: JMC + synopsis: + https://20-2.com + + The Description + title: 2020-08-08 - Mock Entry 20-2 + year: 2020 + s2020.e000002 - Mock Entry 20-2.nfo + NFO tags: + episodedetails: + aired: 2020-08-08 + episode: 2 + genre: ytdl-sub + mpaa: TV-14 + plot: + https://20-2.com + + The Description + season: 2020 + title: 2020-08-08 - Mock Entry 20-2 + year: 2020 + s2020.e000003 - Mock Entry 20-1.info.json + s2020.e000003 - Mock Entry 20-1.mp4 + Video Tags: + contentRating: TV-14 + date: 2020-08-08 + episode_id: 3 + genre: ytdl-sub + show: JMC + synopsis: + https://20-1.com + + The Description + title: 2020-08-08 - Mock Entry 20-1 + year: 2020 + s2020.e000003 - Mock Entry 20-1.nfo + NFO tags: + episodedetails: + aired: 2020-08-08 + episode: 3 + genre: ytdl-sub + mpaa: TV-14 + plot: + https://20-1.com + + The Description + season: 2020 + title: 2020-08-08 - Mock Entry 20-1 + year: 2020 +{output_directory}/Season 2021 + s2021.e000004 - Mock Entry 21-1.info.json + s2021.e000004 - Mock Entry 21-1.mp4 + Video Tags: + contentRating: TV-14 + date: 2021-08-08 + episode_id: 4 + genre: ytdl-sub + show: JMC + synopsis: + https://21-1.com + + The Description + title: 2021-08-08 - Mock Entry 21-1 + year: 2021 + s2021.e000004 - Mock Entry 21-1.nfo + NFO tags: + episodedetails: + aired: 2021-08-08 + episode: 4 + genre: ytdl-sub + mpaa: TV-14 + plot: + https://21-1.com + + The Description + season: 2021 + title: 2021-08-08 - Mock Entry 21-1 + year: 2021 \ No newline at end of file diff --git a/tests/resources/transaction_log_summaries/youtube/test_video_cli.txt b/tests/resources/transaction_log_summaries/youtube/test_video_cli.txt deleted file mode 100644 index 97392956a..000000000 --- a/tests/resources/transaction_log_summaries/youtube/test_video_cli.txt +++ /dev/null @@ -1,22 +0,0 @@ -Files created: ----------------------------------------- -{output_directory}/JMC - Oblivion Mod "Falcor" p.1.info.json - Oblivion Mod "Falcor" p.1.jpg - Oblivion Mod "Falcor" p.1.mp4 - Video Tags: - album: Music Videos - artist: JMC - genre: ytdl-sub - premiered: 2010-08-13 - title: Oblivion Mod "Falcor" p.1 - year: 2010 - Embedded thumbnail - Oblivion Mod "Falcor" p.1.nfo - NFO tags: - musicvideo: - album: Music Videos - artist: JMC - genre: ytdl-sub - premiered: 2010-08-13 - title: Oblivion Mod "Falcor" p.1 \ No newline at end of file diff --git a/tests/resources/transaction_log_summaries/youtube/test_video_missing_thumb.txt b/tests/resources/transaction_log_summaries/youtube/test_video_missing_thumb.txt deleted file mode 100644 index ccd7b91cc..000000000 --- a/tests/resources/transaction_log_summaries/youtube/test_video_missing_thumb.txt +++ /dev/null @@ -1,20 +0,0 @@ -Files created: ----------------------------------------- -{output_directory}/JMC - Oblivion Mod "Falcor" p.1.info.json - Oblivion Mod "Falcor" p.1.mp4 - Video Tags: - album: Music Videos - artist: JMC - genre: ytdl-sub - premiered: 2010-08-13 - title: Oblivion Mod "Falcor" p.1 - year: 2010 - Oblivion Mod "Falcor" p.1.nfo - NFO tags: - musicvideo: - album: Music Videos - artist: JMC - genre: ytdl-sub - premiered: 2010-08-13 - title: Oblivion Mod "Falcor" p.1 \ No newline at end of file diff --git a/tests/unit/config/test_subscription.py b/tests/unit/config/test_subscription.py index 574da0704..8fbfac158 100644 --- a/tests/unit/config/test_subscription.py +++ b/tests/unit/config/test_subscription.py @@ -186,6 +186,7 @@ def preset_with_subscription_overrides_map( "elem2", "elem3", ], + "custom_map": {"custom_map_key": ["custom_map_list_value"]}, } }, }, @@ -290,6 +291,7 @@ def test_subscription_overrides_map( "elem2", "elem3", ], + "custom_map": {"custom_map_key": ["custom_map_list_value"]}, }