diff --git a/ytdl_subscribe/subscriptions/soundcloud.py b/ytdl_subscribe/subscriptions/soundcloud.py index 7ae75cc4..1357cd9a 100644 --- a/ytdl_subscribe/subscriptions/soundcloud.py +++ b/ytdl_subscribe/subscriptions/soundcloud.py @@ -1,18 +1,39 @@ +from abc import ABC from typing import List from ytdl_subscribe.downloaders.soundcloud_downloader import SoundcloudDownloader from ytdl_subscribe.entries.soundcloud import SoundcloudAlbum from ytdl_subscribe.entries.soundcloud import SoundcloudTrack +from ytdl_subscribe.subscriptions.subscription import SourceT from ytdl_subscribe.subscriptions.subscription import Subscription +from ytdl_subscribe.validators.config.config_options.config_options_validator import ( + ConfigOptionsValidator, +) +from ytdl_subscribe.validators.config.preset_validator import PresetValidator from ytdl_subscribe.validators.config.source_options.soundcloud_validators import ( SoundcloudAlbumsAndSinglesSourceValidator, ) +class SoundcloudSubscription(Subscription[SourceT], ABC): + def __init__( + self, + name: str, + config_options: ConfigOptionsValidator, + preset_options: PresetValidator, + ): + super().__init__( + name=name, + config_options=config_options, + preset_options=preset_options, + entry_type=SoundcloudTrack, + ) + + class SoundcloudAlbumsAndSinglesSubscription( Subscription[SoundcloudAlbumsAndSinglesSourceValidator] ): - def _extract_info(self): + def _extract_info(self) -> List[SoundcloudTrack]: tracks: List[SoundcloudTrack] = [] downloader = self.get_downloader(SoundcloudDownloader) @@ -33,5 +54,4 @@ class SoundcloudAlbumsAndSinglesSubscription( track for track in single_tracks if not any(album.contains(track) for album in albums) ] - for entry in tracks: - self.post_process_entry(entry) + return tracks diff --git a/ytdl_subscribe/subscriptions/subscription.py b/ytdl_subscribe/subscriptions/subscription.py index 4cf689ed..37a8416b 100644 --- a/ytdl_subscribe/subscriptions/subscription.py +++ b/ytdl_subscribe/subscriptions/subscription.py @@ -6,6 +6,7 @@ from pathlib import Path from shutil import copyfile from typing import Dict from typing import Generic +from typing import List from typing import Optional from typing import Type from typing import TypeVar @@ -33,16 +34,18 @@ from ytdl_subscribe.validators.config.source_options.mixins import DownloadDateR from ytdl_subscribe.validators.config.source_options.source_validators import SourceValidator from ytdl_subscribe.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive -S = TypeVar("S", bound=SourceValidator) -D = TypeVar("D", bound=Downloader) +SourceT = TypeVar("SourceT", bound=SourceValidator) +EntryT = TypeVar("EntryT", bound=Entry) +DownloaderT = TypeVar("DownloaderT", bound=Downloader) -class Subscription(Generic[S], ABC): +class Subscription(Generic[SourceT], ABC): def __init__( self, name: str, config_options: ConfigOptionsValidator, preset_options: PresetValidator, + entry_type: Type[EntryT], ): """ Parameters @@ -55,6 +58,7 @@ class Subscription(Generic[S], ABC): self.name = name self.__config_options = config_options self.__preset_options = preset_options + self.__entry_type = entry_type self._enhanced_download_archive = EnhancedDownloadArchive( subscription_name=name, @@ -63,7 +67,11 @@ class Subscription(Generic[S], ABC): ) @property - def source_options(self) -> S: + def entry_type(self) -> EntryT: + return self.__entry_type + + @property + def source_options(self) -> SourceT: """Returns the source options defined for this subscription""" return self.__preset_options.subscription_source @@ -98,8 +106,8 @@ class Subscription(Generic[S], ABC): ) def get_downloader( - self, downloader_type: Type[D], source_ytdl_options: Optional[Dict] = None - ) -> D: + self, downloader_type: Type[DownloaderT], source_ytdl_options: Optional[Dict] = None + ) -> DownloaderT: """Returns the downloader that will be used to download media for this subscription""" # if source_ytdl_options are present, override the ytdl_options with them ytdl_options = self.__preset_options.ytdl_options.dict @@ -239,9 +247,11 @@ class Subscription(Generic[S], ABC): Performs the subscription download. """ with self._maintain_archive_file(): - self._extract_info() + entries = self._extract_info() + for entry in entries: + self.post_process_entry(entry) - def _extract_info(self): + def _extract_info(self) -> List[EntryT]: """ Extracts only the info of the source, does not download it """ diff --git a/ytdl_subscribe/subscriptions/youtube.py b/ytdl_subscribe/subscriptions/youtube.py index 2b6eabd1..d09fec45 100644 --- a/ytdl_subscribe/subscriptions/youtube.py +++ b/ytdl_subscribe/subscriptions/youtube.py @@ -1,7 +1,16 @@ +from abc import ABC +from typing import List + from yt_dlp import DateRange from ytdl_subscribe.downloaders.youtube_downloader import YoutubeDownloader +from ytdl_subscribe.entries.youtube import YoutubeVideo +from ytdl_subscribe.subscriptions.subscription import SourceT from ytdl_subscribe.subscriptions.subscription import Subscription +from ytdl_subscribe.validators.config.config_options.config_options_validator import ( + ConfigOptionsValidator, +) +from ytdl_subscribe.validators.config.preset_validator import PresetValidator from ytdl_subscribe.validators.config.source_options.youtube_validators import ( YoutubeChannelSourceValidator, ) @@ -13,34 +22,42 @@ from ytdl_subscribe.validators.config.source_options.youtube_validators import ( ) -class YoutubePlaylistSubscription(Subscription[YoutubePlaylistSourceValidator]): - def _extract_info(self): - entries = self.get_downloader(YoutubeDownloader).download_playlist( +class YoutubeSubscription(Subscription[SourceT], ABC): + def __init__( + self, + name: str, + config_options: ConfigOptionsValidator, + preset_options: PresetValidator, + ): + super().__init__( + name=name, + config_options=config_options, + preset_options=preset_options, + entry_type=YoutubeVideo, + ) + + +class YoutubePlaylistSubscription(YoutubeSubscription[YoutubePlaylistSourceValidator]): + def _extract_info(self) -> List[YoutubeVideo]: + return self.get_downloader(YoutubeDownloader).download_playlist( playlist_id=self.source_options.playlist_id.value ) - for entry in entries: - self.post_process_entry(entry) - -class YoutubeChannelSubscription(Subscription[YoutubeChannelSourceValidator]): - def _extract_info(self): +class YoutubeChannelSubscription(YoutubeSubscription[YoutubeChannelSourceValidator]): + def _extract_info(self) -> List[YoutubeVideo]: source_ytdl_options = {} source_date_range = self.source_options.get_date_range() if source_date_range: source_ytdl_options["daterange"] = source_ytdl_options downloader = self.get_downloader(YoutubeDownloader, source_ytdl_options=source_ytdl_options) - entries = downloader.download_channel(channel_id=self.source_options.channel_id.value) - - for entry in entries: - self.post_process_entry(entry) + return downloader.download_channel(channel_id=self.source_options.channel_id.value) -class YoutubeVideoSubscription(Subscription[YoutubeVideoSourceValidator]): - def _extract_info(self): +class YoutubeVideoSubscription(YoutubeSubscription[YoutubeVideoSourceValidator]): + def _extract_info(self) -> List[YoutubeVideo]: entry = self.get_downloader(YoutubeDownloader).download_video( video_id=self.source_options.video_id.value ) - - self.post_process_entry(entry) + return [entry]