diff --git a/qobuz_dl_rewrite/cli.py b/qobuz_dl_rewrite/cli.py index 70b4b3a..15952e1 100644 --- a/qobuz_dl_rewrite/cli.py +++ b/qobuz_dl_rewrite/cli.py @@ -6,9 +6,9 @@ import os import click from qobuz_dl_rewrite.config import Config +from qobuz_dl_rewrite.constants import CACHE_DIR, CONFIG_DIR from qobuz_dl_rewrite.core import QobuzDL from qobuz_dl_rewrite.utils import init_log -from qobuz_dl_rewrite.constants import CONFIG_DIR, CACHE_DIR logger = logging.getLogger(__name__) diff --git a/qobuz_dl_rewrite/clients.py b/qobuz_dl_rewrite/clients.py index 6f51acf..ac857a7 100644 --- a/qobuz_dl_rewrite/clients.py +++ b/qobuz_dl_rewrite/clients.py @@ -124,7 +124,7 @@ class QobuzClient(ClientInterface): logger.debug("Already logged in") return - if (kwargs.get("app_id") or kwargs.get("secrets")) in (None, ['']): + if (kwargs.get("app_id") or kwargs.get("secrets")) in (None, [""]): logger.info("Fetching tokens from Qobuz") spoofer = Spoofer() kwargs["app_id"] = spoofer.get_app_id() @@ -190,7 +190,6 @@ class QobuzClient(ClientInterface): def get(self, item_id: Union[str, int], media_type: str = "album") -> dict: return self._api_get(media_type, item_id=item_id) - @region.cache_on_arguments(expiration_time=TRACK_CACHE_TIME) def get_file_url(self, item_id, quality=6) -> dict: return self._api_get_file_url(item_id, quality=quality) @@ -314,10 +313,10 @@ class QobuzClient(ClientInterface): if sec is not None: secret = sec - elif hasattr(self, 'sec'): + elif hasattr(self, "sec"): secret = self.sec else: - raise InvalidAppSecretError('Cannot find app secret') + raise InvalidAppSecretError("Cannot find app secret") r_sig = f"trackgetFileUrlformat_id{quality}intentstreamtrack_id{track_id}{unix_ts}{secret}" logger.debug("Raw request signature: %s", r_sig) @@ -459,7 +458,6 @@ class TidalClient(ClientInterface): """ return self._get(meta_id, media_type) - @region.cache_on_arguments(expiration_time=TRACK_CACHE_TIME) def get_file_url(self, meta_id: Union[str, int], quality: int = 6): """ :param meta_id: diff --git a/qobuz_dl_rewrite/converter.py b/qobuz_dl_rewrite/converter.py index 07ad55e..b5b7414 100644 --- a/qobuz_dl_rewrite/converter.py +++ b/qobuz_dl_rewrite/converter.py @@ -107,7 +107,7 @@ class Converter: if self.lossless: if isinstance(self.sampling_rate, int): command.extend(["-ar", str(self.sampling_rate)]) - else: + elif self.sampling_rate is not None: raise TypeError( f"Sampling rate must be int, not {type(self.sampling_rate)}" ) @@ -119,7 +119,7 @@ class Converter: command.extend(["-sample_fmt", "s32"]) else: raise ValueError("Bit depth must be 16, 24, or 32") - else: + elif self.bit_depth is not None: raise TypeError(f"Bit depth must be int, not {type(self.bit_depth)}") command.extend(["-y", self.tempfile]) diff --git a/qobuz_dl_rewrite/core.py b/qobuz_dl_rewrite/core.py index 31270b6..07b9aaf 100644 --- a/qobuz_dl_rewrite/core.py +++ b/qobuz_dl_rewrite/core.py @@ -21,6 +21,7 @@ Media = Union[Album, Playlist, Artist] # type hint # TODO: add support for database + class QobuzDL: def __init__( self, diff --git a/qobuz_dl_rewrite/downloader.py b/qobuz_dl_rewrite/downloader.py index 129970f..8cfcf8e 100644 --- a/qobuz_dl_rewrite/downloader.py +++ b/qobuz_dl_rewrite/downloader.py @@ -1,9 +1,10 @@ -from pprint import pprint +import sys import logging import os import re import shutil from abc import ABC, abstractmethod +from pprint import pprint from tempfile import gettempdir from typing import Any, Callable, Optional, Tuple, Union @@ -218,13 +219,13 @@ class Track: def format_final_path(self) -> str: """Return the final filepath of the downloaded file. - This uses the `_get_formatter` method of TrackMetadata, which returns + This uses the `get_formatter` method of TrackMetadata, which returns a dict with the keys allowed in formatter strings, and their values in the TrackMetadata object. """ - formatter = self.meta._get_formatter() + formatter = self.meta.get_formatter() # filename = sanitize_filepath(self.file_format.format(**formatter)) - filename = clean_format(self.file_format, **formatter) + filename = clean_format(self.file_format, formatter) self.final_path = ( os.path.join(self.folder, filename)[:250].strip() + EXT[self.quality] # file extension dict @@ -375,6 +376,9 @@ class Track: self.container = codec.upper() + print(self.final_path) + print(kwargs.get("sampling_rate")) + print(kwargs.get("remove_source")) engine = CONV_CLASS[codec.upper()]( filename=self.final_path, sampling_rate=kwargs.get("sampling_rate"), @@ -673,7 +677,7 @@ class Album(Tracklist): "tracktotal": resp.get("track_total"), } - raise NotImplementedError(client.source) + raise InvalidSourceError(client.source) def _load_tracks(self): """Given an album metadata dict returned by the API, append all of its @@ -748,15 +752,16 @@ class Album(Tracklist): img = requests.head(cover_url) - if int(img.headers["Content-Length"]) > 5 * 10 ** 6: # 5MB - logger.debug("Requested key (%s) size is too large. Falling back") + if int(img.headers["Content-Length"]) > FLAC_MAX_BLOCKSIZE: # 16.7 MB + logger.info( + f"{cover_key} cover size is too large to " + "embed. Using small cover instead" + ) cover_url = self.cover_urls.get("small") tqdm_download(cover_url, cover_path) - # create a single cover object and use them for all tracks - # TODO: avoid this method if embeded covers are not requested - if self.client.source != "deezer": + if self.client.source != "deezer" and embed_cover: cover = self.get_cover_obj(cover_path, quality) for track in self: @@ -778,15 +783,20 @@ class Album(Tracklist): else: dict_[key] = None + dict_['sampling_rate'] /= 1000 + # 48.0kHz -> 48kHz, 44.1kHz -> 44.1kHz + if dict_['sampling_rate'] % 1 == 0.0: + dict_['sampling_rate'] = int(dict_['sampling_rate']) + return dict_ def _get_formatted_folder(self, parent_folder: str) -> str: if self.bit_depth is not None and self.sampling_rate is not None: - self.container = 'FLAC' - elif self.client.source == 'qobuz': - self.container = 'MP3' - elif self.client.source == 'tidal': - self.container = 'AAC' + self.container = "FLAC" + elif self.client.source == "qobuz": + self.container = "MP3" + elif self.client.source == "tidal": + self.container = "AAC" else: raise Exception(f"{self.bit_depth=}, {self.sampling_rate=}") @@ -1241,11 +1251,11 @@ class Artist(Tracklist): class Label(Artist): def load_meta(self): - assert self.client.source == 'qobuz', 'Label source must be qobuz' + assert self.client.source == "qobuz", "Label source must be qobuz" - resp = self.client.get(self.id, 'label') - self.name = resp['name'] - for album in resp['albums']['items']: + resp = self.client.get(self.id, "label") + self.name = resp["name"] + for album in resp["albums"]["items"]: pprint(album) self.append(Album.from_api(album, client=self.client)) diff --git a/qobuz_dl_rewrite/utils.py b/qobuz_dl_rewrite/utils.py index 431118a..4a87432 100644 --- a/qobuz_dl_rewrite/utils.py +++ b/qobuz_dl_rewrite/utils.py @@ -95,7 +95,7 @@ def clean_format(formatter: str, format_info): clean_dict = dict() for key in fmt_keys: - if isinstance(format_info.get(key), (str, int)): # int for track numbers + if isinstance(format_info.get(key), (str, int, float)): # int for track numbers clean_dict[key] = sanitize_filename(str(format_info[key])) else: clean_dict[key] = "Unknown"