From 6f41b30ddb5cf19e5389a1724e48a0a173af4d1a Mon Sep 17 00:00:00 2001 From: Jesse Bannon Date: Wed, 30 Mar 2022 07:56:19 +0000 Subject: [PATCH] untested youtube entry --- ytdl_subscribe/entries/entry.py | 25 +++++++++++++++++++- ytdl_subscribe/entries/soundcloud.py | 20 ---------------- ytdl_subscribe/entries/youtube.py | 11 +++++++++ ytdl_subscribe/subscriptions/soundcloud.py | 2 +- ytdl_subscribe/subscriptions/subscription.py | 8 +++---- ytdl_subscribe/subscriptions/youtube.py | 18 ++++---------- 6 files changed, 44 insertions(+), 40 deletions(-) create mode 100644 ytdl_subscribe/entries/youtube.py diff --git a/ytdl_subscribe/entries/entry.py b/ytdl_subscribe/entries/entry.py index aab67d3d..3537be85 100644 --- a/ytdl_subscribe/entries/entry.py +++ b/ytdl_subscribe/entries/entry.py @@ -12,8 +12,11 @@ class Entry(object): def __init__(self, **kwargs): self._kwargs = kwargs + def kwargs_contains(self, key): + return key in self._kwargs + def kwargs(self, key) -> Any: - if key not in self._kwargs: + if not self.kwargs_contains(key): raise KeyError( f"Expected '{key}' in {self.__class__.__name__} but does not exist." ) @@ -35,6 +38,22 @@ class Entry(object): def ext(self) -> str: return self.kwargs("ext") + @property + def upload_date(self) -> str: + return self.kwargs("upload_date") + + @property + def upload_year(self) -> int: + return int(self.upload_date[:4]) + + @property + def thumbnail(self) -> str: + return self.kwargs("thumbnail") + + @property + def thumbnail_ext(self) -> str: + return self.thumbnail.split(".")[-1] + @property def download_file_name(self) -> str: return f"{self.uid}.{self.ext}" @@ -48,6 +67,10 @@ class Entry(object): "title": self.title, "sanitized_title": self.sanitized_title, "ext": self.ext, + "upload_date": self.upload_date, + "upload_year": self.upload_year, + "thumbnail": self.thumbnail, + "thumbnail_ext": self.thumbnail_ext, } def apply_formatter(self, format_string: str, overrides: Optional[Dict]) -> str: diff --git a/ytdl_subscribe/entries/soundcloud.py b/ytdl_subscribe/entries/soundcloud.py index 001005ef..a2fe9503 100644 --- a/ytdl_subscribe/entries/soundcloud.py +++ b/ytdl_subscribe/entries/soundcloud.py @@ -6,22 +6,6 @@ from ytdl_subscribe.entries.entry import Entry class SoundcloudTrack(Entry): - @property - def upload_date(self) -> str: - return self.kwargs("upload_date") - - @property - def upload_year(self) -> int: - return int(self.upload_date[:4]) - - @property - def thumbnail(self) -> str: - return self.kwargs("thumbnail") - - @property - def thumbnail_ext(self) -> str: - return self.thumbnail.split(".")[-1] - @property def track_number(self) -> int: return 1 @@ -50,10 +34,6 @@ class SoundcloudTrack(Entry): return dict( super(SoundcloudTrack, self).to_dict(), **{ - "upload_date": self.upload_date, - "upload_year": self.upload_year, - "thumbnail": self.thumbnail, - "thumbnail_ext": self.thumbnail_ext, "track_number": self.track_number, "track_number_padded": self.track_number_padded, "album": self.album, diff --git a/ytdl_subscribe/entries/youtube.py b/ytdl_subscribe/entries/youtube.py new file mode 100644 index 00000000..cfe4f92f --- /dev/null +++ b/ytdl_subscribe/entries/youtube.py @@ -0,0 +1,11 @@ +from ytdl_subscribe.entries.entry import Entry + + +class YoutubeVideo(Entry): + @property + def title(self) -> str: + # Try to get the track, fall back on title + if self.kwargs_contains('track'): + return self.kwargs('track') + + return super(YoutubeVideo, self).title diff --git a/ytdl_subscribe/subscriptions/soundcloud.py b/ytdl_subscribe/subscriptions/soundcloud.py index 8e9ab9c5..9a89da64 100644 --- a/ytdl_subscribe/subscriptions/soundcloud.py +++ b/ytdl_subscribe/subscriptions/soundcloud.py @@ -12,7 +12,7 @@ class SoundcloudSubscription(Subscription): def extract_info(self): base_url = f"https://soundcloud.com/{self.options['username']}" - tracks: List[Type[SoundcloudTrack]] = [] + tracks: List[SoundcloudTrack] = [] if self.options.get("download_strategy") == "albums_then_tracks": # Get the album info first. This tells us which track ids belong diff --git a/ytdl_subscribe/subscriptions/subscription.py b/ytdl_subscribe/subscriptions/subscription.py index c7fdc5fc..925efe80 100644 --- a/ytdl_subscribe/subscriptions/subscription.py +++ b/ytdl_subscribe/subscriptions/subscription.py @@ -51,7 +51,7 @@ class Subscription(object): self.ytdl_opts["writethumbnail"] = True def format_filepath( - self, filepath_formatter: str, entry: Type[Entry], makedirs=False + self, filepath_formatter: str, entry: Entry, makedirs=False ): """ Convert a filepath value in the config to an actual filepath. @@ -60,7 +60,7 @@ class Subscription(object): ---------- filepath_formatter: str File path relative to the specified output path - entry: Type[Entry] + entry: Entry Entry used to populate any format variables in the filepath makedirs: bool Whether to create all directories in the final filepath. @@ -77,7 +77,7 @@ class Subscription(object): return output_file_path - def _post_process_tagging(self, entry: Type[Entry]): + def _post_process_tagging(self, entry: Entry): t = music_tag.load_file( entry.file_path(relative_directory=self.WORKING_DIRECTORY) ) @@ -108,7 +108,7 @@ class Subscription(object): """ raise NotImplemented("Each source needs to implement how it extracts info") - def post_process_entry(self, entry: Type[Entry]): + def post_process_entry(self, entry: Entry): if "tagging" in self.post_process: self._post_process_tagging(entry) diff --git a/ytdl_subscribe/subscriptions/youtube.py b/ytdl_subscribe/subscriptions/youtube.py index c3437351..dfbe6f3a 100644 --- a/ytdl_subscribe/subscriptions/youtube.py +++ b/ytdl_subscribe/subscriptions/youtube.py @@ -1,26 +1,17 @@ import json import os +from typing import List import yt_dlp as ytdl -from sanitize_filename import sanitize from ytdl_subscribe import SubscriptionSource +from ytdl_subscribe.entries.youtube import YoutubeVideo from ytdl_subscribe.subscriptions.subscription import Subscription class YoutubeSubscription(Subscription): source = SubscriptionSource.YOUTUBE - def parse_entry(self, entry): - entry = super(YoutubeSubscription, self).parse_entry(entry) - entry["upload_year"] = entry["upload_date"][:4] - - entry["thumbnail_ext"] = entry["thumbnail"].split(".")[-1] - - # Try to get the track, fall back on title - entry["sanitized_track"] = sanitize(entry.get("track", entry["title"])) - return entry - def extract_info(self): playlist_id = self.options["playlist_id"] url = f"https://youtube.com/playlist?list={playlist_id}" @@ -36,14 +27,13 @@ class YoutubeSubscription(Subscription): _ = ytd.extract_info(url) # Load the entries from info.json, ignore the playlist entry - entries = [] + entries: List[YoutubeVideo] = [] for file_name in os.listdir(self.WORKING_DIRECTORY): if file_name.endswith(".info.json") and not file_name.startswith( playlist_id ): with open(self.WORKING_DIRECTORY + "/" + file_name, "r") as f: - entries.append(json.load(f)) + entries.append(YoutubeVideo(**json.load(f))) - entries = [self.parse_entry(e) for e in entries] for e in entries: self.post_process_entry(e)