diff --git a/src/ytdl_sub/config/preset_class_mappings.py b/src/ytdl_sub/config/preset_class_mappings.py index 73be4059..52867a1f 100644 --- a/src/ytdl_sub/config/preset_class_mappings.py +++ b/src/ytdl_sub/config/preset_class_mappings.py @@ -4,6 +4,7 @@ from typing import Type from ytdl_sub.downloaders.downloader import Downloader from ytdl_sub.downloaders.generic.collection import CollectionDownloader +from ytdl_sub.downloaders.generic.source import SourceDownloader from ytdl_sub.downloaders.soundcloud.albums_and_singles import SoundcloudAlbumsAndSinglesDownloader from ytdl_sub.downloaders.youtube.channel import YoutubeChannelDownloader from ytdl_sub.downloaders.youtube.merge_playlist import YoutubeMergePlaylistDownloader @@ -39,6 +40,7 @@ class DownloadStrategyMapping: }, "generic": { "collection": CollectionDownloader, + "source": SourceDownloader, }, } diff --git a/src/ytdl_sub/downloaders/generic/collection_validator.py b/src/ytdl_sub/downloaders/generic/collection_validator.py index ebbfe9a3..2772c6fc 100644 --- a/src/ytdl_sub/downloaders/generic/collection_validator.py +++ b/src/ytdl_sub/downloaders/generic/collection_validator.py @@ -79,15 +79,38 @@ class CollectionUrlValidator(StrictDictValidator): @property def source_thumbnails(self) -> Optional[CollectionThumbnailListValidator]: """ - Thumbnails to download from the source, if any exist. The hierarchy is + Thumbnails to download from the source, if any exist. The hierarchy is defined as source -> playlist -> entry. + + Usage: + + .. code-block:: yaml + + source_thumbnails: + - name: "poster.jpg" + uid: "avatar_uncropped" + + UID is the yt-dlp thumbnail ID or can specify ``latest_entry`` to use the last entry's + thumbnail that was downloaded. """ return self._source_thumbnails @property def playlist_thumbnails(self) -> Optional[CollectionThumbnailListValidator]: """ - TODO:docstring + Thumbnails to download from the source, if any exist. The hierarchy is defined as + source -> playlist -> entry. + + Usage: + + .. code-block:: yaml + + playlist_thumbnails: + - name: "poster.jpg" + uid: "avatar_uncropped" + + UID is the yt-dlp thumbnail ID or can specify ``latest_entry`` to use the last entry's + thumbnail that was downloaded. """ return self._playlist_thumbnails diff --git a/src/ytdl_sub/downloaders/generic/source.py b/src/ytdl_sub/downloaders/generic/source.py new file mode 100644 index 00000000..a28134c6 --- /dev/null +++ b/src/ytdl_sub/downloaders/generic/source.py @@ -0,0 +1,39 @@ +from ytdl_sub.downloaders.downloader import Downloader +from ytdl_sub.downloaders.downloader import DownloaderValidator +from ytdl_sub.downloaders.generic.collection_validator import CollectionUrlValidator +from ytdl_sub.downloaders.generic.collection_validator import CollectionValidator + + +class SourceDownloadOptions(CollectionUrlValidator, DownloaderValidator): + """ + Downloads from a single URL supported by yt-dlp. + + Usage: + + .. code-block:: yaml + + presets: + my_example_preset: + generic: + # required + download_strategy: "source" + url: "youtube.com/channel/UCsvn_Po0SmunchJYtttWpOxMg" + # optional + playlist_thumbnails: + - name: "poster.jpg" + uid: "avatar_uncropped" + - name: "fanart.jpg" + uid: "banner_uncropped" + """ + + @property + def collection_validator(self) -> CollectionValidator: + """Returns itself!""" + return CollectionValidator( + name=self._name, + value={"urls": [self._value]}, + ) + + +class SourceDownloader(Downloader[SourceDownloadOptions]): + downloader_options_type = SourceDownloadOptions diff --git a/src/ytdl_sub/downloaders/youtube/video.py b/src/ytdl_sub/downloaders/youtube/video.py index d469cb06..c9b9f951 100644 --- a/src/ytdl_sub/downloaders/youtube/video.py +++ b/src/ytdl_sub/downloaders/youtube/video.py @@ -3,6 +3,7 @@ from typing import Dict from ytdl_sub.downloaders.downloader import Downloader from ytdl_sub.downloaders.downloader import DownloaderValidator from ytdl_sub.downloaders.generic.collection_validator import CollectionValidator +from ytdl_sub.downloaders.generic.source import SourceDownloadOptions from ytdl_sub.validators.url_validator import YoutubeVideoUrlValidator @@ -38,10 +39,9 @@ class YoutubeVideoDownloaderOptions(DownloaderValidator): @property def collection_validator(self) -> CollectionValidator: """Downloads the video url""" - return CollectionValidator( - name=self._name, - value={"urls": [{"url": self.video_url, "variables": {"playlist_size": "1"}}]}, - ) + return SourceDownloadOptions( + name=self._name, value={"url": self.video_url} + ).collection_validator @property def video_url(self) -> str: