From 5e9472986a2dea11b3d5140cc544c808c7b37879 Mon Sep 17 00:00:00 2001 From: Jesse Bannon Date: Thu, 6 Jun 2024 11:50:33 -0700 Subject: [PATCH] [FEATURE] Enhance music video presets using specialized map syntax (#808) Enhances the music video presets by supporting the following syntax: `subscriptions.yaml` ``` __preset__: overrides: music_video_directory: "/music_videos" # Choose between Jellyfin/Kodi/Plex Music Videos preset: # - Plex Music Videos: # - Jellyfin Music Videos: # - Kodi Music Videos: # "Plex Music Videos": = Pop: # Sets genre tag to "Pop" "Rick Astley": "https://www.youtube.com/playlist?list=PLlaN88a7y2_plecYoJxvRFTLHVbIVAOoc" "Michael Jackson": "https://www.youtube.com/playlist?list=OLAK5uy_mnY03zP6abNWH929q2XhGzWD_2uKJ_n8E" = Rock: # Prefixing with '+' puts the subscription into 'map-mode'. # Music video presets in map-mode support grouping videos into different # categories, which get set on the album field. # # URLs can either be strings, or maps that can overload title, year, date "+ Guns N' Roses": Music Videos: - "https://www.youtube.com/playlist?list=PLOTK54q5K4INNXaHKtmXYr6J7CajWjqeJ" Concerts: - title: "Live at The Ritz - New York City" year: "1988" url: "https://www.youtube.com/watch?v=OldpIhHPsbs" - title: "Live at The Hollywood Bowl" date: "2023-01-11" url: "https://www.youtube.com/watch?v=Z7hutGlvq9I" ``` The 'map-mode' (denoted by `+`) lets you specify a map of music video categories. Under each category, a URL can be specified as-is or with additional metadata (title, year/date, url). Music videos and concerts, especially older ones, are typically uploaded by random users with inconsistencies in their titles. This syntax aims to make it easy to specify individual URLs with the ability to overwrite their title and year, and group them by category. --- .../scripting/static_variables.rst | 12 + examples/music_video_subscriptions.yaml | 26 ++- .../entries/variables/override_variables.py | 16 ++ .../prebuilt_presets/helpers/url.yaml | 1 + .../helpers/url_categorized.yaml | 210 ++++++++++++++++++ .../prebuilt_presets/music_videos/__init__.py | 8 + .../music_videos/music_video_base.yaml | 39 +++- .../music_videos/music_video_extras.yaml | 58 +++++ .../subscriptions/subscription_validators.py | 19 +- src/ytdl_sub/utils/script.py | 4 +- .../multi_url_False.json | 19 ++ .../multi_url_True.json | 23 ++ .../multi_url_False.json | 19 ++ .../multi_url_True.json | 23 ++ .../multi_url_False.json | 15 ++ .../multi_url_True.json | 18 ++ .../multi_url_False.txt | 77 +++++++ .../multi_url_True.txt | 95 ++++++++ .../multi_url_False.txt | 77 +++++++ .../multi_url_True.txt | 95 ++++++++ .../multi_url_False.txt | 45 ++++ .../multi_url_True.txt | 55 +++++ tests/unit/cli/test_entrypoint.py | 2 +- tests/unit/config/test_subscription.py | 35 ++- .../prebuilt_presets/test_prebuilt_presets.py | 91 ++++++++ 25 files changed, 1064 insertions(+), 18 deletions(-) create mode 100644 src/ytdl_sub/prebuilt_presets/helpers/url_categorized.yaml create mode 100644 src/ytdl_sub/prebuilt_presets/music_videos/music_video_extras.yaml create mode 100644 tests/resources/expected_downloads_summaries/unit/music_videos/Jellyfin Music Videos Categorized/multi_url_False.json create mode 100644 tests/resources/expected_downloads_summaries/unit/music_videos/Jellyfin Music Videos Categorized/multi_url_True.json create mode 100644 tests/resources/expected_downloads_summaries/unit/music_videos/Kodi Music Videos Categorized/multi_url_False.json create mode 100644 tests/resources/expected_downloads_summaries/unit/music_videos/Kodi Music Videos Categorized/multi_url_True.json create mode 100644 tests/resources/expected_downloads_summaries/unit/music_videos/Plex Music Videos Categorized/multi_url_False.json create mode 100644 tests/resources/expected_downloads_summaries/unit/music_videos/Plex Music Videos Categorized/multi_url_True.json create mode 100644 tests/resources/transaction_log_summaries/unit/music_videos/Jellyfin Music Videos Categorized/multi_url_False.txt create mode 100644 tests/resources/transaction_log_summaries/unit/music_videos/Jellyfin Music Videos Categorized/multi_url_True.txt create mode 100644 tests/resources/transaction_log_summaries/unit/music_videos/Kodi Music Videos Categorized/multi_url_False.txt create mode 100644 tests/resources/transaction_log_summaries/unit/music_videos/Kodi Music Videos Categorized/multi_url_True.txt create mode 100644 tests/resources/transaction_log_summaries/unit/music_videos/Plex Music Videos Categorized/multi_url_False.txt create mode 100644 tests/resources/transaction_log_summaries/unit/music_videos/Plex Music Videos Categorized/multi_url_True.txt diff --git a/docs/source/config_reference/scripting/static_variables.rst b/docs/source/config_reference/scripting/static_variables.rst index 2825edba..9a90e761 100644 --- a/docs/source/config_reference/scripting/static_variables.rst +++ b/docs/source/config_reference/scripting/static_variables.rst @@ -5,6 +5,18 @@ Static Variables Subscription Variables ---------------------- +subscription_array +~~~~~~~~~~~~~~~~~~ +For subscriptions in the form of + +.. code-block:: yaml + + "Subscription Name": + - "https://url1.com/..." + - "https://url2.com/..." + +Store all values into an array named ``subscription_array``. + subscription_has_download_archive ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Returns True if the subscription has any entries recorded in a download archive. False diff --git a/examples/music_video_subscriptions.yaml b/examples/music_video_subscriptions.yaml index 330d1ef9..fb600b69 100644 --- a/examples/music_video_subscriptions.yaml +++ b/examples/music_video_subscriptions.yaml @@ -14,12 +14,32 @@ __preset__: overrides: music_video_directory: "/music_videos" -# Choose between Jellyfin/Kodi/Plex Music Videos -# "Jellyfin Music Videos": -# "Kodi Music Videos": +# Choose between Jellyfin/Kodi/Plex Music Videos preset: +# - Plex Music Videos: +# - Jellyfin Music Videos: +# - Kodi Music Videos: "Plex Music Videos": + = Pop: # Sets genre tag to "Pop" "Rick Astley": "https://www.youtube.com/playlist?list=PLlaN88a7y2_plecYoJxvRFTLHVbIVAOoc" "Michael Jackson": "https://www.youtube.com/playlist?list=OLAK5uy_mnY03zP6abNWH929q2XhGzWD_2uKJ_n8E" + = Blues: "Eric Clapton": "https://www.youtube.com/playlist?list=PLABGggHhsbEeaRtdzqnxYoEINsJE_4GF4" + + = Rock: + # Prefixing with '+' puts the subscription into 'map-mode'. + # Music video presets in map-mode support grouping videos into different + # categories, which get set on the album field. + # + # URLs can either be strings, or maps that can overload title, year, date + "+ Guns N' Roses": + Music Videos: + - "https://www.youtube.com/playlist?list=PLOTK54q5K4INNXaHKtmXYr6J7CajWjqeJ" + Concerts: + - title: "Live at The Ritz - New York City" + year: "1988" + url: "https://www.youtube.com/watch?v=OldpIhHPsbs" + - title: "Live at The Hollywood Bowl" + date: "2023-01-11" + url: "https://www.youtube.com/watch?v=Z7hutGlvq9I" \ No newline at end of file diff --git a/src/ytdl_sub/entries/variables/override_variables.py b/src/ytdl_sub/entries/variables/override_variables.py index 68ec72d4..42bb4498 100644 --- a/src/ytdl_sub/entries/variables/override_variables.py +++ b/src/ytdl_sub/entries/variables/override_variables.py @@ -3,6 +3,7 @@ from typing import Set from ytdl_sub.entries.script.function_scripts import CUSTOM_FUNCTION_SCRIPTS from ytdl_sub.entries.script.variable_definitions import VARIABLE_SCRIPTS +from ytdl_sub.entries.script.variable_types import ArrayVariable from ytdl_sub.entries.script.variable_types import BooleanVariable from ytdl_sub.entries.script.variable_types import MapVariable from ytdl_sub.entries.script.variable_types import StringVariable @@ -36,6 +37,21 @@ class SubscriptionVariables: """ return StringVariable(variable_name="subscription_value", definition="{ %string('') }") + @staticmethod + def subscription_array() -> ArrayVariable: + """ + For subscriptions in the form of + + .. code-block:: yaml + + "Subscription Name": + - "https://url1.com/..." + - "https://url2.com/..." + + Store all values into an array named ``subscription_array``. + """ + return ArrayVariable(variable_name="subscription_array", definition="{ [] }") + @staticmethod def subscription_indent_i(index: int) -> StringVariable: """ diff --git a/src/ytdl_sub/prebuilt_presets/helpers/url.yaml b/src/ytdl_sub/prebuilt_presets/helpers/url.yaml index 3a9726dd..7fc1d9ad 100644 --- a/src/ytdl_sub/prebuilt_presets/helpers/url.yaml +++ b/src/ytdl_sub/prebuilt_presets/helpers/url.yaml @@ -129,6 +129,7 @@ presets: avatar_uncropped_thumbnail_file_name: "" banner_uncropped_thumbnail_file_name: "" + subscription_array: "{ [] }" subscription_value: "" subscription_value_2: "" subscription_value_3: "" diff --git a/src/ytdl_sub/prebuilt_presets/helpers/url_categorized.yaml b/src/ytdl_sub/prebuilt_presets/helpers/url_categorized.yaml new file mode 100644 index 00000000..b212f640 --- /dev/null +++ b/src/ytdl_sub/prebuilt_presets/helpers/url_categorized.yaml @@ -0,0 +1,210 @@ +presets: + # Preset for categorizing URls like so + # + # subscription_name: + # category_1: + # - https://...1 + # - https://...2 + # category_2: + # - url: https://...1 + # metadata_field_1: 2011 + # metadata_field_2: 'abc" + # ... + # + # Metadata field of `url` must exist, other ones can be anything. + # Only supports a single level of nesting. + _url_categorized: + preset: + - "_multi_url_bilateral" + + overrides: + # Parameters: + # $0: url string or map containing url + metadata fields + # $1: category key + # + # Output: + # Map containing { url: ..., category: ..., metadata_field_1: ... } + "%flat_array__url_to_map_format": >- + { + %elif( + %is_map($0), + %map_extend( $0, { "category": $1 } ), + %is_string($0), + { "url": $0, "category": $1 }, + %throw("If using album categories, each URL must be either a string or map with metadata fields") + ) + } + + # Parameters: + # $0: category key + # $1: array of URLs in either string or map form + # + # Output: + # Array containing [{ url: ..., category: ... }, ... ] + "%flat_array__category_to_map_format": >- + { + %array_apply_fixed( + %assert_then( + %is_array( $1 ), + $1, + "If using album categories, each category must map to an array" + ), + $0, + %flat_array__url_to_map_format + ) + } + + # Parameters: + # $0: map containing fields { url: , category: ... } + # + # Output: + # Nested map containing { : { url: , category: ... } } + "%flat_array__url_keyed_map_format": >- + { { %map_get($0, "url"): $0 } } + + # Creates an array in the form of [ { url: ..., category: ..., metadata_field_1: ... }, ... ] + category_url_array: >- + { %array_flatten( %map_apply( subscription_map, %flat_array__category_to_map_format ) ) } + + # Creates a map in the form of { : { category: ..., metadata_field_1: ... }, ... } + category_url_map: >- + { + %array_reduce( + %array_apply( category_url_array, %flat_array__url_keyed_map_format ), + %map_extend + ) + } + + # Parameters: + # $0: metadata field to fetch for the current url + # $1: default value + # + # Output: + # Metadata field value if it exists. Otherwise, return default value + "%get_url_field": >- + { %map_get( %map( %map_get( category_url_map, ytdl_sub_input_url, {} ) ), $0, $1 ) } + + # Parameters: + # $0: metadata field to fetch for the current url + # + # Output: + # True if field is specified. False otherwise. + "%contains_url_field": >- + { %not( %is_null( %get_url_field( $0, null ) ) ) } + + + # Parameters: + # $0: integer to fetch the i'th url using 1-based indexing + # + # Output: + # i'th url in the category map + "%get_url_i": >- + { + %map_get( + %map( %array_at( category_url_array, %int( %sub($0, 1) ), {} ) ), + "url", + %array_at(subscription_array, %int( %sub($0, 1) ), null) + ) + } + + subscription_map: "{ {} }" + url: "{ %get_url_i(1) }" + url2: "{ %get_url_i(2) }" + url3: "{ %get_url_i(3) }" + url4: "{ %get_url_i(4) }" + url5: "{ %get_url_i(5) }" + url6: "{ %get_url_i(6) }" + url7: "{ %get_url_i(7) }" + url8: "{ %get_url_i(8) }" + url9: "{ %get_url_i(9) }" + url10: "{ %get_url_i(10) }" + url11: "{ %get_url_i(11) }" + url12: "{ %get_url_i(12) }" + url13: "{ %get_url_i(13) }" + url14: "{ %get_url_i(14) }" + url15: "{ %get_url_i(15) }" + url16: "{ %get_url_i(16) }" + url17: "{ %get_url_i(17) }" + url18: "{ %get_url_i(18) }" + url19: "{ %get_url_i(19) }" + url20: "{ %get_url_i(20) }" + url21: "{ %get_url_i(21) }" + url22: "{ %get_url_i(22) }" + url23: "{ %get_url_i(23) }" + url24: "{ %get_url_i(24) }" + url25: "{ %get_url_i(25) }" + url26: "{ %get_url_i(26) }" + url27: "{ %get_url_i(27) }" + url28: "{ %get_url_i(28) }" + url29: "{ %get_url_i(29) }" + url30: "{ %get_url_i(30) }" + url31: "{ %get_url_i(31) }" + url32: "{ %get_url_i(32) }" + url33: "{ %get_url_i(33) }" + url34: "{ %get_url_i(34) }" + url35: "{ %get_url_i(35) }" + url36: "{ %get_url_i(36) }" + url37: "{ %get_url_i(37) }" + url38: "{ %get_url_i(38) }" + url39: "{ %get_url_i(39) }" + url40: "{ %get_url_i(40) }" + url41: "{ %get_url_i(41) }" + url42: "{ %get_url_i(42) }" + url43: "{ %get_url_i(43) }" + url44: "{ %get_url_i(44) }" + url45: "{ %get_url_i(45) }" + url46: "{ %get_url_i(46) }" + url47: "{ %get_url_i(47) }" + url48: "{ %get_url_i(48) }" + url49: "{ %get_url_i(49) }" + url50: "{ %get_url_i(50) }" + url51: "{ %get_url_i(51) }" + url52: "{ %get_url_i(52) }" + url53: "{ %get_url_i(53) }" + url54: "{ %get_url_i(54) }" + url55: "{ %get_url_i(55) }" + url56: "{ %get_url_i(56) }" + url57: "{ %get_url_i(57) }" + url58: "{ %get_url_i(58) }" + url59: "{ %get_url_i(59) }" + url60: "{ %get_url_i(60) }" + url61: "{ %get_url_i(61) }" + url62: "{ %get_url_i(62) }" + url63: "{ %get_url_i(63) }" + url64: "{ %get_url_i(64) }" + url65: "{ %get_url_i(65) }" + url66: "{ %get_url_i(66) }" + url67: "{ %get_url_i(67) }" + url68: "{ %get_url_i(68) }" + url69: "{ %get_url_i(69) }" + url70: "{ %get_url_i(70) }" + url71: "{ %get_url_i(71) }" + url72: "{ %get_url_i(72) }" + url73: "{ %get_url_i(73) }" + url74: "{ %get_url_i(74) }" + url75: "{ %get_url_i(75) }" + url76: "{ %get_url_i(76) }" + url77: "{ %get_url_i(77) }" + url78: "{ %get_url_i(78) }" + url79: "{ %get_url_i(79) }" + url80: "{ %get_url_i(80) }" + url81: "{ %get_url_i(81) }" + url82: "{ %get_url_i(82) }" + url83: "{ %get_url_i(83) }" + url84: "{ %get_url_i(84) }" + url85: "{ %get_url_i(85) }" + url86: "{ %get_url_i(86) }" + url87: "{ %get_url_i(87) }" + url88: "{ %get_url_i(88) }" + url89: "{ %get_url_i(89) }" + url90: "{ %get_url_i(90) }" + url91: "{ %get_url_i(91) }" + url92: "{ %get_url_i(92) }" + url93: "{ %get_url_i(93) }" + url94: "{ %get_url_i(94) }" + url95: "{ %get_url_i(95) }" + url96: "{ %get_url_i(96) }" + url97: "{ %get_url_i(97) }" + url98: "{ %get_url_i(98) }" + url99: "{ %get_url_i(99) }" + url100: "{ %get_url_i(100) }" \ No newline at end of file diff --git a/src/ytdl_sub/prebuilt_presets/music_videos/__init__.py b/src/ytdl_sub/prebuilt_presets/music_videos/__init__.py index 7338b591..ae128998 100644 --- a/src/ytdl_sub/prebuilt_presets/music_videos/__init__.py +++ b/src/ytdl_sub/prebuilt_presets/music_videos/__init__.py @@ -10,3 +10,11 @@ class MusicVideoPresets(PrebuiltPresets): "Jellyfin Music Videos", "Plex Music Videos", } + + +class MusicVideoExtrasPresets(PrebuiltPresets): + preset_names = { + "Kodi Music Videos with Extras", + "Jellyfin Music Videos with Extras", + "Plex Music Videos with Extras", + } diff --git a/src/ytdl_sub/prebuilt_presets/music_videos/music_video_base.yaml b/src/ytdl_sub/prebuilt_presets/music_videos/music_video_base.yaml index ac810745..25b97697 100644 --- a/src/ytdl_sub/prebuilt_presets/music_videos/music_video_base.yaml +++ b/src/ytdl_sub/prebuilt_presets/music_videos/music_video_base.yaml @@ -1,7 +1,8 @@ presets: _music_video_base: + preset: - - "_multi_url" + - "_url_categorized" output_options: output_directory: "{music_video_directory}" @@ -25,12 +26,38 @@ presets: subscription_indent_1: "{music_video_genre_default}" # Music Video Overrides - music_video_title: "{title}" - music_video_album: "{music_video_album_default}" music_video_artist: "{subscription_name}" - music_video_year: "{upload_year}" - music_video_date: "{upload_date_standardized}" music_video_genre: "{subscription_indent_1}" + music_video_album: >- + { %get_url_field("category", music_video_album_default) } + music_video_title: >- + { %get_url_field("title", title) } + music_video_date: >- + { + %elif( + %contains_url_field("date"), + %get_url_field("date", upload_date_standardized), + + %contains_url_field("year"), + %concat( %get_url_field("date", upload_year), "-01-01"), + + upload_date_standardized + ) + } + music_video_year: >- + { + %int(%elif( + %contains_url_field("date"), + %slice( %get_url_field("date", upload_date_standardized), 0, 4 ), + + %contains_url_field("year"), + %get_url_field("date", upload_year), + + upload_year + )) + } + # Directory Overrides - music_video_file_name: "{music_video_artist_sanitized}/{music_video_title_sanitized}" \ No newline at end of file + music_video_file_name_suffix: "" + music_video_file_name: "{music_video_artist_sanitized}/{music_video_title_sanitized}{music_video_file_name_suffix}" diff --git a/src/ytdl_sub/prebuilt_presets/music_videos/music_video_extras.yaml b/src/ytdl_sub/prebuilt_presets/music_videos/music_video_extras.yaml new file mode 100644 index 00000000..e292deea --- /dev/null +++ b/src/ytdl_sub/prebuilt_presets/music_videos/music_video_extras.yaml @@ -0,0 +1,58 @@ +# +# Kodi Music Videos with Extras: +# + Rick Astley: +# Music Videos: +# - url1 +# - url2 +# ... +# Concerts: +# - url: asfasdfasdf +# year: 2023 +# title: sdfasff +# exclude: asdffsdf +# - url4 +# Extras: +# - url5 +# - url6 +# Behind The Scenes: +# - ... +# Live: +# - ... +# Lyrics: +# - ... + +presets: + _music_video_extras_base: + preset: + - "_url_categorized" + - "_music_video_base" + + overrides: + music_video_album: >- + { %get_url_field("category", music_video_album_default) } + music_video_title: >- + { %get_url_field("title", title) } + + "Jellyfin Music Videos with Extras": + preset: + - "_base" + - "_music_video_extras_base" + - "_music_video_nfo" + - "_music_video_tags" + + "Kodi Music Videos with Extras": + preset: + - "_kodi_base" + - "_music_video_extras_base" + - "_music_video_nfo" + - "_music_video_tags" + + "Plex Music Videos with Extras": + preset: + - "_plex_video_base" + - "_music_video_extras_base" + - "_music_video_tags" + +# overrides: +# metadata_verify_plex_suffix: "{url_metadata}" +# music_video_file_name_suffix: "-{music_video_album}" \ No newline at end of file diff --git a/src/ytdl_sub/subscriptions/subscription_validators.py b/src/ytdl_sub/subscriptions/subscription_validators.py index 5994c218..35bbbcb7 100644 --- a/src/ytdl_sub/subscriptions/subscription_validators.py +++ b/src/ytdl_sub/subscriptions/subscription_validators.py @@ -143,10 +143,21 @@ class SubscriptionValueValidator(SubscriptionLeafValidator, StringValidator): presets=presets, indent_overrides=indent_overrides, ) + # subscription_value self._overrides_to_add[SubscriptionVariables.subscription_value().variable_name] = ( self.value ) + # subscription_value_0 + self._overrides_to_add[ + SubscriptionVariables.subscription_value_i(index=0).variable_name + ] = self.value + + # And the array variable + self._overrides_to_add[SubscriptionVariables.subscription_array().variable_name] = ( + ScriptUtils.to_script([self.value]) + ) + class SubscriptionListValuesValidator(SubscriptionLeafValidator, StringListValidator): def __init__( @@ -167,6 +178,7 @@ class SubscriptionListValuesValidator(SubscriptionLeafValidator, StringListValid indent_overrides=indent_overrides, ) + # Add indexed variables for idx, list_value in enumerate(self.list): # Write the first list value into subscription_value as well if idx == 0: @@ -178,6 +190,11 @@ class SubscriptionListValuesValidator(SubscriptionLeafValidator, StringListValid SubscriptionVariables.subscription_value_i(index=idx).variable_name ] = list_value.value + # And the array variable + self._overrides_to_add[SubscriptionVariables.subscription_array().variable_name] = ( + ScriptUtils.to_script([list_value.value for list_value in self.list]) + ) + class SubscriptionWithOverridesValidator(SubscriptionLeafValidator, DictFormatterValidator): def __init__( @@ -220,7 +237,7 @@ class SubscriptionMapValidator(SubscriptionLeafValidator, LiteralDictValidator): indent_overrides=indent_overrides, ) self._overrides_to_add[SubscriptionVariables.subscription_map().variable_name] = ( - ScriptUtils.to_script(self.dict) + ScriptUtils.to_script(self.dict, sort_keys=False) ) diff --git a/src/ytdl_sub/utils/script.py b/src/ytdl_sub/utils/script.py index fba88a35..e3a17b2f 100644 --- a/src/ytdl_sub/utils/script.py +++ b/src/ytdl_sub/utils/script.py @@ -35,7 +35,7 @@ class ScriptUtils: return dict(variables, **sanitized_variables) @classmethod - def to_script(cls, value: Any) -> str: + def to_script(cls, value: Any, sort_keys: bool = True) -> str: """ Converts a python value to a script value """ @@ -50,7 +50,7 @@ class ScriptUtils: elif isinstance(value, float): out = f"{{%float({value})}}" else: - dumped_json = json.dumps(value, ensure_ascii=False, sort_keys=True) + dumped_json = json.dumps(value, ensure_ascii=False, sort_keys=sort_keys) # Remove triple-single-quotes from JSON to avoid parsing issues dumped_json = re.sub("'{3,}", "'", dumped_json) diff --git a/tests/resources/expected_downloads_summaries/unit/music_videos/Jellyfin Music Videos Categorized/multi_url_False.json b/tests/resources/expected_downloads_summaries/unit/music_videos/Jellyfin Music Videos Categorized/multi_url_False.json new file mode 100644 index 00000000..72e4fbce --- /dev/null +++ b/tests/resources/expected_downloads_summaries/unit/music_videos/Jellyfin Music Videos Categorized/multi_url_False.json @@ -0,0 +1,19 @@ +{ + ".ytdl-sub-subscription_test-download-archive.json": "b98a30417f259daeec888e1a5047b9ed", + "subscription_test/Mock Entry 20-1.info.json": "INFO_JSON", + "subscription_test/Mock Entry 20-1.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 20-1.mp4": "34916dc26e723c3464adcc4687898ca8", + "subscription_test/Mock Entry 20-1.nfo": "68a6a9e51a12e75d4c68e6e644b409d1", + "subscription_test/Mock Entry 20-2.info.json": "INFO_JSON", + "subscription_test/Mock Entry 20-2.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 20-2.mp4": "01a910b7a023325aa9d4ad3a013a1e02", + "subscription_test/Mock Entry 20-2.nfo": "1cbe51945c1a7a9ced0eb1222e9d2405", + "subscription_test/Mock Entry 20-3.info.json": "INFO_JSON", + "subscription_test/Mock Entry 20-3.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 20-3.mp4": "812b6db9ff08bf1822e99e43d371400d", + "subscription_test/Mock Entry 20-3.nfo": "ef07f30d3e882de3f7cb3ad675125352", + "subscription_test/Mock Entry 21-1.info.json": "INFO_JSON", + "subscription_test/Mock Entry 21-1.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 21-1.mp4": "079832b6e49b283d80be402c9c928b90", + "subscription_test/Mock Entry 21-1.nfo": "dc714fd9f3c3729f74927ad245b50d9d" +} \ No newline at end of file diff --git a/tests/resources/expected_downloads_summaries/unit/music_videos/Jellyfin Music Videos Categorized/multi_url_True.json b/tests/resources/expected_downloads_summaries/unit/music_videos/Jellyfin Music Videos Categorized/multi_url_True.json new file mode 100644 index 00000000..ced3db94 --- /dev/null +++ b/tests/resources/expected_downloads_summaries/unit/music_videos/Jellyfin Music Videos Categorized/multi_url_True.json @@ -0,0 +1,23 @@ +{ + ".ytdl-sub-subscription_test-download-archive.json": "bcb2e8e8139f5bf589e027f841aa9449", + "subscription_test/Custom Title.info.json": "INFO_JSON", + "subscription_test/Custom Title.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Custom Title.mp4": "d7c2b8e961a8fcb612bd0d69c96bf0f3", + "subscription_test/Custom Title.nfo": "996f3993b2ba8a0614bef294492dde65", + "subscription_test/Mock Entry 20-4.info.json": "INFO_JSON", + "subscription_test/Mock Entry 20-4.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 20-4.mp4": "10f239edf916f8fb9eb461f24a821578", + "subscription_test/Mock Entry 20-4.nfo": "1e7cb1a09c15f155623f6cd796e874ff", + "subscription_test/Mock Entry 20-5.info.json": "INFO_JSON", + "subscription_test/Mock Entry 20-5.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 20-5.mp4": "046878a073fb269ec61401cdeb834707", + "subscription_test/Mock Entry 20-5.nfo": "f6100f194ae3c3b24211ff515d97ccdf", + "subscription_test/Mock Entry 20-6.info.json": "INFO_JSON", + "subscription_test/Mock Entry 20-6.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 20-6.mp4": "a50ead5d08456f0bcb907f1912caefcf", + "subscription_test/Mock Entry 20-6.nfo": "f51ae05104f5b98531535e75d623f941", + "subscription_test/Mock Entry 20-7.info.json": "INFO_JSON", + "subscription_test/Mock Entry 20-7.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 20-7.mp4": "5b35f04254c38c33ba056274b6c3af9f", + "subscription_test/Mock Entry 20-7.nfo": "852c02ea3ab196d808854ee94a9313d2" +} \ No newline at end of file diff --git a/tests/resources/expected_downloads_summaries/unit/music_videos/Kodi Music Videos Categorized/multi_url_False.json b/tests/resources/expected_downloads_summaries/unit/music_videos/Kodi Music Videos Categorized/multi_url_False.json new file mode 100644 index 00000000..72e4fbce --- /dev/null +++ b/tests/resources/expected_downloads_summaries/unit/music_videos/Kodi Music Videos Categorized/multi_url_False.json @@ -0,0 +1,19 @@ +{ + ".ytdl-sub-subscription_test-download-archive.json": "b98a30417f259daeec888e1a5047b9ed", + "subscription_test/Mock Entry 20-1.info.json": "INFO_JSON", + "subscription_test/Mock Entry 20-1.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 20-1.mp4": "34916dc26e723c3464adcc4687898ca8", + "subscription_test/Mock Entry 20-1.nfo": "68a6a9e51a12e75d4c68e6e644b409d1", + "subscription_test/Mock Entry 20-2.info.json": "INFO_JSON", + "subscription_test/Mock Entry 20-2.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 20-2.mp4": "01a910b7a023325aa9d4ad3a013a1e02", + "subscription_test/Mock Entry 20-2.nfo": "1cbe51945c1a7a9ced0eb1222e9d2405", + "subscription_test/Mock Entry 20-3.info.json": "INFO_JSON", + "subscription_test/Mock Entry 20-3.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 20-3.mp4": "812b6db9ff08bf1822e99e43d371400d", + "subscription_test/Mock Entry 20-3.nfo": "ef07f30d3e882de3f7cb3ad675125352", + "subscription_test/Mock Entry 21-1.info.json": "INFO_JSON", + "subscription_test/Mock Entry 21-1.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 21-1.mp4": "079832b6e49b283d80be402c9c928b90", + "subscription_test/Mock Entry 21-1.nfo": "dc714fd9f3c3729f74927ad245b50d9d" +} \ No newline at end of file diff --git a/tests/resources/expected_downloads_summaries/unit/music_videos/Kodi Music Videos Categorized/multi_url_True.json b/tests/resources/expected_downloads_summaries/unit/music_videos/Kodi Music Videos Categorized/multi_url_True.json new file mode 100644 index 00000000..ced3db94 --- /dev/null +++ b/tests/resources/expected_downloads_summaries/unit/music_videos/Kodi Music Videos Categorized/multi_url_True.json @@ -0,0 +1,23 @@ +{ + ".ytdl-sub-subscription_test-download-archive.json": "bcb2e8e8139f5bf589e027f841aa9449", + "subscription_test/Custom Title.info.json": "INFO_JSON", + "subscription_test/Custom Title.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Custom Title.mp4": "d7c2b8e961a8fcb612bd0d69c96bf0f3", + "subscription_test/Custom Title.nfo": "996f3993b2ba8a0614bef294492dde65", + "subscription_test/Mock Entry 20-4.info.json": "INFO_JSON", + "subscription_test/Mock Entry 20-4.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 20-4.mp4": "10f239edf916f8fb9eb461f24a821578", + "subscription_test/Mock Entry 20-4.nfo": "1e7cb1a09c15f155623f6cd796e874ff", + "subscription_test/Mock Entry 20-5.info.json": "INFO_JSON", + "subscription_test/Mock Entry 20-5.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 20-5.mp4": "046878a073fb269ec61401cdeb834707", + "subscription_test/Mock Entry 20-5.nfo": "f6100f194ae3c3b24211ff515d97ccdf", + "subscription_test/Mock Entry 20-6.info.json": "INFO_JSON", + "subscription_test/Mock Entry 20-6.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 20-6.mp4": "a50ead5d08456f0bcb907f1912caefcf", + "subscription_test/Mock Entry 20-6.nfo": "f51ae05104f5b98531535e75d623f941", + "subscription_test/Mock Entry 20-7.info.json": "INFO_JSON", + "subscription_test/Mock Entry 20-7.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 20-7.mp4": "5b35f04254c38c33ba056274b6c3af9f", + "subscription_test/Mock Entry 20-7.nfo": "852c02ea3ab196d808854ee94a9313d2" +} \ No newline at end of file diff --git a/tests/resources/expected_downloads_summaries/unit/music_videos/Plex Music Videos Categorized/multi_url_False.json b/tests/resources/expected_downloads_summaries/unit/music_videos/Plex Music Videos Categorized/multi_url_False.json new file mode 100644 index 00000000..78727e67 --- /dev/null +++ b/tests/resources/expected_downloads_summaries/unit/music_videos/Plex Music Videos Categorized/multi_url_False.json @@ -0,0 +1,15 @@ +{ + ".ytdl-sub-subscription_test-download-archive.json": "6cb47203ec56d8318a0d428b5b4efa5d", + "subscription_test/Mock Entry 20-1.info.json": "INFO_JSON", + "subscription_test/Mock Entry 20-1.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 20-1.mp4": "34916dc26e723c3464adcc4687898ca8", + "subscription_test/Mock Entry 20-2.info.json": "INFO_JSON", + "subscription_test/Mock Entry 20-2.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 20-2.mp4": "01a910b7a023325aa9d4ad3a013a1e02", + "subscription_test/Mock Entry 20-3.info.json": "INFO_JSON", + "subscription_test/Mock Entry 20-3.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 20-3.mp4": "812b6db9ff08bf1822e99e43d371400d", + "subscription_test/Mock Entry 21-1.info.json": "INFO_JSON", + "subscription_test/Mock Entry 21-1.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 21-1.mp4": "079832b6e49b283d80be402c9c928b90" +} \ No newline at end of file diff --git a/tests/resources/expected_downloads_summaries/unit/music_videos/Plex Music Videos Categorized/multi_url_True.json b/tests/resources/expected_downloads_summaries/unit/music_videos/Plex Music Videos Categorized/multi_url_True.json new file mode 100644 index 00000000..5f236acf --- /dev/null +++ b/tests/resources/expected_downloads_summaries/unit/music_videos/Plex Music Videos Categorized/multi_url_True.json @@ -0,0 +1,18 @@ +{ + ".ytdl-sub-subscription_test-download-archive.json": "69a9960ce69e3813269412fa7cb1bd33", + "subscription_test/Custom Title.info.json": "INFO_JSON", + "subscription_test/Custom Title.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Custom Title.mp4": "d7c2b8e961a8fcb612bd0d69c96bf0f3", + "subscription_test/Mock Entry 20-4.info.json": "INFO_JSON", + "subscription_test/Mock Entry 20-4.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 20-4.mp4": "10f239edf916f8fb9eb461f24a821578", + "subscription_test/Mock Entry 20-5.info.json": "INFO_JSON", + "subscription_test/Mock Entry 20-5.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 20-5.mp4": "046878a073fb269ec61401cdeb834707", + "subscription_test/Mock Entry 20-6.info.json": "INFO_JSON", + "subscription_test/Mock Entry 20-6.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 20-6.mp4": "a50ead5d08456f0bcb907f1912caefcf", + "subscription_test/Mock Entry 20-7.info.json": "INFO_JSON", + "subscription_test/Mock Entry 20-7.jpg": "e80c508c4818454300133fe1dc1a9cd7", + "subscription_test/Mock Entry 20-7.mp4": "5b35f04254c38c33ba056274b6c3af9f" +} \ No newline at end of file diff --git a/tests/resources/transaction_log_summaries/unit/music_videos/Jellyfin Music Videos Categorized/multi_url_False.txt b/tests/resources/transaction_log_summaries/unit/music_videos/Jellyfin Music Videos Categorized/multi_url_False.txt new file mode 100644 index 00000000..52e2c27d --- /dev/null +++ b/tests/resources/transaction_log_summaries/unit/music_videos/Jellyfin Music Videos Categorized/multi_url_False.txt @@ -0,0 +1,77 @@ +Files created: +---------------------------------------- +{output_directory} + .ytdl-sub-subscription_test-download-archive.json +{output_directory}/subscription_test + Mock Entry 20-1.info.json + Mock Entry 20-1.jpg + Mock Entry 20-1.mp4 + Video Tags: + album: Music Videos + artist: subscription_test + 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: subscription_test + 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: subscription_test + 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: subscription_test + 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: subscription_test + 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: subscription_test + 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: subscription_test + 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: subscription_test + 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/unit/music_videos/Jellyfin Music Videos Categorized/multi_url_True.txt b/tests/resources/transaction_log_summaries/unit/music_videos/Jellyfin Music Videos Categorized/multi_url_True.txt new file mode 100644 index 00000000..49e609e1 --- /dev/null +++ b/tests/resources/transaction_log_summaries/unit/music_videos/Jellyfin Music Videos Categorized/multi_url_True.txt @@ -0,0 +1,95 @@ +Files created: +---------------------------------------- +{output_directory} + .ytdl-sub-subscription_test-download-archive.json +{output_directory}/subscription_test + Custom Title.info.json + Custom Title.jpg + Custom Title.mp4 + Video Tags: + album: Concerts + artist: subscription_test + genre: ytdl-sub + premiered: 2021-08-08 + title: Custom Title + year: 2021 + Custom Title.nfo + NFO tags: + musicvideo: + album: Concerts + artist: subscription_test + genre: ytdl-sub + premiered: 2021-08-08 + title: Custom Title + Mock Entry 20-4.info.json + Mock Entry 20-4.jpg + Mock Entry 20-4.mp4 + Video Tags: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2020-08-06 + title: Mock Entry 20-4 + year: 2020 + Mock Entry 20-4.nfo + NFO tags: + musicvideo: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2020-08-06 + title: Mock Entry 20-4 + Mock Entry 20-5.info.json + Mock Entry 20-5.jpg + Mock Entry 20-5.mp4 + Video Tags: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2020-07-06 + title: Mock Entry 20-5 + year: 2020 + Mock Entry 20-5.nfo + NFO tags: + musicvideo: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2020-07-06 + title: Mock Entry 20-5 + Mock Entry 20-6.info.json + Mock Entry 20-6.jpg + Mock Entry 20-6.mp4 + Video Tags: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2020-07-06 + title: Mock Entry 20-6 + year: 2020 + Mock Entry 20-6.nfo + NFO tags: + musicvideo: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2020-07-06 + title: Mock Entry 20-6 + Mock Entry 20-7.info.json + Mock Entry 20-7.jpg + Mock Entry 20-7.mp4 + Video Tags: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2020-06-06 + title: Mock Entry 20-7 + year: 2020 + Mock Entry 20-7.nfo + NFO tags: + musicvideo: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2020-06-06 + title: Mock Entry 20-7 \ No newline at end of file diff --git a/tests/resources/transaction_log_summaries/unit/music_videos/Kodi Music Videos Categorized/multi_url_False.txt b/tests/resources/transaction_log_summaries/unit/music_videos/Kodi Music Videos Categorized/multi_url_False.txt new file mode 100644 index 00000000..52e2c27d --- /dev/null +++ b/tests/resources/transaction_log_summaries/unit/music_videos/Kodi Music Videos Categorized/multi_url_False.txt @@ -0,0 +1,77 @@ +Files created: +---------------------------------------- +{output_directory} + .ytdl-sub-subscription_test-download-archive.json +{output_directory}/subscription_test + Mock Entry 20-1.info.json + Mock Entry 20-1.jpg + Mock Entry 20-1.mp4 + Video Tags: + album: Music Videos + artist: subscription_test + 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: subscription_test + 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: subscription_test + 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: subscription_test + 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: subscription_test + 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: subscription_test + 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: subscription_test + 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: subscription_test + 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/unit/music_videos/Kodi Music Videos Categorized/multi_url_True.txt b/tests/resources/transaction_log_summaries/unit/music_videos/Kodi Music Videos Categorized/multi_url_True.txt new file mode 100644 index 00000000..49e609e1 --- /dev/null +++ b/tests/resources/transaction_log_summaries/unit/music_videos/Kodi Music Videos Categorized/multi_url_True.txt @@ -0,0 +1,95 @@ +Files created: +---------------------------------------- +{output_directory} + .ytdl-sub-subscription_test-download-archive.json +{output_directory}/subscription_test + Custom Title.info.json + Custom Title.jpg + Custom Title.mp4 + Video Tags: + album: Concerts + artist: subscription_test + genre: ytdl-sub + premiered: 2021-08-08 + title: Custom Title + year: 2021 + Custom Title.nfo + NFO tags: + musicvideo: + album: Concerts + artist: subscription_test + genre: ytdl-sub + premiered: 2021-08-08 + title: Custom Title + Mock Entry 20-4.info.json + Mock Entry 20-4.jpg + Mock Entry 20-4.mp4 + Video Tags: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2020-08-06 + title: Mock Entry 20-4 + year: 2020 + Mock Entry 20-4.nfo + NFO tags: + musicvideo: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2020-08-06 + title: Mock Entry 20-4 + Mock Entry 20-5.info.json + Mock Entry 20-5.jpg + Mock Entry 20-5.mp4 + Video Tags: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2020-07-06 + title: Mock Entry 20-5 + year: 2020 + Mock Entry 20-5.nfo + NFO tags: + musicvideo: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2020-07-06 + title: Mock Entry 20-5 + Mock Entry 20-6.info.json + Mock Entry 20-6.jpg + Mock Entry 20-6.mp4 + Video Tags: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2020-07-06 + title: Mock Entry 20-6 + year: 2020 + Mock Entry 20-6.nfo + NFO tags: + musicvideo: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2020-07-06 + title: Mock Entry 20-6 + Mock Entry 20-7.info.json + Mock Entry 20-7.jpg + Mock Entry 20-7.mp4 + Video Tags: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2020-06-06 + title: Mock Entry 20-7 + year: 2020 + Mock Entry 20-7.nfo + NFO tags: + musicvideo: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2020-06-06 + title: Mock Entry 20-7 \ No newline at end of file diff --git a/tests/resources/transaction_log_summaries/unit/music_videos/Plex Music Videos Categorized/multi_url_False.txt b/tests/resources/transaction_log_summaries/unit/music_videos/Plex Music Videos Categorized/multi_url_False.txt new file mode 100644 index 00000000..520d916d --- /dev/null +++ b/tests/resources/transaction_log_summaries/unit/music_videos/Plex Music Videos Categorized/multi_url_False.txt @@ -0,0 +1,45 @@ +Files created: +---------------------------------------- +{output_directory} + .ytdl-sub-subscription_test-download-archive.json +{output_directory}/subscription_test + Mock Entry 20-1.info.json + Mock Entry 20-1.jpg + Mock Entry 20-1.mp4 + Video Tags: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2020-08-08 + title: Mock Entry 20-1 + year: 2020 + Mock Entry 20-2.info.json + Mock Entry 20-2.jpg + Mock Entry 20-2.mp4 + Video Tags: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2020-08-08 + title: Mock Entry 20-2 + year: 2020 + Mock Entry 20-3.info.json + Mock Entry 20-3.jpg + Mock Entry 20-3.mp4 + Video Tags: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2020-08-07 + title: Mock Entry 20-3 + year: 2020 + Mock Entry 21-1.info.json + Mock Entry 21-1.jpg + Mock Entry 21-1.mp4 + Video Tags: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2021-08-08 + title: Mock Entry 21-1 + year: 2021 \ No newline at end of file diff --git a/tests/resources/transaction_log_summaries/unit/music_videos/Plex Music Videos Categorized/multi_url_True.txt b/tests/resources/transaction_log_summaries/unit/music_videos/Plex Music Videos Categorized/multi_url_True.txt new file mode 100644 index 00000000..1b97b19d --- /dev/null +++ b/tests/resources/transaction_log_summaries/unit/music_videos/Plex Music Videos Categorized/multi_url_True.txt @@ -0,0 +1,55 @@ +Files created: +---------------------------------------- +{output_directory} + .ytdl-sub-subscription_test-download-archive.json +{output_directory}/subscription_test + Custom Title.info.json + Custom Title.jpg + Custom Title.mp4 + Video Tags: + album: Concerts + artist: subscription_test + genre: ytdl-sub + premiered: 2021-08-08 + title: Custom Title + year: 2021 + Mock Entry 20-4.info.json + Mock Entry 20-4.jpg + Mock Entry 20-4.mp4 + Video Tags: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2020-08-06 + title: Mock Entry 20-4 + year: 2020 + Mock Entry 20-5.info.json + Mock Entry 20-5.jpg + Mock Entry 20-5.mp4 + Video Tags: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2020-07-06 + title: Mock Entry 20-5 + year: 2020 + Mock Entry 20-6.info.json + Mock Entry 20-6.jpg + Mock Entry 20-6.mp4 + Video Tags: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2020-07-06 + title: Mock Entry 20-6 + year: 2020 + Mock Entry 20-7.info.json + Mock Entry 20-7.jpg + Mock Entry 20-7.mp4 + Video Tags: + album: Music Videos + artist: subscription_test + genre: ytdl-sub + premiered: 2020-06-06 + title: Mock Entry 20-7 + year: 2020 \ No newline at end of file diff --git a/tests/unit/cli/test_entrypoint.py b/tests/unit/cli/test_entrypoint.py index d7a472cc..084df414 100644 --- a/tests/unit/cli/test_entrypoint.py +++ b/tests/unit/cli/test_entrypoint.py @@ -34,7 +34,7 @@ def test_subscription_logs_write_to_file( keep_successful_logs: bool, match: List[str], ): - subscription_names = ["Rick Astley", "Michael Jackson", "Eric Clapton"] + subscription_names = ["Rick Astley", "Michael Jackson", "Eric Clapton", "Guns N' Roses"] if match: subscription_names = ["Rick Astley", "Michael Jackson"] num_runs = 2 diff --git a/tests/unit/config/test_subscription.py b/tests/unit/config/test_subscription.py index e01525b7..ff9feb93 100644 --- a/tests/unit/config/test_subscription.py +++ b/tests/unit/config/test_subscription.py @@ -1,3 +1,4 @@ +import json import re from contextlib import contextmanager from pathlib import Path @@ -470,6 +471,15 @@ def test_advanced_tv_show_subscriptions( == "https://www.youtube.com/playlist?list=PLi8V8UemxeG6lo5if5H5g5EbsteELcb0_" ) + assert overrides.apply_formatter(overrides.dict["subscription_array"]) == json.dumps( + [ + "https://www.youtube.com/@gardeningwithciscoe4430", + "https://www.youtube.com/playlist?list=PLi8V8UemxeG6lo5if5H5g5EbsteELcb0_", + "https://www.youtube.com/playlist?list=PLsJlQSR-KjmaQqqJ9jq18cF6XXXAR4kyn", + "https://www.youtube.com/watch?v=2vq-vPubS5I", + ] + ) + def test_music_subscriptions(default_config: ConfigFile, music_subscriptions_path: Path): subs = Subscription.from_file_path( @@ -493,16 +503,31 @@ def test_music_video_subscriptions(default_config: ConfigFile, music_video_subsc config=default_config, subscription_path=music_video_subscription_path ) - assert len(subs) == 3 + assert len(subs) == 4 assert subs[1].name == "Michael Jackson" - monk = subs[1].overrides.script + jackson = subs[1].overrides.script - assert monk.get("subscription_name").native == "Michael Jackson" + assert jackson.get("subscription_name").native == "Michael Jackson" assert ( - monk.get("subscription_value").native + jackson.get("subscription_value").native == "https://www.youtube.com/playlist?list=OLAK5uy_mnY03zP6abNWH929q2XhGzWD_2uKJ_n8E" ) - assert monk.get("subscription_indent_1").native == "Pop" + assert jackson.get("subscription_indent_1").native == "Pop" + assert ( + jackson.get("url").native + == "https://www.youtube.com/playlist?list=OLAK5uy_mnY03zP6abNWH929q2XhGzWD_2uKJ_n8E" + ) + + assert subs[3].name == "Guns N' Roses" + gnr = subs[3].overrides.script + + assert gnr.get("subscription_name").native == "Guns N' Roses" + assert ( + gnr.get("url").native + == "https://www.youtube.com/playlist?list=PLOTK54q5K4INNXaHKtmXYr6J7CajWjqeJ" + ) + assert gnr.get("subscription_indent_1").native == "Rock" + assert gnr.get("url2").native == "https://www.youtube.com/watch?v=OldpIhHPsbs" def test_default_docker_config_and_subscriptions(): diff --git a/tests/unit/prebuilt_presets/test_prebuilt_presets.py b/tests/unit/prebuilt_presets/test_prebuilt_presets.py index 0f7cf5a2..a92a05c2 100644 --- a/tests/unit/prebuilt_presets/test_prebuilt_presets.py +++ b/tests/unit/prebuilt_presets/test_prebuilt_presets.py @@ -1,4 +1,5 @@ import copy +from pathlib import Path from typing import Dict from typing import List from typing import Optional @@ -9,6 +10,7 @@ from expected_download import assert_expected_downloads from expected_transaction_log import assert_transaction_log_matches from ytdl_sub.prebuilt_presets.music import MusicPresets +from ytdl_sub.prebuilt_presets.music_videos import MusicVideoExtrasPresets from ytdl_sub.prebuilt_presets.music_videos import MusicVideoPresets from ytdl_sub.prebuilt_presets.tv_show import TvShowByDateEpisodeFormattingPresets from ytdl_sub.prebuilt_presets.tv_show import TvShowByDateOldPresets @@ -16,6 +18,7 @@ from ytdl_sub.prebuilt_presets.tv_show import TvShowCollectionEpisodeFormattingP from ytdl_sub.prebuilt_presets.tv_show import TvShowCollectionPresets from ytdl_sub.prebuilt_presets.tv_show import TvShowCollectionSeasonPresets from ytdl_sub.subscriptions.subscription import Subscription +from ytdl_sub.utils.exceptions import RegexNoMatchException from ytdl_sub.utils.exceptions import ValidationException @@ -530,3 +533,91 @@ class TestPrebuiltMusicVideoPresets: dry_run=False, expected_download_summary_file_name=f"{expected_summary_name}.json", ) + + +@pytest.mark.parametrize("music_video_preset", MusicVideoPresets.preset_names) +@pytest.mark.parametrize("multi_url", [True, False]) +class TestPrebuiltMusicVideoPresetsWithCategories: + + def _preset_dict( + self, + output_directory: Path, + music_video_preset: str, + multi_url: bool, + ) -> Dict: + subscription_dict = {"Music Videos": ["https://your.name.here"]} + + if multi_url: + subscription_dict["Concerts"] = [ + {"url": "https://your.name.here2", "title": "Custom Title"} + ] + + preset_dict = { + "preset": [ + music_video_preset, + ], + "overrides": { + "music_video_directory": output_directory, + "subscription_map": subscription_dict, + }, + } + + return preset_dict + + def test_compilation( + self, + config, + output_directory: Path, + music_video_preset: str, + multi_url: bool, + ): + preset_dict = self._preset_dict( + output_directory=output_directory, + music_video_preset=music_video_preset, + multi_url=multi_url, + ) + + _ = Subscription.from_dict( + config=config, preset_name="preset_test", preset_dict=preset_dict + ) + + def test_presets_run( + self, + config, + subscription_name, + output_directory, + mock_download_collection_entries, + music_video_preset: str, + multi_url: bool, + ): + expected_summary_name = ( + f"unit/music_videos/{music_video_preset} Categorized/multi_url_{multi_url}" + ) + + preset_dict = self._preset_dict( + output_directory=output_directory, + music_video_preset=music_video_preset, + multi_url=multi_url, + ) + + subscription = Subscription.from_dict( + config=config, + preset_name=subscription_name, + preset_dict=preset_dict, + ) + + with mock_download_collection_entries( + is_youtube_channel=False, num_urls=2 if multi_url else 1, is_extracted_audio=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=f"{expected_summary_name}.txt", + ) + assert_expected_downloads( + output_directory=output_directory, + dry_run=False, + expected_download_summary_file_name=f"{expected_summary_name}.json", + )