untested youtube entry
This commit is contained in:
parent
6662bc5112
commit
6f41b30ddb
6 changed files with 44 additions and 40 deletions
|
|
@ -12,8 +12,11 @@ class Entry(object):
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
self._kwargs = kwargs
|
self._kwargs = kwargs
|
||||||
|
|
||||||
|
def kwargs_contains(self, key):
|
||||||
|
return key in self._kwargs
|
||||||
|
|
||||||
def kwargs(self, key) -> Any:
|
def kwargs(self, key) -> Any:
|
||||||
if key not in self._kwargs:
|
if not self.kwargs_contains(key):
|
||||||
raise KeyError(
|
raise KeyError(
|
||||||
f"Expected '{key}' in {self.__class__.__name__} but does not exist."
|
f"Expected '{key}' in {self.__class__.__name__} but does not exist."
|
||||||
)
|
)
|
||||||
|
|
@ -35,6 +38,22 @@ class Entry(object):
|
||||||
def ext(self) -> str:
|
def ext(self) -> str:
|
||||||
return self.kwargs("ext")
|
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
|
@property
|
||||||
def download_file_name(self) -> str:
|
def download_file_name(self) -> str:
|
||||||
return f"{self.uid}.{self.ext}"
|
return f"{self.uid}.{self.ext}"
|
||||||
|
|
@ -48,6 +67,10 @@ class Entry(object):
|
||||||
"title": self.title,
|
"title": self.title,
|
||||||
"sanitized_title": self.sanitized_title,
|
"sanitized_title": self.sanitized_title,
|
||||||
"ext": self.ext,
|
"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:
|
def apply_formatter(self, format_string: str, overrides: Optional[Dict]) -> str:
|
||||||
|
|
|
||||||
|
|
@ -6,22 +6,6 @@ from ytdl_subscribe.entries.entry import Entry
|
||||||
|
|
||||||
|
|
||||||
class SoundcloudTrack(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
|
@property
|
||||||
def track_number(self) -> int:
|
def track_number(self) -> int:
|
||||||
return 1
|
return 1
|
||||||
|
|
@ -50,10 +34,6 @@ class SoundcloudTrack(Entry):
|
||||||
return dict(
|
return dict(
|
||||||
super(SoundcloudTrack, self).to_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": self.track_number,
|
||||||
"track_number_padded": self.track_number_padded,
|
"track_number_padded": self.track_number_padded,
|
||||||
"album": self.album,
|
"album": self.album,
|
||||||
|
|
|
||||||
11
ytdl_subscribe/entries/youtube.py
Normal file
11
ytdl_subscribe/entries/youtube.py
Normal file
|
|
@ -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
|
||||||
|
|
@ -12,7 +12,7 @@ class SoundcloudSubscription(Subscription):
|
||||||
|
|
||||||
def extract_info(self):
|
def extract_info(self):
|
||||||
base_url = f"https://soundcloud.com/{self.options['username']}"
|
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":
|
if self.options.get("download_strategy") == "albums_then_tracks":
|
||||||
# Get the album info first. This tells us which track ids belong
|
# Get the album info first. This tells us which track ids belong
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ class Subscription(object):
|
||||||
self.ytdl_opts["writethumbnail"] = True
|
self.ytdl_opts["writethumbnail"] = True
|
||||||
|
|
||||||
def format_filepath(
|
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.
|
Convert a filepath value in the config to an actual filepath.
|
||||||
|
|
@ -60,7 +60,7 @@ class Subscription(object):
|
||||||
----------
|
----------
|
||||||
filepath_formatter: str
|
filepath_formatter: str
|
||||||
File path relative to the specified output path
|
File path relative to the specified output path
|
||||||
entry: Type[Entry]
|
entry: Entry
|
||||||
Entry used to populate any format variables in the filepath
|
Entry used to populate any format variables in the filepath
|
||||||
makedirs: bool
|
makedirs: bool
|
||||||
Whether to create all directories in the final filepath.
|
Whether to create all directories in the final filepath.
|
||||||
|
|
@ -77,7 +77,7 @@ class Subscription(object):
|
||||||
|
|
||||||
return output_file_path
|
return output_file_path
|
||||||
|
|
||||||
def _post_process_tagging(self, entry: Type[Entry]):
|
def _post_process_tagging(self, entry: Entry):
|
||||||
t = music_tag.load_file(
|
t = music_tag.load_file(
|
||||||
entry.file_path(relative_directory=self.WORKING_DIRECTORY)
|
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")
|
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:
|
if "tagging" in self.post_process:
|
||||||
self._post_process_tagging(entry)
|
self._post_process_tagging(entry)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,17 @@
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
from typing import List
|
||||||
|
|
||||||
import yt_dlp as ytdl
|
import yt_dlp as ytdl
|
||||||
from sanitize_filename import sanitize
|
|
||||||
|
|
||||||
from ytdl_subscribe import SubscriptionSource
|
from ytdl_subscribe import SubscriptionSource
|
||||||
|
from ytdl_subscribe.entries.youtube import YoutubeVideo
|
||||||
from ytdl_subscribe.subscriptions.subscription import Subscription
|
from ytdl_subscribe.subscriptions.subscription import Subscription
|
||||||
|
|
||||||
|
|
||||||
class YoutubeSubscription(Subscription):
|
class YoutubeSubscription(Subscription):
|
||||||
source = SubscriptionSource.YOUTUBE
|
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):
|
def extract_info(self):
|
||||||
playlist_id = self.options["playlist_id"]
|
playlist_id = self.options["playlist_id"]
|
||||||
url = f"https://youtube.com/playlist?list={playlist_id}"
|
url = f"https://youtube.com/playlist?list={playlist_id}"
|
||||||
|
|
@ -36,14 +27,13 @@ class YoutubeSubscription(Subscription):
|
||||||
_ = ytd.extract_info(url)
|
_ = ytd.extract_info(url)
|
||||||
|
|
||||||
# Load the entries from info.json, ignore the playlist entry
|
# Load the entries from info.json, ignore the playlist entry
|
||||||
entries = []
|
entries: List[YoutubeVideo] = []
|
||||||
for file_name in os.listdir(self.WORKING_DIRECTORY):
|
for file_name in os.listdir(self.WORKING_DIRECTORY):
|
||||||
if file_name.endswith(".info.json") and not file_name.startswith(
|
if file_name.endswith(".info.json") and not file_name.startswith(
|
||||||
playlist_id
|
playlist_id
|
||||||
):
|
):
|
||||||
with open(self.WORKING_DIRECTORY + "/" + file_name, "r") as f:
|
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:
|
for e in entries:
|
||||||
self.post_process_entry(e)
|
self.post_process_entry(e)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue