[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.
This commit is contained in:
Jesse Bannon 2024-06-06 11:50:33 -07:00 committed by GitHub
parent 5866c12104
commit 5e9472986a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 1064 additions and 18 deletions

View file

@ -5,6 +5,18 @@ Static Variables
Subscription 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 subscription_has_download_archive
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Returns True if the subscription has any entries recorded in a download archive. False Returns True if the subscription has any entries recorded in a download archive. False

View file

@ -14,12 +14,32 @@ __preset__:
overrides: overrides:
music_video_directory: "/music_videos" music_video_directory: "/music_videos"
# Choose between Jellyfin/Kodi/Plex Music Videos # Choose between Jellyfin/Kodi/Plex Music Videos preset:
# "Jellyfin Music Videos": # - Plex Music Videos:
# "Kodi Music Videos": # - Jellyfin Music Videos:
# - Kodi Music Videos:
"Plex Music Videos": "Plex Music Videos":
= Pop: # Sets genre tag to "Pop" = Pop: # Sets genre tag to "Pop"
"Rick Astley": "https://www.youtube.com/playlist?list=PLlaN88a7y2_plecYoJxvRFTLHVbIVAOoc" "Rick Astley": "https://www.youtube.com/playlist?list=PLlaN88a7y2_plecYoJxvRFTLHVbIVAOoc"
"Michael Jackson": "https://www.youtube.com/playlist?list=OLAK5uy_mnY03zP6abNWH929q2XhGzWD_2uKJ_n8E" "Michael Jackson": "https://www.youtube.com/playlist?list=OLAK5uy_mnY03zP6abNWH929q2XhGzWD_2uKJ_n8E"
= Blues: = Blues:
"Eric Clapton": "https://www.youtube.com/playlist?list=PLABGggHhsbEeaRtdzqnxYoEINsJE_4GF4" "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"

View file

@ -3,6 +3,7 @@ from typing import Set
from ytdl_sub.entries.script.function_scripts import CUSTOM_FUNCTION_SCRIPTS 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_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 BooleanVariable
from ytdl_sub.entries.script.variable_types import MapVariable from ytdl_sub.entries.script.variable_types import MapVariable
from ytdl_sub.entries.script.variable_types import StringVariable from ytdl_sub.entries.script.variable_types import StringVariable
@ -36,6 +37,21 @@ class SubscriptionVariables:
""" """
return StringVariable(variable_name="subscription_value", definition="{ %string('') }") 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 @staticmethod
def subscription_indent_i(index: int) -> StringVariable: def subscription_indent_i(index: int) -> StringVariable:
""" """

View file

@ -129,6 +129,7 @@ presets:
avatar_uncropped_thumbnail_file_name: "" avatar_uncropped_thumbnail_file_name: ""
banner_uncropped_thumbnail_file_name: "" banner_uncropped_thumbnail_file_name: ""
subscription_array: "{ [] }"
subscription_value: "" subscription_value: ""
subscription_value_2: "" subscription_value_2: ""
subscription_value_3: "" subscription_value_3: ""

View file

@ -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: <url_value>, category: ... }
#
# Output:
# Nested map containing { <url_value>: { url: <url_value>, 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 { <url value>: { 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) }"

View file

@ -10,3 +10,11 @@ class MusicVideoPresets(PrebuiltPresets):
"Jellyfin Music Videos", "Jellyfin Music Videos",
"Plex 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",
}

View file

@ -1,7 +1,8 @@
presets: presets:
_music_video_base: _music_video_base:
preset: preset:
- "_multi_url" - "_url_categorized"
output_options: output_options:
output_directory: "{music_video_directory}" output_directory: "{music_video_directory}"
@ -25,12 +26,38 @@ presets:
subscription_indent_1: "{music_video_genre_default}" subscription_indent_1: "{music_video_genre_default}"
# Music Video Overrides # Music Video Overrides
music_video_title: "{title}"
music_video_album: "{music_video_album_default}"
music_video_artist: "{subscription_name}" music_video_artist: "{subscription_name}"
music_video_year: "{upload_year}"
music_video_date: "{upload_date_standardized}"
music_video_genre: "{subscription_indent_1}" 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 # Directory Overrides
music_video_file_name: "{music_video_artist_sanitized}/{music_video_title_sanitized}" music_video_file_name_suffix: ""
music_video_file_name: "{music_video_artist_sanitized}/{music_video_title_sanitized}{music_video_file_name_suffix}"

View file

@ -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}"

View file

