From 13e8b548eaff3c18d55e9bf5e4810be15e90f2a0 Mon Sep 17 00:00:00 2001 From: nathom Date: Mon, 12 Apr 2021 15:27:54 -0700 Subject: [PATCH] Reformat track numbers, make progress bars look better --- streamrip/clients.py | 2 +- streamrip/config.py | 9 ++++----- streamrip/core.py | 1 + streamrip/downloader.py | 24 +++++++++++++++++------- streamrip/metadata.py | 3 +++ streamrip/utils.py | 9 +++++---- 6 files changed, 31 insertions(+), 17 deletions(-) diff --git a/streamrip/clients.py b/streamrip/clients.py index 4f11bbe..6cf05a0 100644 --- a/streamrip/clients.py +++ b/streamrip/clients.py @@ -489,7 +489,7 @@ class TidalClient(ClientInterface): try: manifest = json.loads(base64.b64decode(resp["manifest"]).decode("utf-8")) except KeyError: - raise Exception("You must have a TIDAL Hi-Fi account to download tracks.") + raise Exception(resp['userMessage']) logger.debug(manifest) return { diff --git a/streamrip/config.py b/streamrip/config.py index 462ea05..4d52863 100644 --- a/streamrip/config.py +++ b/streamrip/config.py @@ -27,14 +27,12 @@ class Config: Usage: >>> config = Config('test_config.yaml') + >>> config.defaults['qobuz']['quality'] + 3 If test_config was already initialized with values, this will load them into `config`. Otherwise, a new config file is created with the default values. - - >>> config.update_from_cli(**args) - - This will update the config values based on command line args. """ defaults = { @@ -42,7 +40,7 @@ class Config: "quality": 3, "email": None, "password": None, - "app_id": "", # Avoid NoneType error + "app_id": "", "secrets": [], }, "tidal": { @@ -82,6 +80,7 @@ class Config: }, "metadata": { "set_playlist_to_album": False, + "new_playlist_tracknumbers": True, }, "path_format": {"folder": FOLDER_FORMAT, "track": TRACK_FORMAT}, "check_for_updates": True, diff --git a/streamrip/core.py b/streamrip/core.py index 63d3846..ad93199 100644 --- a/streamrip/core.py +++ b/streamrip/core.py @@ -170,6 +170,7 @@ class MusicDL(list): "concurrent_downloads": self.config.session["concurrent_downloads"][ "enabled" ], + "new_tracknumbers": self.config.session['metadata']['new_playlist_tracknumbers'] } logger.debug("Arguments from config: %s", arguments) diff --git a/streamrip/downloader.py b/streamrip/downloader.py index 4cd9f37..b5c3664 100644 --- a/streamrip/downloader.py +++ b/streamrip/downloader.py @@ -214,7 +214,11 @@ class Track: else: url_id = self.id - dl_info = self.client.get_file_url(url_id, self.quality) + try: + dl_info = self.client.get_file_url(url_id, self.quality) + except Exception as e: + click.secho(f"Unable to download track. {e}", fg='red') + return False self.path = os.path.join(gettempdir(), f"{hash(self.id)}_{self.quality}.tmp") logger.debug("Temporary file path: %s", self.path) @@ -233,10 +237,10 @@ class Track: # --------- Download Track ---------- if self.client.source in ("qobuz", "tidal"): logger.debug("Downloadable URL found: %s", dl_info.get("url")) - tqdm_download(dl_info["url"], self.path) # downloads file + tqdm_download(dl_info["url"], self.path, desc=self._progress_desc) # downloads file elif self.client.source == "deezer": # Deezer - logger.debug("Downloadable URL found: %s", dl_info) + logger.debug("Downloadable URL found: %s", dl_info, desc=self._progress_desc) try: tqdm_download(dl_info, self.path) # downloads file except NonStreamable: @@ -301,7 +305,7 @@ class Track: ] ) elif dl_info["type"] == "original": - tqdm_download(dl_info["url"], self.path) + tqdm_download(dl_info["url"], self.path, desc=self._progress_desc) # if a wav is returned, convert to flac engine = converter.FLAC(self.path) @@ -311,6 +315,10 @@ class Track: self.final_path = self.final_path.replace(".mp3", ".flac") self.quality = 2 + @property + def _progress_desc(self): + return click.style(f"Track {int(self.meta.tracknumber):02}", fg='blue') + def download_cover(self): """Downloads the cover art, if cover_url is given.""" @@ -318,10 +326,10 @@ class Track: self.cover_path = os.path.join(self.folder, f"cover{hash(self.cover_url)}.jpg") logger.debug(f"Downloading cover from {self.cover_url}") - click.secho(f"\nDownloading cover art for {self!s}", fg="blue") + # click.secho(f"\nDownloading cover art for {self!s}", fg="blue") if not os.path.exists(self.cover_path): - tqdm_download(self.cover_url, self.cover_path) + tqdm_download(self.cover_url, self.cover_path, desc=click.style('Cover', fg='cyan')) else: logger.debug("Cover already exists, skipping download") @@ -1244,7 +1252,9 @@ class Playlist(Tracklist): item["albumartist"] = self.creator if kwargs.get("new_tracknumbers", True): - item.meta["tracknumber"] = str(self.__download_index) + item["tracknumber"] = self.__download_index + item['discnumber'] = 1 + self.__download_index += 1 self.downloaded = item.download(**kwargs) diff --git a/streamrip/metadata.py b/streamrip/metadata.py index 339fcfe..9590a82 100644 --- a/streamrip/metadata.py +++ b/streamrip/metadata.py @@ -361,6 +361,9 @@ class TrackMetadata: for k, v in FLAC_KEY.items(): tag = getattr(self, k) if tag: + if k in ('tracknumber', 'discnumber', 'tracktotal', 'disctotal'): + tag = f"{int(tag):02}" + logger.debug("Adding tag %s: %s", v, tag) yield (v, str(tag)) diff --git a/streamrip/utils.py b/streamrip/utils.py index 8bc6fd9..1706990 100644 --- a/streamrip/utils.py +++ b/streamrip/utils.py @@ -97,7 +97,7 @@ def get_quality_id(bit_depth: Optional[int], sampling_rate: Optional[int]): return 4 -def tqdm_download(url: str, filepath: str, params: dict = None): +def tqdm_download(url: str, filepath: str, params: dict = None, desc: str = None): """Downloads a file with a progress bar. :param url: url to direct download @@ -114,12 +114,11 @@ def tqdm_download(url: str, filepath: str, params: dict = None): total = int(r.headers.get("content-length", 0)) logger.debug(f"File size = {total}") if total < 1000 and not url.endswith("jpg") and not url.endswith("png"): - print(url) raise NonStreamable(url) try: with open(filepath, "wb") as file, tqdm( - total=total, unit="iB", unit_scale=True, unit_divisor=1024 + total=total, unit="iB", unit_scale=True, unit_divisor=1024, desc=desc ) as bar: for data in r.iter_content(chunk_size=1024): size = file.write(data) @@ -145,8 +144,10 @@ def clean_format(formatter: str, format_info): clean_dict = dict() for key in fmt_keys: - if isinstance(format_info.get(key), (str, int, float)): # int for track numbers + if isinstance(format_info.get(key), (str, float)): clean_dict[key] = sanitize_filename(str(format_info[key])) + elif isinstance(format_info.get(key), int): # track/discnumber + clean_dict[key] = f"{format_info[key]:02}" else: clean_dict[key] = "Unknown"