Fix validators and output directory

This commit is contained in:
jbannon 2022-04-04 23:03:24 +00:00
parent 3a22a9bf10
commit 374021d027
8 changed files with 61 additions and 50 deletions

View file

@ -8,17 +8,21 @@ presets:
skip_premiere_tracks: True skip_premiere_tracks: True
ytdl_options: ytdl_options:
format: 'bestaudio[ext=mp3]' format: 'bestaudio[ext=mp3]'
post_process: output_options:
file_name: "[{album_year}] {sanitized_album}/{track_number_padded} - {sanitized_title}.{ext}" file_name: "[{album_year}] {sanitized_album}/{track_number_padded} - {sanitized_title}.{ext}"
thumbnail_name: "[{album_year}] {sanitized_album}/folder.{thumbnail_ext}" convert_thumbnail: "jpeg"
tagging: thumbnail_name: "[{album_year}] {sanitized_album}/folder.jpeg"
artist: "{artist}" metadata_options:
albumartist: "{artist}" id3:
title: "{title}" id3_version: "2.4"
album: "{album}" tags:
tracknumber: "{track_number}" artist: "{artist}"
year: "{album_year}" albumartist: "{artist}"
genre: "{genre}" title: "{title}"
album: "{album}"
tracknumber: "{track_number}"
year: "{album_year}"
genre: "{genre}"
music_videos: music_videos:
youtube: youtube:
@ -26,14 +30,16 @@ presets:
ytdl_options: ytdl_options:
format: 'best' format: 'best'
ignoreerrors: True ignoreerrors: True
post_process: output_options:
file_name: "{sanitized_artist} - {sanitized_title}.{ext}" file_name: "{sanitized_artist} - {sanitized_title}.{ext}"
convert_thumbnail: "jpg" convert_thumbnail: "jpeg"
thumbnail_name: "{sanitized_artist} - {sanitized_title}.jpg" thumbnail_name: "{sanitized_artist} - {sanitized_title}.jpeg"
nfo_name: "{sanitized_artist} - {sanitized_title}.nfo" metadata_options:
nfo_root: "musicvideo"
nfo: nfo:
artist: "{artist}" nfo_name: "{sanitized_artist} - {sanitized_title}.nfo"
title: "{title}" nfo_root: "musicvideo"
album: "Music Videos" tags:
year: "{upload_year}" artist: "{artist}"
title: "{title}"
album: "Music Videos"
year: "{upload_year}"

View file

@ -2,7 +2,8 @@ ALISON:
preset: "soundcloud_with_id3_tags" preset: "soundcloud_with_id3_tags"
soundcloud: soundcloud:
username: alis_on username: alis_on
output_path: "/mnt/nas/Downloads/ytdl/music/ALISON" output_options:
output_directory: "/tmp/ALISON"
overrides: overrides:
artist: "A.L.I.S.O.N." artist: "A.L.I.S.O.N."
genre: "Synthwave / Electronic" genre: "Synthwave / Electronic"
@ -11,7 +12,8 @@ delorra:
preset: "soundcloud_with_id3_tags" preset: "soundcloud_with_id3_tags"
soundcloud: soundcloud:
username: delorra username: delorra
output_path: "/mnt/nas/Downloads/ytdl/music/DeLorra" output_options:
output_directory: "/tmp/DeLorra"
overrides: overrides:
artist: "DeLorra" artist: "DeLorra"
genre: "Synthwave / Electronic" genre: "Synthwave / Electronic"
@ -20,23 +22,26 @@ bl00dwave:
preset: "soundcloud_with_id3_tags" preset: "soundcloud_with_id3_tags"
soundcloud: soundcloud:
username: bl00dwave username: bl00dwave
output_path: "/tmp/bl00dwave" output_options:
output_directory: "/tmp/bl00dwave"
overrides: overrides:
artist: "bl00dwave" artist: "bl00dwave"
genre: "Synthwave / Electronic" genre: "Synthwave / Electronic"
tom_petty: tom_petty:
preset: "music_videos"
youtube: youtube:
playlist_id: PLoopXDarluPBnuxs4PTC55Sc_2ShAXC0i playlist_id: PLoopXDarluPBnuxs4PTC55Sc_2ShAXC0i
preset: "music_videos" output_options:
output_path: "/tmp/Tom Petty" output_directory: "/tmp/Tom Petty"
overrides: overrides:
artist: "Tom Petty and the Heartbreakers" artist: "Tom Petty and the Heartbreakers"
rammstein: rammstein:
preset: "music_videos"
youtube: youtube:
playlist_id: "PLVTLbc6i-h_iuhdwUfuPDLFLXG2QQnz-x" playlist_id: "PLVTLbc6i-h_iuhdwUfuPDLFLXG2QQnz-x"
preset: "music_videos" output_options:
output_path: "/mnt/nas/Downloads/ytdl/music_videos/Rammstein" output_directory: "/tmp/Rammstein"
overrides: overrides:
artist: "Rammstein" artist: "Rammstein"

View file

@ -1,4 +1,5 @@
import os import os
from pathlib import Path
from shutil import copyfile from shutil import copyfile
from typing import Type from typing import Type
from typing import TypeVar from typing import TypeVar
@ -129,38 +130,44 @@ class Subscription(object):
relative_directory=self.config_options.working_directory.value relative_directory=self.config_options.working_directory.value
) )
entry_destination_file_path = entry.apply_formatter( output_directory = entry.apply_formatter(
format_string=self.output_options.output_directory.format_string,
overrides=self.overrides.dict
)
output_file_name = entry.apply_formatter(
format_string=self.output_options.file_name.format_string, format_string=self.output_options.file_name.format_string,
overrides=self.overrides.dict, overrides=self.overrides.dict,
) )
entry_destination_file_path = Path(output_directory) / Path(output_file_name)
os.makedirs(os.path.dirname(entry_destination_file_path), exist_ok=True) os.makedirs(os.path.dirname(entry_destination_file_path), exist_ok=True)
copyfile(entry_source_file_path, entry_destination_file_path) copyfile(entry_source_file_path, entry_destination_file_path)
# Download the thumbnail if its present # Download the thumbnail if its present
if self.output_options.thumbnail_name: if self.output_options.thumbnail_name:
thumbnail_source_path = entry.thumbnail_path( source_thumbnail_path = entry.thumbnail_path(
relative_directory=self.config_options.working_directory.value relative_directory=self.config_options.working_directory.value
) )
thumbnail_destination_path = entry.apply_formatter( output_thumbnail_name = entry.apply_formatter(
format_string=self.output_options.thumbnail_name.format_string, format_string=self.output_options.thumbnail_name.format_string,
overrides=self.overrides.dict, overrides=self.overrides.dict,
) )
output_thumbnail_path = Path(output_directory) / Path(output_thumbnail_name)
os.makedirs(os.path.dirname(entry_destination_file_path), exist_ok=True) os.makedirs(os.path.dirname(output_thumbnail_path), exist_ok=True)
# If the thumbnail is to be converted, then save the converted thumbnail to the # If the thumbnail is to be converted, then save the converted thumbnail to the
# output filepath # output filepath
if self.output_options.convert_thumbnail: if self.output_options.convert_thumbnail:
im = Image.open(thumbnail_source_path).convert("RGB") im = Image.open(source_thumbnail_path).convert("RGB")
im.save( im.save(
fp=thumbnail_destination_path, fp=output_thumbnail_name,
format=self.output_options.convert_thumbnail.value, format=self.output_options.convert_thumbnail.value,
) )
# Otherwise, just copy the downloaded thumbnail # Otherwise, just copy the downloaded thumbnail
else: else:
copyfile(thumbnail_source_path, thumbnail_destination_path) copyfile(source_thumbnail_path, output_thumbnail_name)
if self.metadata_options.nfo: if self.metadata_options.nfo:
self._post_process_nfo(entry) self._post_process_nfo(entry)

View file

@ -54,8 +54,8 @@ class StringFormatterValidator(StringValidator):
return format_variables return format_variables
def __init__(self, name, format_string: str): def __init__(self, name, value: str):
super().__init__(name=name, value=format_string) super().__init__(name=name, value=value)
self.format_variables = self.__validate_and_get_format_variables() self.format_variables = self.__validate_and_get_format_variables()
@property @property