@ -143,10 +143,21 @@ class SubscriptionValueValidator(SubscriptionLeafValidator, StringValidator):
presets=presets, presets=presets,
indent_overrides=indent_overrides, indent_overrides=indent_overrides,
) )
# subscription_value
self._overrides_to_add[SubscriptionVariables.subscription_value().variable_name] = ( self._overrides_to_add[SubscriptionVariables.subscription_value().variable_name] = (
self.value 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): class SubscriptionListValuesValidator(SubscriptionLeafValidator, StringListValidator):
def __init__( def __init__(
@ -167,6 +178,7 @@ class SubscriptionListValuesValidator(SubscriptionLeafValidator, StringListValid
indent_overrides=indent_overrides, indent_overrides=indent_overrides,
) )
# Add indexed variables
for idx, list_value in enumerate(self.list): for idx, list_value in enumerate(self.list):
# Write the first list value into subscription_value as well # Write the first list value into subscription_value as well
if idx == 0: if idx == 0:
@ -178,6 +190,11 @@ class SubscriptionListValuesValidator(SubscriptionLeafValidator, StringListValid
SubscriptionVariables.subscription_value_i(index=idx).variable_name SubscriptionVariables.subscription_value_i(index=idx).variable_name
] = list_value.value ] = 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): class SubscriptionWithOverridesValidator(SubscriptionLeafValidator, DictFormatterValidator):
def __init__( def __init__(
@ -220,7 +237,7 @@ class SubscriptionMapValidator(SubscriptionLeafValidator, LiteralDictValidator):
indent_overrides=indent_overrides, indent_overrides=indent_overrides,
) )
self._overrides_to_add[SubscriptionVariables.subscription_map().variable_name] = ( self._overrides_to_add[SubscriptionVariables.subscription_map().variable_name] = (
ScriptUtils.to_script(self.dict) ScriptUtils.to_script(self.dict, sort_keys=False)
) )

View file

@ -35,7 +35,7 @@ class ScriptUtils:
return dict(variables, **sanitized_variables) return dict(variables, **sanitized_variables)
@classmethod @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 Converts a python value to a script value
""" """
@ -50,7 +50,7 @@ class ScriptUtils:
elif isinstance(value, float): elif isinstance(value, float):
out = f"{{%float({value})}}" out = f"{{%float({value})}}"
else: 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 # Remove triple-single-quotes from JSON to avoid parsing issues
dumped_json = re.sub("'{3,}", "'", dumped_json) dumped_json = re.sub("'{3,}", "'", dumped_json)

View file

@ -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"
}

View file

@ -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"
}

View file

@ -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"
}

View file

@ -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"
}

View file

@ -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"
}

View file

@ -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"
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -34,7 +34,7 @@ def test_subscription_logs_write_to_file(
keep_successful_logs: bool, keep_successful_logs: bool,
match: List[str], match: List[str],
): ):
subscription_names = ["Rick Astley", "Michael Jackson", "Eric Clapton"] subscription_names = ["Rick Astley", "Michael Jackson", "Eric Clapton", "Guns N' Roses"]
if match: if match:
subscription_names = ["Rick Astley", "Michael Jackson"] subscription_names = ["Rick Astley", "Michael Jackson"]
num_runs = 2 num_runs = 2

View file

@ -1,3 +1,4 @@
import json
import re import re
from contextlib import contextmanager from contextlib import contextmanager
from pathlib import Path from pathlib import Path
@ -470,6 +471,15 @@ def test_advanced_tv_show_subscriptions(
== "https://www.youtube.com/playlist?list=PLi8V8UemxeG6lo5if5H5g5EbsteELcb0_" == "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): def test_music_subscriptions(default_config: ConfigFile, music_subscriptions_path: Path):
subs = Subscription.from_file_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 config=default_config, subscription_path=music_video_subscription_path
) )
assert len(subs) == 3 assert len(subs) == 4
assert subs[1].name == "Michael Jackson" 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 ( assert (
monk.get("subscription_value").native jackson.get("subscription_value").native
== "https://www.youtube.com/playlist?list=OLAK5uy_mnY03zP6abNWH929q2XhGzWD_2uKJ_n8E" == "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(): def test_default_docker_config_and_subscriptions():

View file

@ -1,4 +1,5 @@
import copy import copy
from pathlib import Path
from typing import Dict from typing import Dict
from typing import List from typing import List
from typing import Optional 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 expected_transaction_log import assert_transaction_log_matches
from ytdl_sub.prebuilt_presets.music import MusicPresets 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.music_videos import MusicVideoPresets
from ytdl_sub.prebuilt_presets.tv_show import TvShowByDateEpisodeFormattingPresets from ytdl_sub.prebuilt_presets.tv_show import TvShowByDateEpisodeFormattingPresets
from ytdl_sub.prebuilt_presets.tv_show import TvShowByDateOldPresets 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 TvShowCollectionPresets
from ytdl_sub.prebuilt_presets.tv_show import TvShowCollectionSeasonPresets from ytdl_sub.prebuilt_presets.tv_show import TvShowCollectionSeasonPresets
from ytdl_sub.subscriptions.subscription import Subscription from ytdl_sub.subscriptions.subscription import Subscription
from ytdl_sub.utils.exceptions import RegexNoMatchException
from ytdl_sub.utils.exceptions import ValidationException from ytdl_sub.utils.exceptions import ValidationException
@ -530,3 +533,91 @@ class TestPrebuiltMusicVideoPresets:
dry_run=False, dry_run=False,
expected_download_summary_file_name=f"{expected_summary_name}.json", 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",
)