diff --git a/docs/conf.py b/docs/conf.py index 4102001e..faf3ee3b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -49,6 +49,8 @@ exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # html_theme = "sphinx_rtd_theme" +html_theme_options = {"navigation_depth": 8} + # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". @@ -56,6 +58,6 @@ html_theme = "sphinx_rtd_theme" # Do not show full module path in api docs add_module_names = False -python_use_unqualified_type_names = True +python_use_unqualified_type_names = False napoleon_numpy_docstrings = True napoleon_use_rtype = False diff --git a/docs/config.rst b/docs/config.rst index 5e502c32..1a881619 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -1,5 +1,5 @@ -Configuration -============= +Config +====== ytdl-sub is configured in the ``config.yaml`` and consists of two sections: .. code-block:: yaml @@ -7,21 +7,30 @@ ytdl-sub is configured in the ``config.yaml`` and consists of two sections: configuration: presets: +config.yaml +----------- + +configuration +^^^^^^^^^^^^^ + The ``configuration`` section contains app-wide configs. -Presets -------- +presets +^^^^^^^ ``presets`` define a `formula` for how to format downloaded media and metadata. -Required: Source Download Strategy -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +source +"""""" Download strategies dictate what exactly is getting downloaded from which source. By having separate strategies, we can define strategy-dependent parameters to better fine-tune how we download things. -youtube: channel -"""""""""""""""" +youtube +''''''' + +channel +....... .. code-block:: yaml presets: @@ -29,14 +38,30 @@ youtube: channel youtube: download_strategy: "channel" -.. autoclass:: ytdl_sub.downloaders.youtube_downloader.YoutubeChannelDownloaderOptions() - :members: - :inherited-members: - :member-order: bysource - :exclude-members: get_date_range +channel_id +__________ + .. autoproperty:: ytdl_sub.downloaders.youtube_downloader.YoutubeChannelDownloaderOptions.channel_id -youtube: playlist -""""""""""""""""" +channel_avatar_path +___________________ + .. autoproperty:: ytdl_sub.downloaders.youtube_downloader.YoutubeChannelDownloaderOptions.channel_avatar_path + +channel_banner_path +___________________ + .. autoproperty:: ytdl_sub.downloaders.youtube_downloader.YoutubeChannelDownloaderOptions.channel_banner_path + +before +______ + .. autoproperty:: ytdl_sub.downloaders.youtube_downloader.YoutubeChannelDownloaderOptions.before + +after +_____ + .. autoproperty:: ytdl_sub.downloaders.youtube_downloader.YoutubeChannelDownloaderOptions.after + +-------- + +playlist +........ .. code-block:: yaml presets: @@ -44,12 +69,14 @@ youtube: playlist youtube: download_strategy: "playlist" -.. autoclass:: ytdl_sub.downloaders.youtube_downloader.YoutubePlaylistDownloaderOptions() - :members: - :inherited-members: +playlist_id +___________ + .. autoproperty:: ytdl_sub.downloaders.youtube_downloader.YoutubePlaylistDownloaderOptions.playlist_id -youtube: video -"""""""""""""" +-------- + +video +..... .. code-block:: yaml presets: @@ -57,12 +84,17 @@ youtube: video youtube: download_strategy: "video" -.. autoclass:: ytdl_sub.downloaders.youtube_downloader.YoutubeVideoDownloaderOptions() - :members: - :inherited-members: +video_id +________ + .. autoproperty:: ytdl_sub.downloaders.youtube_downloader.YoutubeVideoDownloaderOptions.video_id -soundcloud: albums_and_singles -"""""""""""""""""""""""""""""" +-------- + +soundcloud +'''''''''' + +albums_and_singles +.................. .. code-block:: yaml presets: @@ -70,36 +102,60 @@ soundcloud: albums_and_singles soundcloud: download_strategy: "albums_and_singles" -.. autoclass:: ytdl_sub.downloaders.soundcloud_downloader.SoundcloudAlbumsAndSinglesDownloadOptions() - :members: - :inherited-members: - :member-order: bysource +username +________ + .. autoproperty:: ytdl_sub.downloaders.soundcloud_downloader.SoundcloudAlbumsAndSinglesDownloadOptions.username -Required: Output Options -^^^^^^^^^^^^^^^^^^^^^^^^ -TODO +skip_premiere_tracks +____________________ + .. autoproperty:: ytdl_sub.downloaders.soundcloud_downloader.SoundcloudAlbumsAndSinglesDownloadOptions.skip_premiere_tracks + +-------- + +output_options +"""""""""""""" + +output_directory +'''''''''''''''' + .. autoproperty:: ytdl_sub.config.preset_options.OutputOptions.output_directory + +file_name +''''''''' + .. autoproperty:: ytdl_sub.config.preset_options.OutputOptions.file_name + +thumbnail_name +'''''''''''''' + .. autoproperty:: ytdl_sub.config.preset_options.OutputOptions.thumbnail_name + +maintain_download_archive +''''''''''''''''''''''''' + .. autoproperty:: ytdl_sub.config.preset_options.OutputOptions.maintain_download_archive + +keep_files +'''''''''' + .. autoproperty:: ytdl_sub.config.preset_options.OutputOptions.keep_files YTDL Options -^^^^^^^^^^^^ +"""""""""""" TODO Overrides -^^^^^^^^^ +""""""""" TODO Plugins -^^^^^^^ +""""""" Music Tags -"""""""""" +'''''''''' TODO NFO -""" +''' TODO NFO Output Directory -"""""""""""""""""""" +'''''''''''''''''''' TODO Format Variables diff --git a/docs/examples.rst b/docs/examples.rst index c88fb86f..d1838daa 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -33,7 +33,7 @@ subscriptions.yaml :literal: Kodi/Jellyfin Music Videos ----------------------- +-------------------------- config.yaml ^^^^^^^^^^^ diff --git a/docs/index.rst b/docs/index.rst index bc38ce90..421058ac 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -15,7 +15,7 @@ Contents ======== .. toctree:: - :maxdepth: 3 + :maxdepth: 5 getting_started config diff --git a/src/ytdl_sub/config/preset_options.py b/src/ytdl_sub/config/preset_options.py index 7e60d9bf..d2af9466 100644 --- a/src/ytdl_sub/config/preset_options.py +++ b/src/ytdl_sub/config/preset_options.py @@ -60,26 +60,94 @@ class OutputOptions(StrictDictValidator): # Output directory should resolve without any entry variables. # This is to check the directory for any download-archives before any downloads begin - self.output_directory: OverridesStringFormatterValidator = self._validate_key( + self._output_directory: OverridesStringFormatterValidator = self._validate_key( key="output_directory", validator=OverridesStringFormatterValidator ) # file name and thumbnails however can use entry variables - self.file_name: StringFormatterValidator = self._validate_key( + self._file_name: StringFormatterValidator = self._validate_key( key="file_name", validator=StringFormatterValidator ) - self.thumbnail_name = self._validate_key_if_present( + self._thumbnail_name = self._validate_key_if_present( key="thumbnail_name", validator=StringFormatterValidator ) - self.maintain_download_archive = self._validate_key_if_present( + self._maintain_download_archive = self._validate_key_if_present( key="maintain_download_archive", validator=BoolValidator, default=False ) - self.delete_stale_files = self._validate_key_if_present( + self._keep_files = self._validate_key_if_present( key="keep_files", validator=DateRangeValidator ) - if self.delete_stale_files and not self.maintain_download_archive: + if self._keep_files and not self.maintain_download_archive: raise self._validation_exception( "keep_files requires maintain_download_archive set to True" ) + + @property + def output_directory(self) -> OverridesStringFormatterValidator: + """ + Required. The output directory to store all media files downloaded. + """ + return self._output_directory + + @property + def file_name(self) -> StringFormatterValidator: + """ + Required. The file name for the media file. This can include directories such as + ``"Season {upload_year}/{title}.{ext}"``, and will be placed in the output directory. + """ + return self._file_name + + @property + def thumbnail_name(self) -> Optional[StringFormatterValidator]: + """ + Optional. The file name for the media's thumbnail image. This can include directories such + as ``"Season {upload_year}/{title}.{thumbnail_ext}"``, and will be placed in the output + directory. + """ + return self._thumbnail_name + + @property + def maintain_download_archive(self) -> bool: + """ + Optional. Maintains a download archive file in the output directory for a subscription. + It is named ``.ytdl-sub-{subscription_name}-download-archive.json``, stored in the + output directory. + + The download archive contains a mapping of ytdl IDs to downloaded files. This is used to + create a ytdl download-archive file when invoking a download on a subscription. This will + prevent ytdl from redownloading media already downloaded. + + Defaults to False. + """ + return self._maintain_download_archive.value + + @property + def keep_files(self) -> DateRangeValidator: + """ + Optional. Requires ``maintain_download_archive`` set to True. + + Only keeps files that are uploaded in the defined range. Should be formatted as: + + .. code-block:: yaml + + output_options: + keep_files: + before: + after: + + where ``before`` and ``after`` are date-times. A common usage of this option is to only + fill in the after, such as: + + .. code-block:: yaml + + output_options: + keep_files: + after: today-2weeks + + Which translates to 'keep files uploaded in the last two weeks'. + + By default, ytdl-sub will keep all files. + """ + return self._keep_files diff --git a/src/ytdl_sub/subscriptions/subscription.py b/src/ytdl_sub/subscriptions/subscription.py index 54dbe718..11333731 100644 --- a/src/ytdl_sub/subscriptions/subscription.py +++ b/src/ytdl_sub/subscriptions/subscription.py @@ -202,9 +202,9 @@ class Subscription: # If output options maintains stale file deletion, perform the delete here prior to saving # the download archive if self.output_options.maintain_download_archive: - if self.output_options.delete_stale_files: + if self.output_options.keep_files: self._enhanced_download_archive.remove_stale_files( - date_range=self.output_options.delete_stale_files.get_date_range() + date_range=self.output_options.keep_files.get_date_range() ) self._enhanced_download_archive.save_download_mappings() diff --git a/src/ytdl_sub/ytdl_additions/enhanced_download_archive.py b/src/ytdl_sub/ytdl_additions/enhanced_download_archive.py index 50786b89..fe86c95e 100644 --- a/src/ytdl_sub/ytdl_additions/enhanced_download_archive.py +++ b/src/ytdl_sub/ytdl_additions/enhanced_download_archive.py @@ -355,7 +355,7 @@ class EnhancedDownloadArchive: ------- The download mapping's file name (no path) """ - return f".ytdl-subscribe-{self.subscription_name}-download-mapping.json" + return f".ytdl-sub-{self.subscription_name}-download-archive.json" @property def _mapping_output_file_path(self):