[FEATURE] Music prebuilt presets
This commit is contained in:
parent
c149957b04
commit
d979465ff9
5 changed files with 198 additions and 57 deletions
|
|
@ -5,8 +5,6 @@ from typing import Set
|
||||||
|
|
||||||
import mergedeep
|
import mergedeep
|
||||||
|
|
||||||
from ytdl_sub.prebuilt_presets.tv_show import TvShowByDatePresets
|
|
||||||
from ytdl_sub.prebuilt_presets.tv_show import TvShowCollectionPresets
|
|
||||||
from ytdl_sub.utils.yaml import load_yaml
|
from ytdl_sub.utils.yaml import load_yaml
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -27,3 +25,7 @@ PREBUILT_PRESET_NAMES: Set[str] = set(PREBUILT_PRESETS.keys())
|
||||||
PUBLISHED_PRESET_NAMES: Set[str] = {
|
PUBLISHED_PRESET_NAMES: Set[str] = {
|
||||||
name for name in PREBUILT_PRESET_NAMES if not name.startswith("_")
|
name for name in PREBUILT_PRESET_NAMES if not name.startswith("_")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class PrebuiltPresets:
|
||||||
|
preset_names: Set[str]
|
||||||
|
|
|
||||||
9
src/ytdl_sub/prebuilt_presets/music/__init__.py
Normal file
9
src/ytdl_sub/prebuilt_presets/music/__init__.py
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
from ytdl_sub.prebuilt_presets import _, PrebuiltPresets
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class MusicPresets(PrebuiltPresets):
|
||||||
|
|
||||||
|
kodi_tv_show_by_date = _
|
||||||
|
jellyfin_tv_show_by_date = _
|
||||||
|
plex_tv_show_by_date = _
|
||||||
147
src/ytdl_sub/prebuilt_presets/music/music.yaml
Normal file
147
src/ytdl_sub/prebuilt_presets/music/music.yaml
Normal file
|
|
@ -0,0 +1,147 @@
|
||||||
|
presets:
|
||||||
|
|
||||||
|
_music_base:
|
||||||
|
output_options:
|
||||||
|
output_directory: "{music_directory}"
|
||||||
|
file_name: "{track_full_path}"
|
||||||
|
thumbnail_name: "{album_cover_path}"
|
||||||
|
download_archive_name: ".{subscription_name_sanitized}-download-archive.json"
|
||||||
|
maintain_download_archive: True
|
||||||
|
|
||||||
|
ytdl_options:
|
||||||
|
break_on_existing: True
|
||||||
|
|
||||||
|
format: "ba[ext=webm]/ba"
|
||||||
|
|
||||||
|
audio_extract:
|
||||||
|
codec: "best"
|
||||||
|
|
||||||
|
music_tags:
|
||||||
|
artist: "{track_artist}"
|
||||||
|
albumartist: "{track_album_artist}"
|
||||||
|
title: "{track_title}"
|
||||||
|
album: "{track_album}"
|
||||||
|
track: "{track_number}"
|
||||||
|
tracktotal: "{track_total}"
|
||||||
|
year: "{track_year}"
|
||||||
|
# multi-tags
|
||||||
|
artists:
|
||||||
|
- "{track_artist}"
|
||||||
|
albumartists:
|
||||||
|
- "{track_album_artist}"
|
||||||
|
genre:
|
||||||
|
- "{track_genre}"
|
||||||
|
|
||||||
|
overrides:
|
||||||
|
# Subscription overrides
|
||||||
|
subscription_indent_1: "Unset" # genre
|
||||||
|
url: "{subscription_value}"
|
||||||
|
|
||||||
|
# Track Overrides
|
||||||
|
track_title: "{title}"
|
||||||
|
track_album: "Singles"
|
||||||
|
track_artist: "{channel}"
|
||||||
|
track_album_artist: "{track_artist}"
|
||||||
|
track_number: "1"
|
||||||
|
track_number_padded: "01"
|
||||||
|
track_total: "1"
|
||||||
|
track_year: "{upload_year}"
|
||||||
|
track_genre: "{subscription_indent_1}"
|
||||||
|
|
||||||
|
# Directory Overrides
|
||||||
|
music_directory: "/music/tagged_manual"
|
||||||
|
artist_dir: "{track_artist_sanitized}"
|
||||||
|
album_dir: "[{track_year}] {track_album_sanitized}"
|
||||||
|
track_file_name: "{track_number_padded} - {track_title_sanitized}.{ext}"
|
||||||
|
track_full_path: "{artist_dir}/{album_dir}/{track_file_name}"
|
||||||
|
album_cover_path: "{artist_dir}/{album_dir}/folder.{thumbnail_ext}"
|
||||||
|
|
||||||
|
|
||||||
|
"Single":
|
||||||
|
preset:
|
||||||
|
- "_music_base"
|
||||||
|
|
||||||
|
download:
|
||||||
|
- "{url}"
|
||||||
|
|
||||||
|
|
||||||
|
_albums_from_playlists:
|
||||||
|
preset:
|
||||||
|
- "Single"
|
||||||
|
|
||||||
|
overrides:
|
||||||
|
track_album: "{playlist_title}"
|
||||||
|
track_number: "{playlist_index}"
|
||||||
|
track_number_padded: "{playlist_index_padded}"
|
||||||
|
track_total: "{playlist_count}"
|
||||||
|
track_year: "{playlist_max_upload_year}"
|
||||||
|
|
||||||
|
|
||||||
|
_albums_from_chapters:
|
||||||
|
preset: "Single"
|
||||||
|
|
||||||
|
chapters:
|
||||||
|
embed_chapters: True
|
||||||
|
split_by_chapters:
|
||||||
|
when_no_chapters: "pass"
|
||||||
|
|
||||||
|
overrides:
|
||||||
|
track_title: "{chapter_title}" # Chapter title is the track title
|
||||||
|
track_album: "{title}" # Video's title is the album title
|
||||||
|
track_number: "{chapter_index}"
|
||||||
|
track_number_padded: "{chapter_index_padded}"
|
||||||
|
track_total: "{chapter_count}"
|
||||||
|
|
||||||
|
"SoundCloud Discography":
|
||||||
|
preset: "_music_base"
|
||||||
|
|
||||||
|
# Download using the multi_url strategy
|
||||||
|
download:
|
||||||
|
download_strategy: "multi_url"
|
||||||
|
urls:
|
||||||
|
# The first URL will be all the artist's tracks.
|
||||||
|
# Treat these as singles - an album with a single track
|
||||||
|
- url: "{url}/tracks"
|
||||||
|
variables:
|
||||||
|
sc_track_album: "{title}"
|
||||||
|
sc_track_number: "1"
|
||||||
|
sc_track_number_padded: "01"
|
||||||
|
sc_track_total: "1"
|
||||||
|
sc_track_year: "{upload_year}"
|
||||||
|
# Set the second URL to the artist's albums. If a track belongs to both
|
||||||
|
# to an album and tracks (in the URL above), it will resolve to this
|
||||||
|
# URL and include the album metadata we set below.
|
||||||
|
- url: "{url}/albums"
|
||||||
|
variables:
|
||||||
|
sc_track_album: "{playlist_title}"
|
||||||
|
sc_track_number: "{playlist_index}"
|
||||||
|
sc_track_number_padded: "{playlist_index_padded}"
|
||||||
|
sc_track_total: "{playlist_count}"
|
||||||
|
sc_track_year: "{playlist_max_upload_year}"
|
||||||
|
|
||||||
|
# Override various track properties using playlist variables.
|
||||||
|
overrides:
|
||||||
|
track_album: "{sc_track_album}"
|
||||||
|
track_number: "{sc_track_number}"
|
||||||
|
track_number_padded: "{sc_track_number_padded}"
|
||||||
|
track_total: "{sc_track_total}"
|
||||||
|
track_year: "{sc_track_year}"
|
||||||
|
|
||||||
|
"YouTube Releases":
|
||||||
|
preset:
|
||||||
|
- "_albums_from_playlists"
|
||||||
|
|
||||||
|
"Bandcamp":
|
||||||
|
preset:
|
||||||
|
- "_albums_from_playlists"
|
||||||
|
regex:
|
||||||
|
from:
|
||||||
|
title:
|
||||||
|
match:
|
||||||
|
- ".*? - (.*)" # Captures 'Some - Song' from 'Emily Hopkins - Some - Song'
|
||||||
|
capture_group_names:
|
||||||
|
- "captured_track_title"
|
||||||
|
capture_group_defaults:
|
||||||
|
- "{title}"
|
||||||
|
overrides:
|
||||||
|
track_title: "{captured_track_title}"
|
||||||
|
|
@ -1,26 +1,4 @@
|
||||||
from typing import Set
|
from ytdl_sub.prebuilt_presets import PrebuiltPresets
|
||||||
|
|
||||||
|
|
||||||
class PrebuiltPreset:
|
|
||||||
"""placeholder"""
|
|
||||||
|
|
||||||
|
|
||||||
_ = PrebuiltPreset()
|
|
||||||
|
|
||||||
|
|
||||||
class PrebuiltPresets:
|
|
||||||
@classmethod
|
|
||||||
def get_preset_names(cls) -> Set[str]:
|
|
||||||
"""
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
Preset names in the set
|
|
||||||
"""
|
|
||||||
return set(
|
|
||||||
preset_name
|
|
||||||
for preset_name in dir(cls)
|
|
||||||
if isinstance(getattr(cls, preset_name), PrebuiltPreset)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class TvShowByDatePresets(PrebuiltPresets):
|
class TvShowByDatePresets(PrebuiltPresets):
|
||||||
|
|
@ -28,39 +6,44 @@ class TvShowByDatePresets(PrebuiltPresets):
|
||||||
TV Show by Date presets create a TV show from a single URL using upload dates as season/episode
|
TV Show by Date presets create a TV show from a single URL using upload dates as season/episode
|
||||||
numbers.
|
numbers.
|
||||||
"""
|
"""
|
||||||
|
preset_names = {
|
||||||
kodi_tv_show_by_date = _
|
"kodi_tv_show_by_date",
|
||||||
jellyfin_tv_show_by_date = _
|
"jellyfin_tv_show_by_date",
|
||||||
plex_tv_show_by_date = _
|
"plex_tv_show_by_date",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class TvShowByDateEpisodeFormattingPresets(PrebuiltPresets):
|
class TvShowByDateEpisodeFormattingPresets(PrebuiltPresets):
|
||||||
season_by_year__episode_by_month_day = _
|
preset_names = {
|
||||||
season_by_year__episode_by_month_day_reversed = _
|
"season_by_year__episode_by_month_day",
|
||||||
season_by_year_month__episode_by_day = _
|
"season_by_year__episode_by_month_day_reversed",
|
||||||
season_by_year__episode_by_download_index = _
|
"season_by_year_month__episode_by_day",
|
||||||
|
"season_by_year__episode_by_download_index",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class TvShowCollectionPresets(PrebuiltPresets):
|
class TvShowCollectionPresets(PrebuiltPresets):
|
||||||
"""
|
preset_names = {
|
||||||
Docstring for all TV SHOW URL presets
|
"kodi_tv_show_collection",
|
||||||
"""
|
"jellyfin_tv_show_collection",
|
||||||
|
"plex_tv_show_collection",
|
||||||
kodi_tv_show_collection = _
|
}
|
||||||
jellyfin_tv_show_collection = _
|
|
||||||
plex_tv_show_collection = _
|
|
||||||
|
|
||||||
|
|
||||||
class TvShowCollectionEpisodeFormattingPresets(PrebuiltPresets):
|
class TvShowCollectionEpisodeFormattingPresets(PrebuiltPresets):
|
||||||
season_by_collection__episode_by_year_month_day = _
|
preset_names = {
|
||||||
season_by_collection__episode_by_year_month_day_reversed = _
|
"season_by_collection__episode_by_year_month_day",
|
||||||
season_by_collection__episode_by_playlist_index = _
|
"season_by_collection__episode_by_year_month_day_reversed",
|
||||||
season_by_collection__episode_by_playlist_index_reversed = _
|
"season_by_collection__episode_by_playlist_index",
|
||||||
|
"season_by_collection__episode_by_playlist_index_reversed",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class TvShowCollectionSeasonPresets(PrebuiltPresets):
|
class TvShowCollectionSeasonPresets(PrebuiltPresets):
|
||||||
collection_season_1 = _
|
preset_names = {
|
||||||
collection_season_2 = _
|
"collection_season_1",
|
||||||
collection_season_3 = _
|
"collection_season_2",
|
||||||
collection_season_4 = _
|
"collection_season_3",
|
||||||
collection_season_5 = _
|
"collection_season_4",
|
||||||
|
"collection_season_5",
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ import pytest
|
||||||
from expected_download import assert_expected_downloads
|
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 import TvShowByDatePresets
|
from ytdl_sub.prebuilt_presets.tv_show import TvShowByDatePresets
|
||||||
from ytdl_sub.prebuilt_presets import TvShowCollectionPresets
|
from ytdl_sub.prebuilt_presets.tv_show import TvShowCollectionPresets
|
||||||
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 TvShowCollectionEpisodeFormattingPresets
|
from ytdl_sub.prebuilt_presets.tv_show import TvShowCollectionEpisodeFormattingPresets
|
||||||
from ytdl_sub.prebuilt_presets.tv_show import TvShowCollectionSeasonPresets
|
from ytdl_sub.prebuilt_presets.tv_show import TvShowCollectionSeasonPresets
|
||||||
|
|
@ -15,9 +15,9 @@ from ytdl_sub.subscriptions.subscription import Subscription
|
||||||
from ytdl_sub.utils.exceptions import ValidationException
|
from ytdl_sub.utils.exceptions import ValidationException
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("media_player_preset", TvShowByDatePresets.get_preset_names())
|
@pytest.mark.parametrize("media_player_preset", TvShowByDatePresets.preset_names)
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"tv_show_structure_preset", TvShowByDateEpisodeFormattingPresets.get_preset_names()
|
"tv_show_structure_preset", TvShowByDateEpisodeFormattingPresets.preset_names
|
||||||
)
|
)
|
||||||
class TestPrebuiltTVShowPresets:
|
class TestPrebuiltTVShowPresets:
|
||||||
def test_compilation(
|
def test_compilation(
|
||||||
|
|
@ -179,12 +179,12 @@ class TestPrebuiltTVShowPresets:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("media_player_preset", TvShowCollectionPresets.get_preset_names())
|
@pytest.mark.parametrize("media_player_preset", TvShowCollectionPresets.preset_names)
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"tv_show_structure_preset", TvShowCollectionEpisodeFormattingPresets.get_preset_names()
|
"tv_show_structure_preset", TvShowCollectionEpisodeFormattingPresets.preset_names
|
||||||
)
|
)
|
||||||
class TestPrebuiltTvShowCollectionPresets:
|
class TestPrebuiltTvShowCollectionPresets:
|
||||||
@pytest.mark.parametrize("season_preset", TvShowCollectionSeasonPresets.get_preset_names())
|
@pytest.mark.parametrize("season_preset", TvShowCollectionSeasonPresets.preset_names)
|
||||||
def test_compilation(
|
def test_compilation(
|
||||||
self,
|
self,
|
||||||
config,
|
config,
|
||||||
|
|
@ -208,7 +208,7 @@ class TestPrebuiltTvShowCollectionPresets:
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@pytest.mark.parametrize("season_preset", TvShowCollectionSeasonPresets.get_preset_names())
|
@pytest.mark.parametrize("season_preset", TvShowCollectionSeasonPresets.preset_names)
|
||||||
def test_compilation_errors_missing_one(
|
def test_compilation_errors_missing_one(
|
||||||
self,
|
self,
|
||||||
config,
|
config,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue