import os import tempfile from types import SimpleNamespace from pathlib import Path import yaml from appdirs import AppDirs from requests.utils import CaseInsensitiveDict from vinetrimmer.objects.vaults import Vault from vinetrimmer.utils.collections import merge_dict class Config: @staticmethod def load_vault(vault): return Vault(**{ "type_" if k == "type" else k: v for k, v in vault.items() }) class Directories: def __init__(self): self.app_dirs = AppDirs("vinetrimmer", False) self.package_root = Path(__file__).resolve().parent.parent self.configuration = self.package_root / "config" self.user_configs = self.package_root self.service_configs = self.user_configs / "Services" self.data = self.package_root self.downloads = Path(__file__).resolve().parents[2] / "Downloads" self.temp = Path(__file__).resolve().parents[2] / "Temp" self.cache = self.package_root / "Cache" self.cookies = self.data / "Cookies" self.logs = self.package_root / "Logs" self.devices = self.data / "devices" class Filenames: def __init__(self): self.log = os.path.join(directories.logs, "vinetrimmer_{time}.log") self.root_config = os.path.join(directories.configuration, "vinetrimmer.yml") self.user_root_config = os.path.join(directories.user_configs, "vinetrimmer.yml") self.service_config = os.path.join(directories.configuration, "services", "{service}.yml") self.user_service_config = os.path.join(directories.service_configs, "{service}.yml") self.subtitles = os.path.join(directories.temp, "TextTrack_{id}_{language_code}.srt") self.chapters = os.path.join(directories.temp, "{filename}_chapters.txt") directories = Directories() filenames = Filenames() with open(filenames.root_config) as fd: config = yaml.safe_load(fd) with open(filenames.user_root_config) as fd: user_config = yaml.safe_load(fd) merge_dict(config, user_config) config = SimpleNamespace(**config) credentials = config.credentials # This serves two purposes: # - Allow `range` to be used in the arguments section in the config rather than just `range_` # - Allow sections like [arguments.Amazon] to work even if an alias (e.g. AMZN or amzn) is used. # CaseInsensitiveDict is used for `arguments` above to achieve case insensitivity. # NOTE: The import cannot be moved to the top of the file, it will cause a circular import error. from vinetrimmer.services import SERVICE_MAP # noqa: E402 if "range_" not in config.arguments: config.arguments["range_"] = config.arguments.get("range_") for service, aliases in SERVICE_MAP.items(): for alias in aliases: config.arguments[alias] = config.arguments.get(service) config.arguments = CaseInsensitiveDict(config.arguments)