simplify
This commit is contained in:
parent
4a07b72293
commit
7a5ae6b778
4 changed files with 173 additions and 146 deletions
134
src/ytdl_sub/prebuilt_presets/helpers/keyed_url.yaml
Normal file
134
src/ytdl_sub/prebuilt_presets/helpers/keyed_url.yaml
Normal file
|
|
@ -0,0 +1,134 @@
|
||||||
|
#
|
||||||
|
# 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:
|
||||||
|
_keyed_url:
|
||||||
|
|
||||||
|
overrides:
|
||||||
|
|
||||||
|
# Takes a value and standardizes it to a dict, i.e.
|
||||||
|
#
|
||||||
|
# Concerts:
|
||||||
|
# - https://url1 -> { "url": "https://url1" }
|
||||||
|
# - url: https://url2
|
||||||
|
# title: custom title -> { "url": "https://url2", "title": "custom title" }
|
||||||
|
"%standardize_value_to_dict": >-
|
||||||
|
{
|
||||||
|
%if(
|
||||||
|
%is_string($0),
|
||||||
|
{ "url": $0 },
|
||||||
|
$0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Takes a Subscription Dict in the form of
|
||||||
|
#
|
||||||
|
# Concerts:
|
||||||
|
# - https://url1
|
||||||
|
# - url: https://url2
|
||||||
|
# title: custom title
|
||||||
|
# Another:
|
||||||
|
# - https://url3
|
||||||
|
#
|
||||||
|
# and standardizes it to
|
||||||
|
#
|
||||||
|
# [
|
||||||
|
# { "key": "Concerts", "url": "https://url1" },
|
||||||
|
# { "key": "Concerts", "url": "https://url2", "title": "custom title" },
|
||||||
|
# { "key": "Another", "url": "https://url3" }
|
||||||
|
# ]
|
||||||
|
"%subscription_dict_to_list__inner": >-
|
||||||
|
{
|
||||||
|
%map_extend(
|
||||||
|
{ "key": $0 },
|
||||||
|
%assert_then(
|
||||||
|
%if(
|
||||||
|
%is_dict( %standardize_value_to_dict( $1 ) ),
|
||||||
|
%map_contains( %standardize_value_to_dict( $1 ), "url" ),
|
||||||
|
False
|
||||||
|
),
|
||||||
|
%standardize_value_to_dict( $1 ),
|
||||||
|
"Value must be either a string or a Map with the key 'url'"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
# The actual variable that holds the subscription list of maps
|
||||||
|
subscription_map_list: >-
|
||||||
|
{
|
||||||
|
%map_apply( subscription_dict, %subscription_dict_to_list__inner )
|
||||||
|
}
|
||||||
|
|
||||||
|
# Helper function to get the i'th map in the subscription list.
|
||||||
|
# Returns an empty map if it does not exist.
|
||||||
|
"%get_subscription_map_i": >-
|
||||||
|
{
|
||||||
|
%array_at( subscription_map_list, $0, {} )
|
||||||
|
}
|
||||||
|
|
||||||
|
# Helper function to get the i'th map's url in the subscription list.
|
||||||
|
# Returns null if it does not exist.
|
||||||
|
"%get_subscription_map_i_url": >-
|
||||||
|
{
|
||||||
|
%map_get(
|
||||||
|
%get_subscription_map_i( $0 ),
|
||||||
|
"url",
|
||||||
|
null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
download:
|
||||||
|
- url: "{ %get_subscription_map_i_url(0) }"
|
||||||
|
playlist_thumbnails:
|
||||||
|
- name: "{avatar_uncropped_thumbnail_file_name}"
|
||||||
|
uid: "avatar_uncropped"
|
||||||
|
- name: "{banner_uncropped_thumbnail_file_name}"
|
||||||
|
uid: "banner_uncropped"
|
||||||
|
variables:
|
||||||
|
keyed_metadata: "{ %get_subscription_map_i(0) }"
|
||||||
|
- url: "{ %get_url_by_idx(1) }"
|
||||||
|
variables:
|
||||||
|
keyed_metadata: "{ %get_subscription_map_i(1) }"
|
||||||
|
- url: "{ %get_url_by_idx(2) }"
|
||||||
|
variables:
|
||||||
|
keyed_metadata: "{ %get_subscription_map_i(2) }"
|
||||||
|
- url: "{ %get_url_by_idx(3) }"
|
||||||
|
variables:
|
||||||
|
keyed_metadata: "{ %get_subscription_map_i(3) }"
|
||||||
|
- url: "{ %get_url_by_idx(4) }"
|
||||||
|
variables:
|
||||||
|
keyed_metadata: "{ %get_subscription_map_i(4) }"
|
||||||
|
- url: "{ %get_url_by_idx(5) }"
|
||||||
|
variables:
|
||||||
|
keyed_metadata: "{ %get_subscription_map_i(5) }"
|
||||||
|
- url: "{ %get_url_by_idx(6) }"
|
||||||
|
variables:
|
||||||
|
keyed_metadata: "{ %get_subscription_map_i(6) }"
|
||||||
|
- url: "{ %get_url_by_idx(7) }"
|
||||||
|
variables:
|
||||||
|
keyed_metadata: "{ %get_subscription_map_i(7) }"
|
||||||
|
- url: "{ %get_url_by_idx(8) }"
|
||||||
|
variables:
|
||||||
|
keyed_metadata: "{ %get_subscription_map_i(8) }"
|
||||||
|
|
||||||
|
|
@ -6,7 +6,10 @@
|
||||||
# - url2
|
# - url2
|
||||||
# ...
|
# ...
|
||||||
# Concerts:
|
# Concerts:
|
||||||
# - "Custom Title | 2013 | url3"
|
# - url: asfasdfasdf
|
||||||
|
# year: 2023
|
||||||
|
# title: sdfasff
|
||||||
|
# exclude: asdffsdf
|
||||||
# - url4
|
# - url4
|
||||||
# Extras:
|
# Extras:
|
||||||
# - url5
|
# - url5
|
||||||
|
|
@ -21,106 +24,14 @@
|
||||||
presets:
|
presets:
|
||||||
_music_video_extras_base:
|
_music_video_extras_base:
|
||||||
preset:
|
preset:
|
||||||
|
- "_keyed_url"
|
||||||
- "_music_video_base"
|
- "_music_video_base"
|
||||||
|
|
||||||
overrides:
|
overrides:
|
||||||
|
music_video_album: >-
|
||||||
# Splits metadata values from (TODO: allow any whitespace between | )
|
{ %map_get( %map(keyed_metadata), "key" ) }
|
||||||
# Key:
|
music_video_title: >-
|
||||||
# - metadata_0 | url
|
{ %map_get( keyed_metadata, "title", title ) }
|
||||||
# - metadata_0 | metadata_1 | url
|
|
||||||
"%get_value_split": >-
|
|
||||||
{ %split($0, " | ") }
|
|
||||||
|
|
||||||
# Gets the size of the metadata split
|
|
||||||
"%get_value_size": >-
|
|
||||||
{ %array_size( %get_value_split($0) ) }
|
|
||||||
|
|
||||||
# Gets the URL from the metadata, will always be the last one
|
|
||||||
"%get_value_url": >-
|
|
||||||
{ %array_at( %get_value_split($0), -1 ) }
|
|
||||||
|
|
||||||
# gets metadata_i if present, otherwise returns null
|
|
||||||
"%get_value_metadata_i": >-
|
|
||||||
{
|
|
||||||
%if(
|
|
||||||
%gt( %get_value_size($0) , %add($1, 1) ),
|
|
||||||
%array_at( %get_value_split($0), $1 ),
|
|
||||||
null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
# For each value under a key, build this map allowing up to 5 metadata values
|
|
||||||
"%get_value_metadata_map": >-
|
|
||||||
{
|
|
||||||
{
|
|
||||||
"key": $1,
|
|
||||||
"url": %get_value_url($0),
|
|
||||||
0: %get_value_metadata_i($0, 0),
|
|
||||||
1: %get_value_metadata_i($0, 1),
|
|
||||||
2: %get_value_metadata_i($0, 2),
|
|
||||||
3: %get_value_metadata_i($0, 3),
|
|
||||||
4: %get_value_metadata_i($0, 4)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# TODO: Have this support single-string values
|
|
||||||
"%get_value_metadata_map_outer": >-
|
|
||||||
{ %array_apply_fixed( $1, $0, %get_value_metadata_map ) }
|
|
||||||
|
|
||||||
# Build an array of metadata maps from every key in the subscription_map
|
|
||||||
subscription_list_of_maps: >-
|
|
||||||
{
|
|
||||||
%array_flatten(
|
|
||||||
%map_apply( subscription_map, %get_value_metadata_map_outer )
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
"%get_list_metadata_field_by_idx": >-
|
|
||||||
{
|
|
||||||
%map_get(
|
|
||||||
%array_at( subscription_list_of_maps, $0, {} ),
|
|
||||||
$1,
|
|
||||||
$2
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
"%get_url_by_idx": >-
|
|
||||||
{ %get_list_metadata_field_by_idx($0, "url", null) }
|
|
||||||
"%get_key_by_idx": >-
|
|
||||||
{ %get_list_metadata_field_by_idx($0, "key", null) }
|
|
||||||
"%get_metadata_i_by_idx": >-
|
|
||||||
{ %get_list_metadata_field_by_idx($0, $1, $2) }
|
|
||||||
|
|
||||||
metadata_0_default: "{ %string(null) }"
|
|
||||||
metadata_1_default: "{ %string(null) }"
|
|
||||||
metadata_2_default: "{ %string(null) }"
|
|
||||||
metadata_3_default: "{ %string(null) }"
|
|
||||||
metadata_4_default: "{ %string(null) }"
|
|
||||||
|
|
||||||
|
|
||||||
download:
|
|
||||||
- url: "{ %get_url_by_idx(0) }"
|
|
||||||
playlist_thumbnails:
|
|
||||||
- name: "{avatar_uncropped_thumbnail_file_name}"
|
|
||||||
uid: "avatar_uncropped"
|
|
||||||
- name: "{banner_uncropped_thumbnail_file_name}"
|
|
||||||
uid: "banner_uncropped"
|
|
||||||
variables:
|
|
||||||
metadata_key: "{ %get_key_by_idx(0) }"
|
|
||||||
metadata_0: "{ %get_metadata_i_by_idx(0, 0, metadata_0_default) }"
|
|
||||||
metadata_1: "{ %get_metadata_i_by_idx(0, 1, metadata_1_default) }"
|
|
||||||
metadata_2: "{ %get_metadata_i_by_idx(0, 2, metadata_2_default) }"
|
|
||||||
metadata_3: "{ %get_metadata_i_by_idx(0, 3, metadata_3_default) }"
|
|
||||||
metadata_4: "{ %get_metadata_i_by_idx(0, 4, metadata_4_default) }"
|
|
||||||
- url: "{ %get_url_by_idx(1) }"
|
|
||||||
variables:
|
|
||||||
metadata_key: "{ %get_key_by_idx(1) }"
|
|
||||||
metadata_0: "{ %get_metadata_i_by_idx(0, 0, metadata_0_default) }"
|
|
||||||
metadata_1: "{ %get_metadata_i_by_idx(0, 1, metadata_1_default) }"
|
|
||||||
metadata_2: "{ %get_metadata_i_by_idx(0, 2, metadata_2_default) }"
|
|
||||||
metadata_3: "{ %get_metadata_i_by_idx(0, 3, metadata_3_default) }"
|
|
||||||
metadata_4: "{ %get_metadata_i_by_idx(0, 4, metadata_4_default) }"
|
|
||||||
|
|
||||||
"Jellyfin Music Videos with Extras":
|
"Jellyfin Music Videos with Extras":
|
||||||
preset:
|
preset:
|
||||||
|
|
|
||||||
|
|
@ -63,21 +63,19 @@ def _is_type_compatible(
|
||||||
True if arg is compatible with expected_arg_type. False otherwise.
|
True if arg is compatible with expected_arg_type. False otherwise.
|
||||||
"""
|
"""
|
||||||
if is_union(expected_arg_type):
|
if is_union(expected_arg_type):
|
||||||
# See if the arg is a valid against the union
|
if issubclass(arg_type, (NamedCustomFunction, Variable)):
|
||||||
valid_type = False
|
return True # custom-function/variable can be anything, so pass for now
|
||||||
|
|
||||||
# if the input arg is a union, do a direct comparison
|
# if the input arg is a union, do a direct comparison
|
||||||
if is_union(arg_type):
|
if is_union(arg_type):
|
||||||
valid_type = arg_type == expected_arg_type
|
return arg_type == expected_arg_type
|
||||||
# otherwise, iterate the union to see if it's compatible
|
|
||||||
else:
|
|
||||||
for union_type in expected_arg_type.__args__:
|
|
||||||
if issubclass(arg_type, union_type):
|
|
||||||
valid_type = True
|
|
||||||
break
|
|
||||||
|
|
||||||
if not valid_type:
|
# otherwise, iterate the union to see if it's compatible
|
||||||
return False
|
for union_type in expected_arg_type.__args__:
|
||||||
|
if issubclass(arg_type, union_type):
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
# If the input is a union and the expected type is not, see if
|
# If the input is a union and the expected type is not, see if
|
||||||
# each possible union input is compatible with the expected type
|
# each possible union input is compatible with the expected type
|
||||||
elif is_union(arg_type):
|
elif is_union(arg_type):
|
||||||
|
|
|
||||||
|
|
@ -542,18 +542,6 @@ class TestPrebuiltMusicVideoPresets:
|
||||||
)
|
)
|
||||||
@pytest.mark.parametrize("multi_url", [True, False])
|
@pytest.mark.parametrize("multi_url", [True, False])
|
||||||
class TestPrebuiltMusicVideoPresets:
|
class TestPrebuiltMusicVideoPresets:
|
||||||
def _will_succeed(self, music_video_extras_preset: str, album_metadata: str) -> bool:
|
|
||||||
if "Plex" not in music_video_extras_preset:
|
|
||||||
return True
|
|
||||||
|
|
||||||
return album_metadata in [
|
|
||||||
"behindthescenes",
|
|
||||||
"concert",
|
|
||||||
"interview",
|
|
||||||
"live",
|
|
||||||
"lyrics",
|
|
||||||
"video",
|
|
||||||
]
|
|
||||||
|
|
||||||
def _preset_dict(
|
def _preset_dict(
|
||||||
self,
|
self,
|
||||||
|
|
@ -561,17 +549,25 @@ class TestPrebuiltMusicVideoPresets:
|
||||||
music_video_extras_preset: str,
|
music_video_extras_preset: str,
|
||||||
album_metadata: str,
|
album_metadata: str,
|
||||||
multi_url: bool,
|
multi_url: bool,
|
||||||
) -> Tuple[Dict, bool]:
|
) -> Dict:
|
||||||
"""Dict, whether it will succeed or not"""
|
subscription_dict = f"""{{
|
||||||
|
{{
|
||||||
subscription_indent_1 = album_metadata
|
{album_metadata}: "https://your.name.here"
|
||||||
subscription_indent_2 = "https://your.name.here"
|
}}
|
||||||
subscription_indent_3 = ""
|
}}"""
|
||||||
subscription_indent_4 = ""
|
|
||||||
|
|
||||||
if multi_url:
|
if multi_url:
|
||||||
subscription_indent_3 = subscription_indent_1 + " | Custom Title"
|
subscription_dict = f"""{{
|
||||||
subscription_indent_4 = "https://your.name.here2"
|
{{
|
||||||
|
{album_metadata}: [
|
||||||
|
"https://your.name.here",
|
||||||
|
{{
|
||||||
|
"url": "https://your.name.here2",
|
||||||
|
"title": "Custom Title"
|
||||||
|
}}
|
||||||
|
]
|
||||||
|
}}
|
||||||
|
}}"""
|
||||||
|
|
||||||
preset_dict = {
|
preset_dict = {
|
||||||
"preset": [
|
"preset": [
|
||||||
|
|
@ -579,16 +575,11 @@ class TestPrebuiltMusicVideoPresets:
|
||||||
],
|
],
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"music_video_directory": output_directory,
|
"music_video_directory": output_directory,
|
||||||
"subscription_value_1": subscription_indent_1,
|
"subscription_dict": subscription_dict,
|
||||||
"subscription_value_2": subscription_indent_2,
|
|
||||||
"subscription_value_3": subscription_indent_3,
|
|
||||||
"subscription_value_4": subscription_indent_4,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return preset_dict, self._will_succeed(
|
return preset_dict
|
||||||
music_video_extras_preset=music_video_extras_preset, album_metadata=album_metadata
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_compilation(
|
def test_compilation(
|
||||||
self,
|
self,
|
||||||
|
|
@ -598,7 +589,7 @@ class TestPrebuiltMusicVideoPresets:
|
||||||
album_metadata: str,
|
album_metadata: str,
|
||||||
multi_url: bool,
|
multi_url: bool,
|
||||||
):
|
):
|
||||||
preset_dict, _ = self._preset_dict(
|
preset_dict = self._preset_dict(
|
||||||
output_directory=output_directory,
|
output_directory=output_directory,
|
||||||
music_video_extras_preset=music_video_extras_preset,
|
music_video_extras_preset=music_video_extras_preset,
|
||||||
album_metadata=album_metadata,
|
album_metadata=album_metadata,
|
||||||
|
|
@ -623,7 +614,7 @@ class TestPrebuiltMusicVideoPresets:
|
||||||
f"unit/music_videos/{music_video_extras_preset}/{album_metadata}/multi_url_{multi_url}"
|
f"unit/music_videos/{music_video_extras_preset}/{album_metadata}/multi_url_{multi_url}"
|
||||||
)
|
)
|
||||||
|
|
||||||
preset_dict, will_succeed = self._preset_dict(
|
preset_dict = self._preset_dict(
|
||||||
output_directory=output_directory,
|
output_directory=output_directory,
|
||||||
music_video_extras_preset=music_video_extras_preset,
|
music_video_extras_preset=music_video_extras_preset,
|
||||||
album_metadata=album_metadata,
|
album_metadata=album_metadata,
|
||||||
|
|
@ -636,13 +627,6 @@ class TestPrebuiltMusicVideoPresets:
|
||||||
preset_dict=preset_dict,
|
preset_dict=preset_dict,
|
||||||
)
|
)
|
||||||
|
|
||||||
if not will_succeed:
|
|
||||||
with pytest.raises(RegexNoMatchException), mock_download_collection_entries(
|
|
||||||
is_youtube_channel=False, num_urls=2 if multi_url else 1, is_extracted_audio=False
|
|
||||||
):
|
|
||||||
subscription.download(dry_run=False)
|
|
||||||
return
|
|
||||||
|
|
||||||
with mock_download_collection_entries(
|
with mock_download_collection_entries(
|
||||||
is_youtube_channel=False, num_urls=2 if multi_url else 1, is_extracted_audio=False
|
is_youtube_channel=False, num_urls=2 if multi_url else 1, is_extracted_audio=False
|
||||||
):
|
):
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue