ytdl-sub/ytdl_subscribe/validators/config/subscription_validator.py
2022-04-04 23:03:24 +00:00

111 lines
4.1 KiB
Python

from typing import Any
from typing import List
import yaml
from mergedeep import mergedeep
from ytdl_subscribe.subscriptions.soundcloud import (
SoundcloudAlbumsAndSinglesSubscription,
)
from ytdl_subscribe.subscriptions.subscription import Subscription
from ytdl_subscribe.subscriptions.youtube import YoutubeSubscription
from ytdl_subscribe.utils.enums import SubscriptionSourceName
from ytdl_subscribe.validators.base.strict_dict_validator import StrictDictValidator
from ytdl_subscribe.validators.base.validators import DictValidator
from ytdl_subscribe.validators.base.validators import StringValidator
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 PresetValidator
from ytdl_subscribe.validators.config.sources.soundcloud_validators import (
SoundcloudSourceValidator, SoundcloudAlbumsAndSinglesDownloadValidator,
)
from ytdl_subscribe.validators.config.sources.youtube_validators import (
YoutubePlaylistDownloadValidator,
)
class SubscriptionValidator(StrictDictValidator):
"""
A Subscription is a preset but overrides it with specific values
"""
required_keys = {"preset"}
optional_keys = PresetValidator.required_keys.union(PresetValidator.optional_keys)
def __init__(self, config: ConfigValidator, name: str, value: Any):
super().__init__(name, value)
self.config = config
# Ensure the overrides defined here are valid
_ = self.validate_key(
key="overrides",
validator=OverridesValidator,
default={},
)
preset_name = self.validate_key(
key="preset",
validator=StringValidator,
).value
available_presets = self.config.presets.keys
if preset_name not in available_presets:
raise self._validation_exception(
f"'preset '{preset_name}' does not exist in the provided config. "
f"Available presets: {', '.join(available_presets)}"
)
# A little hacky, we will override the preset with the contents of this subscription, then validate it
preset_dict = mergedeep.merge(
self.config.presets.dict[preset_name],
self.dict,
strategy=mergedeep.Strategy.REPLACE,
)
del preset_dict["preset"]
self.preset = PresetValidator(
name=f"{self.name}.{preset_name}",
value=preset_dict,
)
def to_subscription(self) -> Subscription:
if isinstance(
self.preset.subscription_source.download_strategy,
SoundcloudAlbumsAndSinglesDownloadValidator,
):
subscription_class = SoundcloudAlbumsAndSinglesSubscription
elif isinstance(
self.preset.subscription_source.download_strategy,
YoutubePlaylistDownloadValidator,
):
subscription_class = YoutubeSubscription
else:
raise ValueError("subscription source class not found")
return subscription_class(
name=self.name,
config_options=self.config,
source_options=self.preset.subscription_source,
output_options=self.preset.output_options,
metadata_options=self.preset.metadata_options,
ytdl_options=self.preset.ytdl_options,
overrides=self.preset.overrides,
)
@classmethod
def from_file_path(
cls, config: ConfigValidator, subscription_path: str
) -> List["SubscriptionValidator"]:
# TODO: Create separate yaml file loader class
with open(subscription_path, "r", encoding="utf-8") as file:
subscription_dict = yaml.safe_load(file)
subscriptions: List["SubscriptionValidator"] = []
for subscription_key, subscription_object in subscription_dict.items():
subscriptions.append(
SubscriptionValidator(
config=config, name=subscription_key, value=subscription_object
)
)
return subscriptions