kill soundcloud downloader
This commit is contained in:
parent
a6052160bf
commit
a16fca5fde
3 changed files with 34 additions and 103 deletions
|
|
@ -1,65 +0,0 @@
|
||||||
from abc import ABC
|
|
||||||
from typing import Generic
|
|
||||||
from typing import TypeVar
|
|
||||||
|
|
||||||
from ytdl_sub.downloaders.downloader import Downloader
|
|
||||||
from ytdl_sub.downloaders.downloader import DownloaderValidator
|
|
||||||
from ytdl_sub.entries.soundcloud import SoundcloudTrack
|
|
||||||
from ytdl_sub.validators.validators import BoolValidator
|
|
||||||
|
|
||||||
|
|
||||||
class SoundcloudDownloaderOptions(DownloaderValidator, ABC):
|
|
||||||
"""
|
|
||||||
Abstract source validator for all soundcloud sources.
|
|
||||||
"""
|
|
||||||
|
|
||||||
_optional_keys = {"skip_premiere_tracks"}
|
|
||||||
|
|
||||||
def __init__(self, name: str, value: dict):
|
|
||||||
super().__init__(name=name, value=value)
|
|
||||||
self._skip_premiere_tracks = self._validate_key(
|
|
||||||
"skip_premiere_tracks", BoolValidator, default=True
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def skip_premiere_tracks(self) -> bool:
|
|
||||||
"""
|
|
||||||
Optional. True to skip tracks that require purchasing. False otherwise. Defaults to True.
|
|
||||||
"""
|
|
||||||
return self._skip_premiere_tracks.value
|
|
||||||
|
|
||||||
|
|
||||||
SoundcloudDownloaderOptionsT = TypeVar(
|
|
||||||
"SoundcloudDownloaderOptionsT", bound=SoundcloudDownloaderOptions
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class SoundcloudDownloader(
|
|
||||||
Downloader[SoundcloudDownloaderOptionsT, SoundcloudTrack],
|
|
||||||
Generic[SoundcloudDownloaderOptionsT],
|
|
||||||
ABC,
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Class that handles downloading soundcloud entries via ytdl and converting them into
|
|
||||||
SoundcloudTrack / SoundcloudAlbumTrack objects
|
|
||||||
"""
|
|
||||||
|
|
||||||
downloader_entry_type = SoundcloudTrack
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def artist_albums_url(cls, artist_url: str) -> str:
|
|
||||||
"""
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
Full artist album url
|
|
||||||
"""
|
|
||||||
return f"{artist_url}/albums"
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def artist_tracks_url(cls, artist_url: str) -> str:
|
|
||||||
"""
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
Full artist tracks url
|
|
||||||
"""
|
|
||||||
return f"{artist_url}/tracks"
|
|
||||||
|
|
@ -1,15 +1,17 @@
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
|
|
||||||
|
from ytdl_sub.downloaders.downloader import Downloader
|
||||||
|
from ytdl_sub.downloaders.downloader import DownloaderValidator
|
||||||
from ytdl_sub.downloaders.generic.collection import CollectionDownloader
|
from ytdl_sub.downloaders.generic.collection import CollectionDownloader
|
||||||
from ytdl_sub.downloaders.generic.collection import CollectionDownloadOptions
|
from ytdl_sub.downloaders.generic.collection import CollectionDownloadOptions
|
||||||
from ytdl_sub.downloaders.soundcloud.abc import SoundcloudDownloader
|
from ytdl_sub.entries.entry import Entry
|
||||||
from ytdl_sub.downloaders.soundcloud.abc import SoundcloudDownloaderOptions
|
|
||||||
from ytdl_sub.entries.soundcloud import SoundcloudTrack
|
from ytdl_sub.entries.soundcloud import SoundcloudTrack
|
||||||
from ytdl_sub.validators.url_validator import SoundcloudUsernameUrlValidator
|
from ytdl_sub.validators.url_validator import SoundcloudUsernameUrlValidator
|
||||||
|
from ytdl_sub.validators.validators import BoolValidator
|
||||||
|
|
||||||
|
|
||||||
class SoundcloudAlbumsAndSinglesDownloadOptions(SoundcloudDownloaderOptions):
|
class SoundcloudAlbumsAndSinglesDownloadOptions(DownloaderValidator):
|
||||||
"""
|
"""
|
||||||
Downloads a soundcloud user's entire discography. Groups together album tracks and considers
|
Downloads a soundcloud user's entire discography. Groups together album tracks and considers
|
||||||
any track not in an album as a single. Also includes any collaboration tracks.
|
any track not in an album as a single. Also includes any collaboration tracks.
|
||||||
|
|
@ -30,12 +32,16 @@ class SoundcloudAlbumsAndSinglesDownloadOptions(SoundcloudDownloaderOptions):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_required_keys = {"url"}
|
_required_keys = {"url"}
|
||||||
|
_optional_keys = {"skip_premiere_tracks"}
|
||||||
|
|
||||||
def __init__(self, name, value):
|
def __init__(self, name, value):
|
||||||
super().__init__(name, value)
|
super().__init__(name, value)
|
||||||
self._url = self._validate_key(
|
self._url = self._validate_key(
|
||||||
key="url", validator=SoundcloudUsernameUrlValidator
|
key="url", validator=SoundcloudUsernameUrlValidator
|
||||||
).username_url
|
).username_url
|
||||||
|
self._skip_premiere_tracks = self._validate_key(
|
||||||
|
"skip_premiere_tracks", BoolValidator, default=True
|
||||||
|
)
|
||||||
|
|
||||||
self.collection_validator = CollectionDownloadOptions(
|
self.collection_validator = CollectionDownloadOptions(
|
||||||
name=self._name,
|
name=self._name,
|
||||||
|
|
@ -67,6 +73,13 @@ class SoundcloudAlbumsAndSinglesDownloadOptions(SoundcloudDownloaderOptions):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def skip_premiere_tracks(self) -> bool:
|
||||||
|
"""
|
||||||
|
Optional. True to skip tracks that require purchasing. False otherwise. Defaults to True.
|
||||||
|
"""
|
||||||
|
return self._skip_premiere_tracks.value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def url(self) -> str:
|
def url(self) -> str:
|
||||||
"""
|
"""
|
||||||
|
|
@ -76,9 +89,11 @@ class SoundcloudAlbumsAndSinglesDownloadOptions(SoundcloudDownloaderOptions):
|
||||||
|
|
||||||
|
|
||||||
class SoundcloudAlbumsAndSinglesDownloader(
|
class SoundcloudAlbumsAndSinglesDownloader(
|
||||||
SoundcloudDownloader[SoundcloudAlbumsAndSinglesDownloadOptions]
|
Downloader[SoundcloudAlbumsAndSinglesDownloadOptions, SoundcloudTrack]
|
||||||
):
|
):
|
||||||
downloader_options_type = SoundcloudAlbumsAndSinglesDownloadOptions
|
downloader_options_type = SoundcloudAlbumsAndSinglesDownloadOptions
|
||||||
|
downloader_entry_type = SoundcloudTrack
|
||||||
|
|
||||||
supports_subtitles = False
|
supports_subtitles = False
|
||||||
supports_chapters = False
|
supports_chapters = False
|
||||||
|
|
||||||
|
|
@ -100,6 +115,16 @@ class SoundcloudAlbumsAndSinglesDownloader(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _should_skip(self, entry: Entry) -> bool:
|
||||||
|
if not self.download_options.skip_premiere_tracks:
|
||||||
|
return False
|
||||||
|
|
||||||
|
for url in [entry.kwargs_get("url", ""), entry.webpage_url]:
|
||||||
|
if "/preview/" in url:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
def download(self) -> Generator[SoundcloudTrack, None, None]:
|
def download(self) -> Generator[SoundcloudTrack, None, None]:
|
||||||
"""
|
"""
|
||||||
Soundcloud subscription to download albums and tracks as singles.
|
Soundcloud subscription to download albums and tracks as singles.
|
||||||
|
|
@ -112,4 +137,7 @@ class SoundcloudAlbumsAndSinglesDownloader(
|
||||||
)
|
)
|
||||||
|
|
||||||
for entry in downloader.download():
|
for entry in downloader.download():
|
||||||
|
if self._should_skip(entry):
|
||||||
|
continue
|
||||||
|
|
||||||
yield entry
|
yield entry
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
from ytdl_sub.entries.entry import Entry
|
from ytdl_sub.entries.entry import Entry
|
||||||
from ytdl_sub.entries.variables.soundcloud_variables import SoundcloudVariables
|
from ytdl_sub.entries.variables.soundcloud_variables import SoundcloudVariables
|
||||||
|
|
||||||
|
# TODO: Delete since not used
|
||||||
|
|
||||||
|
|
||||||
class SoundcloudTrack(SoundcloudVariables, Entry):
|
class SoundcloudTrack(SoundcloudVariables, Entry):
|
||||||
"""
|
"""
|
||||||
|
|
@ -9,37 +11,3 @@ class SoundcloudTrack(SoundcloudVariables, Entry):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
entry_extractor = "soundcloud"
|
entry_extractor = "soundcloud"
|
||||||
|
|
||||||
def is_premiere(self) -> bool:
|
|
||||||
"""
|
|
||||||
Returns whether the entry is a premier track. Check this by seeing if the track's url is
|
|
||||||
a preview.
|
|
||||||
"""
|
|
||||||
return "/preview/" in self.kwargs("url")
|
|
||||||
|
|
||||||
|
|
||||||
class SoundcloudAlbumTrack(SoundcloudTrack):
|
|
||||||
"""
|
|
||||||
Entry object to represent a Soundcloud track yt-dlp that belongs to an album.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@property
|
|
||||||
def track_number(self) -> int:
|
|
||||||
"""Returns the entry's track number"""
|
|
||||||
return self.kwargs("playlist_index")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def track_count(self) -> int:
|
|
||||||
"""Returns the entry's total tracks in album"""
|
|
||||||
return self.kwargs("playlist_count")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def album(self) -> str:
|
|
||||||
"""Returns the entry's album name, fetched from its internal album"""
|
|
||||||
return self.kwargs("playlist")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def album_year(self) -> int:
|
|
||||||
"""Returns the entry's album year, fetched from its internal album"""
|
|
||||||
# added from parent entry
|
|
||||||
return self._additional_variables["playlist_max_upload_year"]
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue