fix tests, re-update youtube channel test
This commit is contained in:
parent
7f6ed1621a
commit
b0033e4e57
10 changed files with 115 additions and 35 deletions
76
examples/advanced/music_video_config.yaml
Normal file
76
examples/advanced/music_video_config.yaml
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
###############################################################################
|
||||||
|
# Top-level configurations to apply umask and persist error logs
|
||||||
|
configuration:
|
||||||
|
umask: "002"
|
||||||
|
persist_logs:
|
||||||
|
logs_directory: './logs'
|
||||||
|
keep_successful_logs: False
|
||||||
|
|
||||||
|
presets:
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Try to capture music video metadata using regex
|
||||||
|
regex_capture_metadata:
|
||||||
|
regex:
|
||||||
|
from:
|
||||||
|
# Try to capture the artist and title of the track from the
|
||||||
|
# video title. Default to channel and video title.
|
||||||
|
title:
|
||||||
|
match:
|
||||||
|
- "(.*) - (.*) \\[O" # artist - song [Official ...
|
||||||
|
- "(.*) - (.*) \\(O" # artist - song (Official ...
|
||||||
|
- "(.*) - \"(.*)\" \\[O" # artist - "song" [Official ...
|
||||||
|
- "(.*) - \"(.*)\" \\(O" # artist - "song" (Official ...
|
||||||
|
- "(.*): (.*) \\[O" # artist: song [Official ...
|
||||||
|
- "(.*): (.*) \\(O" # artist: song (Official ...
|
||||||
|
- "(.*) - \"(.*)\".*" # artist - "song"
|
||||||
|
- "(.*) - '(.*)'.*" # artist - 'song'
|
||||||
|
- "(.*) - (.*).*" # artist - song
|
||||||
|
exclude:
|
||||||
|
- ".*[Aa][Uu][Dd][Ii][Oo].*" # Exclude audio vids
|
||||||
|
- ".*[Ll][Yy][Rr][Ii][Cc].*" # Exclude lyric vids
|
||||||
|
capture_group_names:
|
||||||
|
- "captured_artist"
|
||||||
|
- "captured_title"
|
||||||
|
capture_group_defaults:
|
||||||
|
- "{channel}"
|
||||||
|
- "{title}"
|
||||||
|
|
||||||
|
# Try to capture the year the music video premiered.
|
||||||
|
# Default to upload year
|
||||||
|
description:
|
||||||
|
match:
|
||||||
|
- ".*(19\\d{2}).*" # first 19XX digit value as year
|
||||||
|
- ".*(20\\d{2}).*" # first 20XX digit value as year
|
||||||
|
capture_group_names:
|
||||||
|
- "captured_year"
|
||||||
|
capture_group_defaults:
|
||||||
|
- "{upload_year}"
|
||||||
|
|
||||||
|
overrides:
|
||||||
|
music_video_directory: "/music_videos"
|
||||||
|
music_video_title: "{music_video_year} - {captured_title}"
|
||||||
|
music_video_artist: "{subscription_name}"
|
||||||
|
music_video_album: "Music Videos"
|
||||||
|
music_video_year: "{captured_year}"
|
||||||
|
music_video_file_name: "{music_video_artist_sanitized}/{music_video_title_sanitized}"
|
||||||
|
|
||||||
|
#######################################################
|
||||||
|
|
||||||
|
regex_capture_artist:
|
||||||
|
overrides:
|
||||||
|
music_video_artist: "{captured_artist}"
|
||||||
|
|
||||||
|
#######################################################
|
||||||
|
|
||||||
|
concert:
|
||||||
|
preset: "music_video"
|
||||||
|
|
||||||
|
overrides:
|
||||||
|
music_video_album: "Concerts"
|
||||||
|
|
||||||
|
#######################################################
|
||||||
|
|
||||||
|
year_as_upload_date:
|
||||||
|
overrides:
|
||||||
|
music_video_year: "{upload_year}"
|
||||||
|
|
@ -8,6 +8,12 @@ configuration:
|
||||||
|
|
||||||
presets:
|
presets:
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Set tv_show_directory here instead of in the subscriptions file
|
||||||
|
tv_show_paths:
|
||||||
|
overrides:
|
||||||
|
tv_show_directory: "/tv_shows"
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Filter out any YouTube shorts
|
# Filter out any YouTube shorts
|
||||||
no_shorts:
|
no_shorts:
|
||||||
|
|
@ -34,7 +40,7 @@ presets:
|
||||||
# Wait 2 days before downloading in hopes to get more accurate sponsorblock
|
# Wait 2 days before downloading in hopes to get more accurate sponsorblock
|
||||||
sponsorblock_wait:
|
sponsorblock_wait:
|
||||||
# Import the sponsorblock preset defined above
|
# Import the sponsorblock preset defined above
|
||||||
presets:
|
preset:
|
||||||
- "sponsorblock"
|
- "sponsorblock"
|
||||||
|
|
||||||
date_range:
|
date_range:
|
||||||
|
|
@ -47,6 +53,7 @@ presets:
|
||||||
preset:
|
preset:
|
||||||
- "Kodi TV Show by Date" # Set intended player
|
- "Kodi TV Show by Date" # Set intended player
|
||||||
- "best_video_quality" # prebuilt preset to get best quality
|
- "best_video_quality" # prebuilt preset to get best quality
|
||||||
|
- "tv_show_paths"
|
||||||
|
|
||||||
# Embed chapters into video files
|
# Embed chapters into video files
|
||||||
chapters:
|
chapters:
|
||||||
|
|
@ -62,7 +69,7 @@ presets:
|
||||||
# ytdl_options lets you pass any arg into yt-dlp's Python API
|
# ytdl_options lets you pass any arg into yt-dlp's Python API
|
||||||
ytdl_options:
|
ytdl_options:
|
||||||
# Set the cookie file
|
# Set the cookie file
|
||||||
cookiefile: "/config/youtube_cookies.txt"
|
# cookiefile: "/config/youtube_cookies.txt"
|
||||||
|
|
||||||
# For YouTube, get English metadata if multiple languages are present
|
# For YouTube, get English metadata if multiple languages are present
|
||||||
extractor_args:
|
extractor_args:
|
||||||
|
|
@ -70,11 +77,6 @@ presets:
|
||||||
lang:
|
lang:
|
||||||
- "en"
|
- "en"
|
||||||
|
|
||||||
# Set tv_show_directory in the preset
|
|
||||||
# instead of in the subscriptions file
|
|
||||||
overrides:
|
|
||||||
tv_show_directory: "/youtube"
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Custom preset to archive an entire channel
|
# Custom preset to archive an entire channel
|
||||||
TV Show Full Archive:
|
TV Show Full Archive:
|
||||||
|
|
|
||||||
|
|
@ -169,10 +169,13 @@ def music_video_subscription_path() -> Path:
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def channel_as_tv_show_config(working_directory) -> ConfigFile:
|
def tv_show_config_path() -> str:
|
||||||
return _load_config(
|
return "examples/advanced/tv_show_config.yaml"
|
||||||
config_path=Path("examples/tv_show_config.yaml"), working_directory=working_directory
|
|
||||||
)
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def tv_show_config(working_directory, tv_show_config_path) -> ConfigFile:
|
||||||
|
return _load_config(config_path=Path(tv_show_config_path), working_directory=working_directory)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
|
|
|
||||||
|
|
@ -43,12 +43,12 @@ class TestDateRange:
|
||||||
def test_recent_channel_download(
|
def test_recent_channel_download(
|
||||||
self,
|
self,
|
||||||
recent_preset_dict,
|
recent_preset_dict,
|
||||||
channel_as_tv_show_config,
|
tv_show_config,
|
||||||
output_directory,
|
output_directory,
|
||||||
dry_run,
|
dry_run,
|
||||||
):
|
):
|
||||||
recent_channel_subscription = Subscription.from_dict(
|
recent_channel_subscription = Subscription.from_dict(
|
||||||
config=channel_as_tv_show_config,
|
config=tv_show_config,
|
||||||
preset_name="recent",
|
preset_name="recent",
|
||||||
preset_dict=recent_preset_dict,
|
preset_dict=recent_preset_dict,
|
||||||
)
|
)
|
||||||
|
|
@ -86,7 +86,7 @@ class TestDateRange:
|
||||||
@pytest.mark.parametrize("dry_run", [True, False])
|
@pytest.mark.parametrize("dry_run", [True, False])
|
||||||
def test_recent_channel_download__no_vids_in_range(
|
def test_recent_channel_download__no_vids_in_range(
|
||||||
self,
|
self,
|
||||||
channel_as_tv_show_config,
|
tv_show_config,
|
||||||
recent_preset_dict,
|
recent_preset_dict,
|
||||||
output_directory,
|
output_directory,
|
||||||
dry_run,
|
dry_run,
|
||||||
|
|
@ -94,7 +94,7 @@ class TestDateRange:
|
||||||
recent_preset_dict["date_range"]["after"] = "21000101"
|
recent_preset_dict["date_range"]["after"] = "21000101"
|
||||||
|
|
||||||
recent_channel_no_vids_in_range_subscription = Subscription.from_dict(
|
recent_channel_no_vids_in_range_subscription = Subscription.from_dict(
|
||||||
config=channel_as_tv_show_config,
|
config=tv_show_config,
|
||||||
preset_name="recent",
|
preset_name="recent",
|
||||||
preset_dict=recent_preset_dict,
|
preset_dict=recent_preset_dict,
|
||||||
)
|
)
|
||||||
|
|
@ -118,19 +118,19 @@ class TestDateRange:
|
||||||
@pytest.mark.parametrize("dry_run", [True, False])
|
@pytest.mark.parametrize("dry_run", [True, False])
|
||||||
def test_rolling_recent_channel_download(
|
def test_rolling_recent_channel_download(
|
||||||
self,
|
self,
|
||||||
channel_as_tv_show_config,
|
tv_show_config,
|
||||||
recent_preset_dict,
|
recent_preset_dict,
|
||||||
rolling_recent_channel_preset_dict,
|
rolling_recent_channel_preset_dict,
|
||||||
output_directory,
|
output_directory,
|
||||||
dry_run,
|
dry_run,
|
||||||
):
|
):
|
||||||
recent_channel_subscription = Subscription.from_dict(
|
recent_channel_subscription = Subscription.from_dict(
|
||||||
config=channel_as_tv_show_config,
|
config=tv_show_config,
|
||||||
preset_name="recent",
|
preset_name="recent",
|
||||||
preset_dict=recent_preset_dict,
|
preset_dict=recent_preset_dict,
|
||||||
)
|
)
|
||||||
rolling_recent_channel_subscription = Subscription.from_dict(
|
rolling_recent_channel_subscription = Subscription.from_dict(
|
||||||
config=channel_as_tv_show_config,
|
config=tv_show_config,
|
||||||
preset_name="recent",
|
preset_name="recent",
|
||||||
preset_dict=rolling_recent_channel_preset_dict,
|
preset_dict=rolling_recent_channel_preset_dict,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -43,16 +43,16 @@ class TestChannel:
|
||||||
expected md5 file hashes.
|
expected md5 file hashes.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@pytest.mark.parametrize("dry_run", [False])
|
@pytest.mark.parametrize("dry_run", [True, False])
|
||||||
def test_full_channel_download(
|
def test_full_channel_download(
|
||||||
self,
|
self,
|
||||||
channel_as_tv_show_config,
|
tv_show_config,
|
||||||
channel_preset_dict,
|
channel_preset_dict,
|
||||||
output_directory,
|
output_directory,
|
||||||
dry_run,
|
dry_run,
|
||||||
):
|
):
|
||||||
full_channel_subscription = Subscription.from_dict(
|
full_channel_subscription = Subscription.from_dict(
|
||||||
config=channel_as_tv_show_config, preset_name="pz", preset_dict=channel_preset_dict
|
config=tv_show_config, preset_name="pz", preset_dict=channel_preset_dict
|
||||||
)
|
)
|
||||||
transaction_log = full_channel_subscription.download(dry_run=dry_run)
|
transaction_log = full_channel_subscription.download(dry_run=dry_run)
|
||||||
assert_transaction_log_matches(
|
assert_transaction_log_matches(
|
||||||
|
|
|
||||||
|
|
@ -208,12 +208,12 @@ class TestYoutubeVideo:
|
||||||
|
|
||||||
def test_single_video_nulled_values(
|
def test_single_video_nulled_values(
|
||||||
self,
|
self,
|
||||||
channel_as_tv_show_config,
|
tv_show_config,
|
||||||
single_tv_show_video_nulled_values_preset_dict,
|
single_tv_show_video_nulled_values_preset_dict,
|
||||||
output_directory,
|
output_directory,
|
||||||
):
|
):
|
||||||
single_video_subscription = Subscription.from_dict(
|
single_video_subscription = Subscription.from_dict(
|
||||||
config=channel_as_tv_show_config,
|
config=tv_show_config,
|
||||||
preset_name="tv_video_nulled_values",
|
preset_name="tv_video_nulled_values",
|
||||||
preset_dict=single_tv_show_video_nulled_values_preset_dict,
|
preset_dict=single_tv_show_video_nulled_values_preset_dict,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@
|
||||||
"Project ⧸ Zombie/Season 2018/s2018.e110201 - Jesse's Minecraft Server | IP mc.jesse.id-thumb.jpg": "28d852ede73b879b9ebf9a061cfc7d46",
|
"Project ⧸ Zombie/Season 2018/s2018.e110201 - Jesse's Minecraft Server | IP mc.jesse.id-thumb.jpg": "28d852ede73b879b9ebf9a061cfc7d46",
|
||||||
"Project ⧸ Zombie/Season 2018/s2018.e110201 - Jesse's Minecraft Server | IP mc.jesse.id.en.srt": "3d2c4e7f65d2ca5e96da38ce7eecfc4e",
|
"Project ⧸ Zombie/Season 2018/s2018.e110201 - Jesse's Minecraft Server | IP mc.jesse.id.en.srt": "3d2c4e7f65d2ca5e96da38ce7eecfc4e",
|
||||||
"Project ⧸ Zombie/Season 2018/s2018.e110201 - Jesse's Minecraft Server | IP mc.jesse.id.info.json": "INFO_JSON",
|
"Project ⧸ Zombie/Season 2018/s2018.e110201 - Jesse's Minecraft Server | IP mc.jesse.id.info.json": "INFO_JSON",
|
||||||
"Project ⧸ Zombie/Season 2018/s2018.e110201 - Jesse's Minecraft Server | IP mc.jesse.id.mp4": "77aca1c8f8ef32c282a8a871d80bec10",
|
"Project ⧸ Zombie/Season 2018/s2018.e110201 - Jesse's Minecraft Server | IP mc.jesse.id.mp4": "3725eaeaae4a400599070a56a1dccf9d",
|
||||||
"Project ⧸ Zombie/Season 2018/s2018.e110201 - Jesse's Minecraft Server | IP mc.jesse.id.nfo": "a9b7ac3cacbda7fed9d12b0519945292",
|
"Project ⧸ Zombie/Season 2018/s2018.e110201 - Jesse's Minecraft Server | IP mc.jesse.id.nfo": "a9b7ac3cacbda7fed9d12b0519945292",
|
||||||
"Project ⧸ Zombie/fanart.jpg": "129c6639b47299bc48062f0365e670ee",
|
"Project ⧸ Zombie/fanart.jpg": "129c6639b47299bc48062f0365e670ee",
|
||||||
"Project ⧸ Zombie/poster.jpg": "5de28eea5a921a041452ab3ce1041f73",
|
"Project ⧸ Zombie/poster.jpg": "5de28eea5a921a041452ab3ce1041f73",
|
||||||
|
|
|
||||||
|
|
@ -579,6 +579,7 @@ Files created:
|
||||||
s2018.e110201 - Jesse's Minecraft Server | IP mc.jesse.id.en.srt
|
s2018.e110201 - Jesse's Minecraft Server | IP mc.jesse.id.en.srt
|
||||||
s2018.e110201 - Jesse's Minecraft Server | IP mc.jesse.id.info.json
|
s2018.e110201 - Jesse's Minecraft Server | IP mc.jesse.id.info.json
|
||||||
s2018.e110201 - Jesse's Minecraft Server | IP mc.jesse.id.mp4
|
s2018.e110201 - Jesse's Minecraft Server | IP mc.jesse.id.mp4
|
||||||
|
Embedded subtitles with lang(s) en
|
||||||
Video Tags:
|
Video Tags:
|
||||||
contentRating: TV-14
|
contentRating: TV-14
|
||||||
date: 2018-11-02
|
date: 2018-11-02
|
||||||
|
|
|
||||||
|
|
@ -351,16 +351,14 @@ def test_subscription_file_invalid_form(config_file: ConfigFile):
|
||||||
_ = Subscription.from_file_path(config=config_file, subscription_path="mocked")
|
_ = Subscription.from_file_path(config=config_file, subscription_path="mocked")
|
||||||
|
|
||||||
|
|
||||||
def test_tv_show_subscriptions(
|
def test_tv_show_subscriptions(tv_show_config: ConfigFile, tv_show_subscriptions_path: Path):
|
||||||
channel_as_tv_show_config: ConfigFile, tv_show_subscriptions_path: Path
|
|
||||||
):
|
|
||||||
subs = Subscription.from_file_path(
|
subs = Subscription.from_file_path(
|
||||||
config=channel_as_tv_show_config, subscription_path=tv_show_subscriptions_path
|
config=tv_show_config, subscription_path=tv_show_subscriptions_path
|
||||||
)
|
)
|
||||||
|
|
||||||
assert len(subs) == 5
|
assert len(subs) == 5
|
||||||
assert subs[2].name == "Jake Trains"
|
assert subs[3].name == "Jake Trains"
|
||||||
jake_train_overrides = subs[2].overrides.dict_with_format_strings
|
jake_train_overrides = subs[3].overrides.dict_with_format_strings
|
||||||
|
|
||||||
assert jake_train_overrides["subscription_name"] == "Jake Trains"
|
assert jake_train_overrides["subscription_name"] == "Jake Trains"
|
||||||
assert jake_train_overrides["subscription_value"] == "https://www.youtube.com/@JakeTrains"
|
assert jake_train_overrides["subscription_value"] == "https://www.youtube.com/@JakeTrains"
|
||||||
|
|
|
||||||
|
|
@ -96,17 +96,17 @@ def test_main_permission_error(capsys, mock_sys_exit, expected_uncaught_error_me
|
||||||
assert mock_error.call_args.args[1] == "test"
|
assert mock_error.call_args.args[1] == "test"
|
||||||
|
|
||||||
|
|
||||||
def test_args_after_sub_work(mock_sys_exit):
|
def test_args_after_sub_work(mock_sys_exit, tv_show_config_path):
|
||||||
with mock_sys_exit(expected_exit_code=0), patch.object(
|
with mock_sys_exit(expected_exit_code=0), patch.object(
|
||||||
sys,
|
sys,
|
||||||
"argv",
|
"argv",
|
||||||
["ytdl-sub", "-c", "examples/tv_show_config.yaml", "sub", "--log-level", "verbose"],
|
["ytdl-sub", "-c", tv_show_config_path, "sub", "--log-level", "verbose"],
|
||||||
), patch("ytdl_sub.cli.entrypoint._download_subscriptions_from_yaml_files") as mock_sub:
|
), patch("ytdl_sub.cli.entrypoint._download_subscriptions_from_yaml_files") as mock_sub:
|
||||||
main()
|
main()
|
||||||
|
|
||||||
assert mock_sub.call_count == 1
|
assert mock_sub.call_count == 1
|
||||||
assert mock_sub.call_args.kwargs["subscription_paths"] == ["subscriptions.yaml"]
|
assert mock_sub.call_args.kwargs["subscription_paths"] == ["subscriptions.yaml"]
|
||||||
assert mock_sub.call_args.kwargs["config"]._name == "examples/tv_show_config.yaml"
|
assert mock_sub.call_args.kwargs["config"]._name == tv_show_config_path
|
||||||
assert Logger._LOGGER_LEVEL == LoggerLevels.VERBOSE
|
assert Logger._LOGGER_LEVEL == LoggerLevels.VERBOSE
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -151,11 +151,11 @@ def test_uses_default_config_if_present(mock_sys_exit):
|
||||||
FileHandler.delete(DEFAULT_CONFIG_FILE_NAME)
|
FileHandler.delete(DEFAULT_CONFIG_FILE_NAME)
|
||||||
|
|
||||||
|
|
||||||
def test_no_positional_arg_command(mock_sys_exit):
|
def test_no_positional_arg_command(mock_sys_exit, tv_show_config_path):
|
||||||
with mock_sys_exit(expected_exit_code=1), patch.object(
|
with mock_sys_exit(expected_exit_code=1), patch.object(
|
||||||
sys,
|
sys,
|
||||||
"argv",
|
"argv",
|
||||||
["ytdl-sub", "-c", "examples/tv_show_config.yaml", "--log-level", "verbose"],
|
["ytdl-sub", "-c", tv_show_config_path, "--log-level", "verbose"],
|
||||||
), patch.object(logging.Logger, "error") as mock_error:
|
), patch.object(logging.Logger, "error") as mock_error:
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue