organize
This commit is contained in:
parent
a89ed5e2fc
commit
677214db64
7 changed files with 207 additions and 182 deletions
|
|
@ -1,12 +1,11 @@
|
|||
import pathlib
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from typing import Dict
|
||||
|
||||
import mergedeep
|
||||
|
||||
from ytdl_sub.prebuilt_presets.tv_show.out import PrebuiltJellyfinTVShowPresets
|
||||
from ytdl_sub.prebuilt_presets.tv_show.out import PrebuiltKodiTVShowPresets
|
||||
from ytdl_sub.prebuilt_presets.tv_show import PrebuiltJellyfinTVShowPresets
|
||||
from ytdl_sub.prebuilt_presets.tv_show import PrebuiltKodiTVShowPresets
|
||||
from ytdl_sub.utils.yaml import load_yaml
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,102 @@
|
|||
from typing import Any
|
||||
from typing import Dict
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
|
||||
Preset = Dict[str, Any]
|
||||
|
||||
|
||||
class PrebuiltPresets:
|
||||
BASE_PRESET: str
|
||||
|
||||
def _preset(self, name: str, presets: List[str]) -> Preset:
|
||||
return {"presets": {name: {"preset": [self.BASE_PRESET] + presets}}}
|
||||
|
||||
def _tv_show_url(self, name: str) -> Preset:
|
||||
"""
|
||||
Kodi TV Show with seasons as years, episodes ordered by upload date
|
||||
"""
|
||||
return self._preset(
|
||||
name=name, presets=["tv-show-url", "season-by-year--episode-by-month-day"]
|
||||
)
|
||||
|
||||
def _tv_show_youtube_channel(self, name: str) -> Preset:
|
||||
return self._preset(
|
||||
name=name, presets=["tv-show-youtube-channel", "season-by-year--episode-by-month-day"]
|
||||
)
|
||||
|
||||
def _tv_show_collection(self, name: str) -> Preset:
|
||||
return self._preset(
|
||||
name=name,
|
||||
presets=["tv-show-collection", "season-by-collection--episode-by-year-month-day"],
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_preset_names(cls) -> List[str]:
|
||||
preset_names = [prop for prop in dir(cls) if isinstance(getattr(cls, prop), property)]
|
||||
return preset_names
|
||||
|
||||
@classmethod
|
||||
def get_collection_preset_names(cls) -> List[str]:
|
||||
return [name for name in cls.get_preset_names() if "collection" in name]
|
||||
|
||||
@classmethod
|
||||
def get_non_collection_preset_names(cls) -> List[str]:
|
||||
return [name for name in cls.get_preset_names() if "collection" not in name]
|
||||
|
||||
@classmethod
|
||||
def get_presets(cls, preset_names: Optional[List[str]] = None) -> List[Preset]:
|
||||
if preset_names is None:
|
||||
preset_names = cls.get_preset_names()
|
||||
|
||||
return [getattr(cls(), preset_name) for preset_name in preset_names]
|
||||
|
||||
|
||||
class PrebuiltKodiTVShowPresets(PrebuiltPresets):
|
||||
BASE_PRESET = "kodi-tv-show"
|
||||
|
||||
@property
|
||||
def kodi_tv_show_url(self) -> Preset:
|
||||
"""
|
||||
Kodi TV Show with seasons as years, episodes ordered by upload date
|
||||
"""
|
||||
return self._tv_show_url(name="kodi_tv_show_url")
|
||||
|
||||
@property
|
||||
def kodi_tv_show_youtube_channel(self) -> Preset:
|
||||
"""
|
||||
Kodi TV Show from a YouTube channel with seasons as years, episodes ordered by upload date
|
||||
"""
|
||||
return self._tv_show_youtube_channel(name="kodi_tv_show_youtube_channel")
|
||||
|
||||
@property
|
||||
def kodi_tv_show_collection(self) -> Preset:
|
||||
"""
|
||||
Kodi TV Show from a collection of multiple URLs. TODO: finish docstring
|
||||
"""
|
||||
return self._tv_show_collection(name="kodi_tv_show_collection")
|
||||
|
||||
|
||||
class PrebuiltJellyfinTVShowPresets(PrebuiltPresets):
|
||||
BASE_PRESET = "jellyfin-tv-show"
|
||||
|
||||
@property
|
||||
def jellyfin_tv_show_url(self) -> Preset:
|
||||
"""
|
||||
Kodi TV Show with seasons as years, episodes ordered by upload date
|
||||
"""
|
||||
return self._tv_show_url(name="jellyfin_tv_show_url")
|
||||
|
||||
@property
|
||||
def jellyfin_tv_show_youtube_channel(self) -> Preset:
|
||||
"""
|
||||
Kodi TV Show from a YouTube channel with seasons as years, episodes ordered by upload date
|
||||
"""
|
||||
return self._tv_show_youtube_channel(name="jellyfin_tv_show_youtube_channel")
|
||||
|
||||
@property
|
||||
def jellyfin_tv_show_collection(self) -> Preset:
|
||||
"""
|
||||
Kodi TV Show from a collection of multiple URLs. TODO: finish docstring
|
||||
"""
|
||||
return self._tv_show_collection(name="jellyfin_tv_show_collection")
|
||||
|
|
@ -27,40 +27,66 @@ presets:
|
|||
episode_air_date_standardized: "{upload_date_standardized}"
|
||||
episode_file_name: "s{season_number_padded}.e{episode_number_padded} - {uid_sanitized}"
|
||||
episode_file_path: "Season {season_number_padded}/{episode_file_name}"
|
||||
episode_number_suffix: ""
|
||||
|
||||
####################################################################################################
|
||||
|
||||
season-by-year:
|
||||
overrides:
|
||||
season_number: "{upload_year}"
|
||||
season_number_padded: "{upload_year}"
|
||||
season_number_padded: "{season_number}"
|
||||
|
||||
episode-by-month-day:
|
||||
season-by-year-month:
|
||||
overrides:
|
||||
season_number: "{upload_year}{upload_month_padded}"
|
||||
season_number_padded: "{season_number}"
|
||||
|
||||
####################################################################################################
|
||||
|
||||
season-by-year-month--episode-by-day:
|
||||
preset:
|
||||
- "episode-base"
|
||||
- "season-by-year-month"
|
||||
overrides:
|
||||
episode_number: "{upload_day}"
|
||||
episode_number_padded: "{upload_day_padded}"
|
||||
|
||||
season-by-year--episode-by-month-day:
|
||||
preset:
|
||||
- "episode-base"
|
||||
- "season-by-year"
|
||||
- "episode-base"
|
||||
overrides:
|
||||
episode_number: "{upload_month}{upload_day_padded}"
|
||||
episode_number_padded: "{upload_month_padded}{upload_day_padded}"
|
||||
episode_number: "{upload_month}{upload_day_padded}{episode_number_suffix}"
|
||||
episode_number_padded: "{upload_month_padded}{upload_day_padded}{episode_number_suffix}"
|
||||
|
||||
episode-by-month-day-reversed:
|
||||
season-by-year--episode-by-month-day-reversed:
|
||||
preset:
|
||||
- "episode-base"
|
||||
- "season-by-year"
|
||||
- "episode-base"
|
||||
overrides:
|
||||
episode_number: "{upload_day_of_year_reversed}"
|
||||
episode_number_padded: "{upload_day_of_year_reversed_padded}"
|
||||
episode_number: "{upload_day_of_year_reversed}{episode_number_suffix}"
|
||||
episode_number_padded: "{upload_day_of_year_reversed_padded}{episode_number_suffix}"
|
||||
|
||||
episode-by-year-month-day:
|
||||
season-by-collection--episode-by-year-month-day:
|
||||
preset:
|
||||
- "episode-base"
|
||||
overrides:
|
||||
episode_number: "{upload_year_truncated}{upload_month_padded}{upload_day_padded}"
|
||||
episode_number: "{upload_year_truncated}{upload_month_padded}{upload_day_padded}{episode_number_suffix}"
|
||||
episode_number_padded: "{episode_number}"
|
||||
|
||||
episode-by-year-month-day-reversed:
|
||||
season-by-collection--episode-by-year-month-day-reversed:
|
||||
preset:
|
||||
- "episode-base"
|
||||
overrides:
|
||||
episode_number: "{upload_year_truncated_reversed}{upload_month_reversed_padded}{upload_day_reversed_padded}"
|
||||
episode_number_padded: "{episode_number}"
|
||||
episode_number: "{upload_year_truncated_reversed}{upload_month_reversed_padded}{upload_day_reversed_padded}{episode_number_suffix}"
|
||||
episode_number_padded: "{episode_number}"
|
||||
|
||||
####################################################################################################
|
||||
|
||||
episode-add-hour-granularity:
|
||||
overrides:
|
||||
episode_number_suffix: "{epoch_hour}{playlist_index_reversed_padded6}"
|
||||
|
||||
episode-add-hour-granularity-reversed:
|
||||
overrides:
|
||||
episode_number_suffix: "{epoch_hour}{playlist_index_padded6}"
|
||||
|
|
|
|||
|
|
@ -1,154 +0,0 @@
|
|||
from typing import Any
|
||||
from typing import Dict
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
|
||||
Preset = Dict[str, Any]
|
||||
|
||||
|
||||
class PrebuiltPresets:
|
||||
BASE_PRESET: str
|
||||
|
||||
def _preset(self, name: str, presets: List[str]) -> Preset:
|
||||
return {"presets": {name: {"preset": [self.BASE_PRESET] + presets}}}
|
||||
|
||||
def _tv_show_url(self, name: str) -> Preset:
|
||||
"""
|
||||
Kodi TV Show with seasons as years, episodes ordered by upload date
|
||||
"""
|
||||
return self._preset(name=name, presets=["tv-show-url", "episode-by-month-day"])
|
||||
|
||||
def _tv_show_url_reversed(self, name: str) -> Preset:
|
||||
return self._preset(name=name, presets=["tv-show-url", "episode-by-month-day-reversed"])
|
||||
|
||||
def _tv_show_youtube_channel(self, name: str) -> Preset:
|
||||
return self._preset(name=name, presets=["tv-show-youtube-channel", "episode-by-month-day"])
|
||||
|
||||
def _tv_show_youtube_channel_reversed(self, name: str) -> Preset:
|
||||
return self._preset(name=name, presets=["tv-show-youtube-channel", "episode-by-month-day"])
|
||||
|
||||
def _tv_show_collection(self, name: str) -> Preset:
|
||||
return self._preset(name=name, presets=["tv-show-collection", "episode-by-year-month-day"])
|
||||
|
||||
def _tv_show_collection_reversed(self, name: str) -> Preset:
|
||||
return self._preset(
|
||||
name=name, presets=["tv-show-collection", "episode-by-year-month-day-reversed"]
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_preset_names(cls) -> List[str]:
|
||||
preset_names = [prop for prop in dir(cls) if isinstance(getattr(cls, prop), property)]
|
||||
return preset_names
|
||||
|
||||
@classmethod
|
||||
def get_collection_preset_names(cls) -> List[str]:
|
||||
return [name for name in cls.get_preset_names() if "collection" in name]
|
||||
|
||||
@classmethod
|
||||
def get_non_collection_preset_names(cls) -> List[str]:
|
||||
return [name for name in cls.get_preset_names() if "collection" not in name]
|
||||
|
||||
@classmethod
|
||||
def get_presets(cls, preset_names: Optional[List[str]] = None) -> List[Preset]:
|
||||
if preset_names is None:
|
||||
preset_names = cls.get_preset_names()
|
||||
|
||||
return [getattr(cls(), preset_name) for preset_name in preset_names]
|
||||
|
||||
|
||||
class PrebuiltKodiTVShowPresets(PrebuiltPresets):
|
||||
BASE_PRESET = "kodi-tv-show"
|
||||
|
||||
@property
|
||||
def kodi_tv_show_url(self) -> Preset:
|
||||
"""
|
||||
Kodi TV Show with seasons as years, episodes ordered by upload date
|
||||
"""
|
||||
return self._tv_show_url(name="kodi_tv_show_url")
|
||||
|
||||
@property
|
||||
def kodi_tv_show_url_reversed(self) -> Preset:
|
||||
"""
|
||||
Kodi TV Show with seasons as years, episodes ordered by upload date in descending order
|
||||
(more recent uploads have smaller episode number)
|
||||
"""
|
||||
return self._tv_show_url_reversed(name="kodi_tv_show_url_reversed")
|
||||
|
||||
@property
|
||||
def kodi_tv_show_youtube_channel(self) -> Preset:
|
||||
"""
|
||||
Kodi TV Show from a YouTube channel with seasons as years, episodes ordered by upload date
|
||||
"""
|
||||
return self._tv_show_youtube_channel(name="kodi_tv_show_youtube_channel")
|
||||
|
||||
@property
|
||||
def kodi_tv_show_youtube_channel_reversed(self) -> Preset:
|
||||
"""
|
||||
Kodi TV Show from a YouTube channel with seasons as years, episodes ordered by upload date
|
||||
in descending order (more recent uploads have smaller episode number)
|
||||
"""
|
||||
return self._tv_show_youtube_channel_reversed(name="kodi_tv_show_youtube_channel_reversed")
|
||||
|
||||
@property
|
||||
def kodi_tv_show_collection(self) -> Preset:
|
||||
"""
|
||||
Kodi TV Show from a collection of multiple URLs. TODO: finish docstring
|
||||
"""
|
||||
return self._tv_show_collection(name="kodi_tv_show_collection")
|
||||
|
||||
@property
|
||||
def kodi_tv_show_collection_reversed(self) -> Preset:
|
||||
"""
|
||||
Kodi TV Show from a collection of multiple URLs. TODO: finish docstring
|
||||
"""
|
||||
return self._tv_show_collection_reversed(name="kodi_tv_show_collection_reversed")
|
||||
|
||||
|
||||
class PrebuiltJellyfinTVShowPresets(PrebuiltPresets):
|
||||
BASE_PRESET = "jellyfin-tv-show"
|
||||
|
||||
@property
|
||||
def jellyfin_tv_show_url(self) -> Preset:
|
||||
"""
|
||||
Kodi TV Show with seasons as years, episodes ordered by upload date
|
||||
"""
|
||||
return self._tv_show_url(name="jellyfin_tv_show_url")
|
||||
|
||||
@property
|
||||
def jellyfin_tv_show_url_reversed(self) -> Preset:
|
||||
"""
|
||||
Kodi TV Show with seasons as years, episodes ordered by upload date in descending order
|
||||
(more recent uploads have smaller episode number)
|
||||
"""
|
||||
return self._tv_show_url_reversed(name="jellyfin_tv_show_url_reversed")
|
||||
|
||||
@property
|
||||
def jellyfin_tv_show_youtube_channel(self) -> Preset:
|
||||
"""
|
||||
Kodi TV Show from a YouTube channel with seasons as years, episodes ordered by upload date
|
||||
"""
|
||||
return self._tv_show_youtube_channel(name="jellyfin_tv_show_youtube_channel")
|
||||
|
||||
@property
|
||||
def jellyfin_tv_show_youtube_channel_reversed(self) -> Preset:
|
||||
"""
|
||||
Kodi TV Show from a YouTube channel with seasons as years, episodes ordered by upload date
|
||||
in descending order (more recent uploads have smaller episode number)
|
||||
"""
|
||||
return self._tv_show_youtube_channel_reversed(
|
||||
name="jellyfin_tv_show_youtube_channel_reversed"
|
||||
)
|
||||
|
||||
@property
|
||||
def jellyfin_tv_show_collection(self) -> Preset:
|
||||
"""
|
||||
Kodi TV Show from a collection of multiple URLs. TODO: finish docstring
|
||||
"""
|
||||
return self._tv_show_collection(name="jellyfin_tv_show_collection")
|
||||
|
||||
@property
|
||||
def jellyfin_tv_show_collection_reversed(self) -> Preset:
|
||||
"""
|
||||
Kodi TV Show from a collection of multiple URLs. TODO: finish docstring
|
||||
"""
|
||||
return self._tv_show_collection_reversed(name="jellyfin_tv_show_collection_reversed")
|
||||
|
|
@ -2,6 +2,7 @@ presets:
|
|||
|
||||
####################################################################################################
|
||||
|
||||
# TV show from any single source. Uses latest entry's thumbnail as tv show poster
|
||||
tv-show-url:
|
||||
generic:
|
||||
download_strategy: "source"
|
||||
|
|
@ -12,6 +13,7 @@ presets:
|
|||
|
||||
####################################################################################################
|
||||
|
||||
# TV show from a single YouTube channel. Uses avatar and banner as poster and fanart.
|
||||
tv-show-youtube-channel:
|
||||
generic:
|
||||
download_strategy: "source"
|
||||
|
|
@ -24,6 +26,8 @@ presets:
|
|||
|
||||
####################################################################################################
|
||||
|
||||
# TV show from a collection. Must specify additional `tv-show-collection-season` presets in
|
||||
# addition. Each season sets its own `collection_season_number/_padded`
|
||||
tv-show-collection:
|
||||
generic:
|
||||
download_strategy: "collection"
|
||||
|
|
@ -5,8 +5,8 @@ import pytest
|
|||
|
||||
from ytdl_sub.config.config_file import ConfigFile
|
||||
from ytdl_sub.config.preset import Preset
|
||||
from ytdl_sub.prebuilt_presets import PrebuiltKodiTVShowPresets
|
||||
from ytdl_sub.prebuilt_presets.tv_show.out import PrebuiltJellyfinTVShowPresets
|
||||
from ytdl_sub.prebuilt_presets.tv_show import PrebuiltJellyfinTVShowPresets
|
||||
from ytdl_sub.prebuilt_presets.tv_show import PrebuiltKodiTVShowPresets
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
@ -18,18 +18,44 @@ def config() -> ConfigFile:
|
|||
|
||||
class TestPrebuiltTVShowPresets:
|
||||
@pytest.mark.parametrize(
|
||||
"preset_name",
|
||||
"media_player_preset",
|
||||
[
|
||||
*PrebuiltKodiTVShowPresets.get_non_collection_preset_names(),
|
||||
*PrebuiltJellyfinTVShowPresets.get_non_collection_preset_names(),
|
||||
],
|
||||
)
|
||||
def test_non_collection_presets_compile(self, config, preset_name: str):
|
||||
@pytest.mark.parametrize(
|
||||
"tv_show_structure_preset",
|
||||
[
|
||||
"season-by-year-month--episode-by-day",
|
||||
"season-by-year--episode-by-month-day",
|
||||
"season-by-year--episode-by-month-day-reversed",
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"episode_hour_granularity_preset",
|
||||
[
|
||||
None,
|
||||
"episode-add-hour-granularity",
|
||||
"episode-add-hour-granularity-reversed",
|
||||
],
|
||||
)
|
||||
def test_non_collection_presets_compile(
|
||||
self,
|
||||
config: ConfigFile,
|
||||
media_player_preset: str,
|
||||
tv_show_structure_preset: str,
|
||||
episode_hour_granularity_preset: str,
|
||||
):
|
||||
parent_presets = [media_player_preset, tv_show_structure_preset]
|
||||
if episode_hour_granularity_preset:
|
||||
parent_presets.append(episode_hour_granularity_preset)
|
||||
|
||||
preset = Preset.from_dict(
|
||||
config=config,
|
||||
preset_name=f"{preset_name}-test",
|
||||
preset_name=f"{media_player_preset}-test",
|
||||
preset_dict={
|
||||
"preset": preset_name,
|
||||
"preset": parent_presets,
|
||||
"overrides": {
|
||||
"url": "https://your.name.here",
|
||||
"tv_show_name": "test tv show",
|
||||
|
|
@ -40,20 +66,42 @@ class TestPrebuiltTVShowPresets:
|
|||
assert preset
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"preset_name",
|
||||
"media_player_preset",
|
||||
[
|
||||
*PrebuiltKodiTVShowPresets.get_collection_preset_names(),
|
||||
*PrebuiltJellyfinTVShowPresets.get_collection_preset_names(),
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"season_indices", [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [4, 1]]
|
||||
"tv_show_structure_preset",
|
||||
[
|
||||
"season-by-collection--episode-by-year-month-day",
|
||||
"season-by-collection--episode-by-year-month-day-reversed",
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"episode_hour_granularity_preset",
|
||||
[
|
||||
None,
|
||||
"episode-add-hour-granularity",
|
||||
"episode-add-hour-granularity-reversed",
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize("season_indices", [[1], [1, 2, 3, 4, 5]])
|
||||
@pytest.mark.parametrize("is_season_1_youtube_channel", [True, False])
|
||||
def test_collection_presets_compile(
|
||||
self, config, preset_name: str, season_indices: List[int], is_season_1_youtube_channel: bool
|
||||
self,
|
||||
config,
|
||||
media_player_preset: str,
|
||||
tv_show_structure_preset: str,
|
||||
episode_hour_granularity_preset: str,
|
||||
season_indices: List[int],
|
||||
is_season_1_youtube_channel: bool,
|
||||
):
|
||||
parent_presets: List[str] = [preset_name]
|
||||
parent_presets: List[str] = [media_player_preset, tv_show_structure_preset]
|
||||
if episode_hour_granularity_preset:
|
||||
parent_presets.append(episode_hour_granularity_preset)
|
||||
|
||||
overrides: Dict[str, str] = {}
|
||||
for season_index in season_indices:
|
||||
parent_presets.append(f"tv-show-collection-season-{season_index}")
|
||||
|
|
@ -70,7 +118,7 @@ class TestPrebuiltTVShowPresets:
|
|||
|
||||
preset = Preset.from_dict(
|
||||
config=config,
|
||||
preset_name=f"{preset_name}-test",
|
||||
preset_name=f"{media_player_preset}-test",
|
||||
preset_dict={
|
||||
"preset": parent_presets,
|
||||
"overrides": dict(
|
||||
|
|
|
|||
Loading…
Reference in a new issue