diff --git a/ytdl_subscribe/subscriptions/soundcloud.py b/ytdl_subscribe/subscriptions/soundcloud.py index ec7d6e66..85eb210f 100644 --- a/ytdl_subscribe/subscriptions/soundcloud.py +++ b/ytdl_subscribe/subscriptions/soundcloud.py @@ -1,4 +1,3 @@ -from abc import ABC from typing import List from ytdl_subscribe.downloaders.soundcloud_downloader import SoundcloudDownloader @@ -13,32 +12,16 @@ from ytdl_subscribe.validators.config.source_options.soundcloud_validators impor ) -class SoundcloudSubscription(Subscription, ABC): - source_validator_type = SoundcloudSourceValidator - downloader_type = SoundcloudDownloader - - @property - def source_options(self) -> SoundcloudSourceValidator: - return super().source_options - - @property - def downloader(self) -> SoundcloudDownloader: - return super().downloader - - -class SoundcloudAlbumsAndSinglesSubscription(SoundcloudSubscription): - download_strategy_type = SoundcloudAlbumsAndSinglesDownloadValidator - - @property - def download_strategy_options(self) -> SoundcloudAlbumsAndSinglesDownloadValidator: - return super().download_strategy_options - +class SoundcloudAlbumsAndSinglesSubscription( + Subscription[SoundcloudSourceValidator, SoundcloudAlbumsAndSinglesDownloadValidator] +): def extract_info(self): tracks: List[SoundcloudTrack] = [] + downloader = self.get_downloader(SoundcloudDownloader) # Get the album info first. This tells us which track ids belong # to an album. Unfortunately we cannot use download_archive or info.json for this - albums: List[SoundcloudAlbum] = self.downloader.download_albums( + albums: List[SoundcloudAlbum] = downloader.download_albums( artist_name=self.download_strategy_options.username.value ) @@ -48,7 +31,7 @@ class SoundcloudAlbumsAndSinglesSubscription(SoundcloudSubscription): ) # only add tracks that are not part of an album - single_tracks = self.downloader.download_tracks( + single_tracks = downloader.download_tracks( artist_name=self.download_strategy_options.username.value ) tracks += [ diff --git a/ytdl_subscribe/subscriptions/subscription.py b/ytdl_subscribe/subscriptions/subscription.py index 2659e527..de0cfbf5 100644 --- a/ytdl_subscribe/subscriptions/subscription.py +++ b/ytdl_subscribe/subscriptions/subscription.py @@ -1,6 +1,8 @@ import os +from abc import ABC from pathlib import Path from shutil import copyfile +from typing import Generic from typing import Type from typing import TypeVar @@ -28,15 +30,11 @@ from ytdl_subscribe.validators.config.source_options.source_validator import ( from ytdl_subscribe.validators.config.source_options.source_validator import SourceValidator T = TypeVar("T", bound=SourceValidator) -U = TypeVar("U", bound=DownloadStrategyValidator) -V = TypeVar("V", bound=Downloader) +U = TypeVar("U", bound=Downloader) +V = TypeVar("V", bound=DownloadStrategyValidator) -class Subscription: - source_validator_type: Type[T] - download_strategy_type: Type[U] - downloader_type: Type[V] - +class Subscription(Generic[T, V], ABC): def __init__( self, name: str, @@ -55,13 +53,22 @@ class Subscription: self.__config_options = config_options self.__preset_options = preset_options - if not isinstance(preset_options.subscription_source, self.source_validator_type): - raise ValueError("Source options does not match the expected type") + @property + def source_options(self) -> T: + """Returns the source options defined for this subscription""" + return self.__preset_options.subscription_source - if not isinstance( - preset_options.subscription_source.download_strategy, self.download_strategy_type - ): - raise ValueError("Download strategy does not match the expected type") + def get_downloader(self, downloader_type: Type[U]) -> U: + """Returns the downloader that will be used to download media for this subscription""" + return downloader_type( + output_directory=self.working_directory, + ytdl_options=self.__preset_options.ytdl_options.dict, + ) + + @property + def download_strategy_options(self) -> V: + """Returns the download strategy options defined for this subscription""" + return self.source_options.download_strategy @property def output_options(self) -> OutputOptionsValidator: @@ -73,16 +80,6 @@ class Subscription: """Returns the metadata options defined for this subscription""" return self.__preset_options.metadata_options - @property - def source_options(self) -> T: - """Returns the source options defined for this subscription""" - return self.__preset_options.subscription_source - - @property - def download_strategy_options(self) -> U: - """Returns the download strategy options defined for this subscription""" - return self.source_options.download_strategy - @property def overrides(self) -> OverridesValidator: """Returns the overrides defined for this subscription""" @@ -93,14 +90,6 @@ class Subscription: """Returns the directory that the downloader saves files to""" return str(Path(self.__config_options.working_directory.value) / Path(self.name)) - @property - def downloader(self) -> V: - """Returns the downloader that will be used to download media for this subscription""" - return self.downloader_type( - output_directory=self.working_directory, - ytdl_options=self.__preset_options.ytdl_options.dict, - ) - def _apply_formatter(self, entry: Entry, formatter: StringFormatterValidator) -> str: """ Parameters diff --git a/ytdl_subscribe/subscriptions/youtube.py b/ytdl_subscribe/subscriptions/youtube.py index f4cfae92..79c7d7f7 100644 --- a/ytdl_subscribe/subscriptions/youtube.py +++ b/ytdl_subscribe/subscriptions/youtube.py @@ -1,5 +1,3 @@ -from abc import ABC - from ytdl_subscribe.downloaders.youtube_downloader import YoutubeDownloader from ytdl_subscribe.subscriptions.subscription import Subscription from ytdl_subscribe.validators.config.source_options.youtube_validators import ( @@ -10,28 +8,11 @@ from ytdl_subscribe.validators.config.source_options.youtube_validators import ( ) -class YoutubeSubscription(Subscription, ABC): - source_validator_type = YoutubeSourceValidator - downloader_type = YoutubeDownloader - - @property - def source_options(self) -> YoutubeSourceValidator: - return super().source_options - - @property - def downloader(self) -> YoutubeDownloader: - return super().downloader - - -class YoutubePlaylistSubscription(YoutubeSubscription): - download_strategy_type = YoutubePlaylistDownloadValidator - - @property - def download_strategy_options(self) -> YoutubePlaylistDownloadValidator: - return super().download_strategy_options - +class YoutubePlaylistSubscription( + Subscription[YoutubeSourceValidator, YoutubePlaylistDownloadValidator] +): def extract_info(self): - entries = self.downloader.download_playlist( + entries = self.get_downloader(YoutubeDownloader).download_playlist( playlist_id=self.download_strategy_options.playlist_id.value )