View file

@ -13,8 +13,8 @@ class StringSelectValidator(StringValidator):
select_values: Set[str] = set() select_values: Set[str] = set()
def __init__(self, name, format_string: str): def __init__(self, name, value: str):
super().__init__(name=name, value=format_string) super().__init__(name=name, value=value)
if self.value not in self.select_values: if self.value not in self.select_values:
raise self._validation_exception( raise self._validation_exception(

View file

@ -16,11 +16,3 @@ class MetadataOptionsValidator(StrictDictValidator):
self.id3 = self.validate_key_if_present(key="id3", validator=Id3Validator) self.id3 = self.validate_key_if_present(key="id3", validator=Id3Validator)
self.nfo = self.validate_key_if_present(key="nfo", validator=NFOValidator) self.nfo = self.validate_key_if_present(key="nfo", validator=NFOValidator)
self.output_directory: StringFormatterValidator = self.validate_key(
key="output_directory", validator=StringFormatterValidator
)
self.file_name: StringFormatterValidator = self.validate_key(
key="file_name", validator=StringFormatterValidator
)

View file

@ -38,7 +38,7 @@ class OverridesValidator(DictFormatterValidator):
def dict(self) -> dict: def dict(self) -> dict:
"""For overrides, create sanitized versions of each entry for convenience""" """For overrides, create sanitized versions of each entry for convenience"""
output_dict = copy.deepcopy(super().dict) output_dict = copy.deepcopy(super().dict)
for key in self.keys: for key in list(output_dict.keys()):
output_dict[f"sanitized_{key}"] = sanitize_filename.sanitize( output_dict[f"sanitized_{key}"] = sanitize_filename.sanitize(
output_dict[key] output_dict[key]
) )
@ -47,8 +47,9 @@ class OverridesValidator(DictFormatterValidator):
class PresetValidator(StrictDictValidator): class PresetValidator(StrictDictValidator):
required_keys = {"output_options, metadata_options"} required_keys = {"output_options"}
optional_keys = { optional_keys = {
"metadata_options",
"ytdl_options", "ytdl_options",
"overrides", "overrides",
*SubscriptionSourceName.all(), *SubscriptionSourceName.all(),

View file

@ -17,7 +17,7 @@ from ytdl_subscribe.validators.config.config_validator import ConfigValidator
from ytdl_subscribe.validators.config.preset_validator import OverridesValidator from ytdl_subscribe.validators.config.preset_validator import OverridesValidator
from ytdl_subscribe.validators.config.preset_validator import PresetValidator from ytdl_subscribe.validators.config.preset_validator import PresetValidator
from ytdl_subscribe.validators.config.sources.soundcloud_validators import ( from ytdl_subscribe.validators.config.sources.soundcloud_validators import (
SoundcloudSourceValidator, SoundcloudSourceValidator, SoundcloudAlbumsAndSinglesDownloadValidator,
) )
from ytdl_subscribe.validators.config.sources.youtube_validators import ( from ytdl_subscribe.validators.config.sources.youtube_validators import (
YoutubePlaylistDownloadValidator, YoutubePlaylistDownloadValidator,
@ -64,14 +64,14 @@ class SubscriptionValidator(StrictDictValidator):
del preset_dict["preset"] del preset_dict["preset"]
self.preset = PresetValidator( self.preset = PresetValidator(
name=self.name, name=f"{self.name}.{preset_name}",
value=preset_dict, value=preset_dict,
) )
def to_subscription(self) -> Subscription: def to_subscription(self) -> Subscription:
if isinstance( if isinstance(
self.preset.subscription_source.download_strategy, self.preset.subscription_source.download_strategy,
SoundcloudAlbumsAndSinglesSubscription, SoundcloudAlbumsAndSinglesDownloadValidator,
): ):
subscription_class = SoundcloudAlbumsAndSinglesSubscription subscription_class = SoundcloudAlbumsAndSinglesSubscription
elif isinstance( elif isinstance(