diff --git a/docs/index.rst b/docs/index.rst index ced478d4..5564031f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -21,4 +21,5 @@ Contents .. toctree:: :maxdepth: 2 + presets config diff --git a/docs/presets.rst b/docs/presets.rst new file mode 100644 index 00000000..593959c7 --- /dev/null +++ b/docs/presets.rst @@ -0,0 +1,119 @@ +Presets +======= +``ytdl-sub`` offers a number of built-in presets using best practices for formatting +media in various players. + +TV Shows +-------- + +There are two main methods for downloading and formatting videos as a TV show. + +TV Show by Date +^^^^^^^^^^^^^^^ + +TV Show by Date will organize something like a YouTube channel or playlist +into a tv show, where seasons and episodes are organized using upload date. + +Player Presets +"""""""""""""" + +* ``kodi_tv_show_by_date`` +* ``jellyfin_tv_show_by_date`` +* ``plex_tv_show_by_date`` + +Episode Formatting Presets +"""""""""""""""""""""""""" + +* ``season_by_year__episode_by_month_day`` +* ``season_by_year_month__episode_by_day`` +* ``season_by_year__episode_by_month_day_reversed`` + * Episode numbers are reversed, meaning more recent episodes appear at the + top of a season by having a lower value. + +Usage +""""" + +A preset/subscription requires specifying a player and episode formatting preset +and overriding the following variables: + +.. code-block:: yaml + + rick_a_tv_show_by_date: + preset: + - "jellyfin_tv_show_by_date" + - "season_by_year__episode_by_month_day" + overrides: + # required + tv_show_name: "Rick A" + tv_show_directory: "/path/to/youtube_shows" + url: "https://www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw" + # can be modified from their default value + # episode_title: "{upload_date_standardized} - {title}" + # episode_description: "{webpage_url}" + + +TV Show Collection +^^^^^^^^^^^^^^^^^^ + +TV Show Collections are made up from multiple URLs, where each URL is a season. +If a video belongs to multiple URLs (i.e. a channel and a channel's playlist), +it will resolve to the bottom-most season. + +Two main use cases of a collection are: + 1. Organize a YouTube channel TV show where Season 1 contains any video + not in a 'season playlist', Season 2 for 'Playlist A', Season 3 for + 'Playlist B', etc. + 2. Organize one or more YouTube channels/playlists, where each season + represents a separate channel/playlist. + +Player Presets +"""""""""""""" + +* ``kodi_tv_show_collection`` +* ``jellyfin_tv_show_collection`` +* ``plex_tv_show_collection`` + +Episode Formatting Presets +"""""""""""""""""""""""""" + +* ``season_by_collection__episode_by_year_month_day`` +* ``season_by_collection__episode_by_year_month_day_reversed`` +* ``season_by_collection__episode_by_playlist_index`` + * Only use playlist_index episode formatting for playlists that + will never change. Otherwise, indices get messed up. +* ``season_by_collection__episode_by_playlist_index_reversed`` + +Season Presets +"""""""""""""" + +* ``collection_season_1`` +* ``collection_season_2`` +* ``collection_season_3`` +* ``collection_season_4`` +* ``collection_season_5`` + +Example +""""""" + +A preset/subscription requires specifying a player, episode formatting, and +one or more season presets, with the following override variables: + +.. code-block:: yaml + + rick_a_tv_show_collection: + preset: + - "jellyfin_tv_show_collection" + - "season_by_collection__episode_by_year_month_day_reversed" + - "collection_season_1" + - "collection_season_2" + overrides: + # required + tv_show_name: "Rick A" + tv_show_directory: "/path/to/youtube_shows" + collection_season_1_url: "https://www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw" + collection_season_1_name: "All Videos" + collection_season_2_url: "https://www.youtube.com/playlist?list=PLlaN88a7y2_plecYoJxvRFTLHVbIVAOoc" + collection_season_2_name: "Official Music Videos" + # can be modified from their default value + # episode_title: "{upload_date_standardized} - {title}" + # episode_description: "{webpage_url}" diff --git a/src/ytdl_sub/prebuilt_presets/__init__.py b/src/ytdl_sub/prebuilt_presets/__init__.py index baf18e67..f60dd237 100644 --- a/src/ytdl_sub/prebuilt_presets/__init__.py +++ b/src/ytdl_sub/prebuilt_presets/__init__.py @@ -4,8 +4,8 @@ from typing import Dict import mergedeep -from ytdl_sub.prebuilt_presets.tv_show import PrebuiltTvShowCollectionPresets 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 @@ -21,7 +21,7 @@ def _merge_presets() -> Dict[str, Any]: mergedeep.merge( merged_configs, *TvShowByDatePresets.get_presets(), - *PrebuiltTvShowCollectionPresets.get_presets(), + *TvShowCollectionPresets.get_presets(), ) return merged_configs["presets"] diff --git a/src/ytdl_sub/prebuilt_presets/tv_show/__init__.py b/src/ytdl_sub/prebuilt_presets/tv_show/__init__.py index 93e7fd7f..dc53dfc1 100644 --- a/src/ytdl_sub/prebuilt_presets/tv_show/__init__.py +++ b/src/ytdl_sub/prebuilt_presets/tv_show/__init__.py @@ -69,7 +69,7 @@ class TvShowByDatePresets(PrebuiltPresets): """ @property - def kodi_tv_show_by_date(self) -> Preset: + def kodi_tv_show_by_date(self): """ Formats a TV show organized by date for Kodi """ @@ -78,7 +78,7 @@ class TvShowByDatePresets(PrebuiltPresets): ) @property - def jellyfin_tv_show_by_date(self) -> Preset: + def jellyfin_tv_show_by_date(self): """ Formats a TV show organized by date for Jellyfin """ @@ -87,7 +87,7 @@ class TvShowByDatePresets(PrebuiltPresets): ) @property - def plex_tv_show_by_date(self) -> Preset: + def plex_tv_show_by_date(self): """ Formats a TV show organized by date for Plex """ @@ -96,7 +96,7 @@ class TvShowByDatePresets(PrebuiltPresets): ) -class PrebuiltTvShowUrlEpisodeOrderingPresets(PrebuiltPresets): +class TvShowByDateEpisodeFormattingPresets(PrebuiltPresets): @property def season_by_year__episode_by_month_day(self) -> Preset: """ @@ -119,7 +119,7 @@ class PrebuiltTvShowUrlEpisodeOrderingPresets(PrebuiltPresets): return self._document_preset() -class PrebuiltTvShowCollectionPresets(PrebuiltPresets): +class TvShowCollectionPresets(PrebuiltPresets): """ Docstring for all TV SHOW URL presets """ @@ -153,7 +153,7 @@ class PrebuiltTvShowCollectionPresets(PrebuiltPresets): ) -class PrebuiltTvShowCollectionEpisodeOrderingPresets(PrebuiltPresets): +class TvShowCollectionEpisodeFormattingPresets(PrebuiltPresets): @property def season_by_collection__episode_by_year_month_day(self) -> Preset: """ @@ -183,7 +183,7 @@ class PrebuiltTvShowCollectionEpisodeOrderingPresets(PrebuiltPresets): return self._document_preset() -class PrebuiltTvShowCollectionSeasonPresets(PrebuiltPresets): +class TvShowCollectionSeasonPresets(PrebuiltPresets): @property def collection_season_1(self): """ diff --git a/tests/unit/prebuilt_presets/test_prebuilt_presets.py b/tests/unit/prebuilt_presets/test_prebuilt_presets.py index 6577cde9..c08375ee 100644 --- a/tests/unit/prebuilt_presets/test_prebuilt_presets.py +++ b/tests/unit/prebuilt_presets/test_prebuilt_presets.py @@ -6,18 +6,18 @@ import pytest from expected_download import assert_expected_downloads from expected_transaction_log import assert_transaction_log_matches -from ytdl_sub.prebuilt_presets import PrebuiltTvShowCollectionPresets from ytdl_sub.prebuilt_presets import TvShowByDatePresets -from ytdl_sub.prebuilt_presets.tv_show import PrebuiltTvShowCollectionEpisodeOrderingPresets -from ytdl_sub.prebuilt_presets.tv_show import PrebuiltTvShowCollectionSeasonPresets -from ytdl_sub.prebuilt_presets.tv_show import PrebuiltTvShowUrlEpisodeOrderingPresets +from ytdl_sub.prebuilt_presets import TvShowCollectionPresets +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 TvShowCollectionSeasonPresets from ytdl_sub.subscriptions.subscription import Subscription from ytdl_sub.utils.exceptions import ValidationException @pytest.mark.parametrize("media_player_preset", TvShowByDatePresets.get_preset_names()) @pytest.mark.parametrize( - "tv_show_structure_preset", PrebuiltTvShowUrlEpisodeOrderingPresets.get_preset_names() + "tv_show_structure_preset", TvShowByDateEpisodeFormattingPresets.get_preset_names() ) class TestPrebuiltTVShowPresets: def test_compilation( @@ -112,14 +112,12 @@ class TestPrebuiltTVShowPresets: ) -@pytest.mark.parametrize("media_player_preset", PrebuiltTvShowCollectionPresets.get_preset_names()) +@pytest.mark.parametrize("media_player_preset", TvShowCollectionPresets.get_preset_names()) @pytest.mark.parametrize( - "tv_show_structure_preset", PrebuiltTvShowCollectionEpisodeOrderingPresets.get_preset_names() + "tv_show_structure_preset", TvShowCollectionEpisodeFormattingPresets.get_preset_names() ) class TestPrebuiltTvShowCollectionPresets: - @pytest.mark.parametrize( - "season_preset", PrebuiltTvShowCollectionSeasonPresets.get_preset_names() - ) + @pytest.mark.parametrize("season_preset", TvShowCollectionSeasonPresets.get_preset_names()) def test_compilation( self, config, @@ -143,9 +141,7 @@ class TestPrebuiltTvShowCollectionPresets: }, ) - @pytest.mark.parametrize( - "season_preset", PrebuiltTvShowCollectionSeasonPresets.get_preset_names() - ) + @pytest.mark.parametrize("season_preset", TvShowCollectionSeasonPresets.get_preset_names()) def test_compilation_errors_missing_one( self, config,