diff --git a/streamrip/constants.py b/streamrip/constants.py index f339d26..7d7735c 100644 --- a/streamrip/constants.py +++ b/streamrip/constants.py @@ -73,6 +73,7 @@ __MP4_KEYS = ( "trkn", "disk", None, + None, ) __MP3_KEYS = ( @@ -95,6 +96,7 @@ __MP3_KEYS = ( id3.TRCK, id3.TPOS, None, + None, ) __METADATA_TYPES = ( @@ -117,6 +119,7 @@ __METADATA_TYPES = ( "tracknumber", "discnumber", "tracktotal", + "disctotal", ) diff --git a/streamrip/downloader.py b/streamrip/downloader.py index 16716d7..7622d57 100644 --- a/streamrip/downloader.py +++ b/streamrip/downloader.py @@ -748,9 +748,10 @@ class Album(Tracklist): "id": resp.get("id"), "title": resp.get("title"), "_artist": resp.get("artist") or resp.get("performer"), - "albumartist": resp.get("artist", {}).get("name"), + "albumartist": safe_get(resp, "artist", "name"), "year": str(resp.get("release_date_original"))[:4], "version": resp.get("version"), + "composer": safe_get(resp, "composer", "name"), "release_type": resp.get("release_type", "album"), "cover_urls": resp.get("image"), "streamable": resp.get("streamable"), @@ -760,6 +761,10 @@ class Album(Tracklist): "bit_depth": resp.get("maximum_bit_depth"), "sampling_rate": sampling_rate, "tracktotal": resp.get("tracks_count"), + "description": resp.get("description"), + "disctotal": max( + track.get("media_number", 1) for track in resp["tracks"]["items"] + ), } elif client.source == "tidal": return { @@ -778,6 +783,7 @@ class Album(Tracklist): "bit_depth": 24 if resp.get("audioQuality") == "HI_RES" else 16, "sampling_rate": 44100, # always 44.1 kHz "tracktotal": resp.get("numberOfTracks"), + "disctotal": 1, } elif client.source == "deezer": if resp.get("release_date", False): @@ -804,6 +810,7 @@ class Album(Tracklist): "bit_depth": 16, "sampling_rate": 44100, "tracktotal": resp.get("track_total") or resp.get("nb_tracks"), + "disctotal": max(track['disk_number'] for track in resp['tracks']), } raise InvalidSourceError(client.source) @@ -907,15 +914,21 @@ class Album(Tracklist): if self.client.source != "deezer" and embed_cover: cover = self.get_cover_obj(cover_path, quality) + download_args = { + 'quality': quality, + 'parent_folder': folder, + 'progress_bar': kwargs.get("progress_bar", True), + 'database': database, + 'track_format': kwargs.get("track_format", TRACK_FORMAT), + } for track in self: logger.debug("Downloading track to %s", folder) - track.download( - quality, - folder, - kwargs.get("progress_bar", True), - database=database, - track_format=kwargs.get("track_format", TRACK_FORMAT), - ) + if self.disctotal > 1: + disc_folder = os.path.join(folder, f"Disc {track.meta.discnumber}") + download_args['parent_folder'] = disc_folder + + track.download(**download_args) + if kwargs.get("tag_tracks", True) and self.client.source != "deezer": track.tag(cover=cover, embed_cover=embed_cover) @@ -923,7 +936,7 @@ class Album(Tracklist): logger.debug(f"Removing cover at {cover_path}") try: os.remove(cover_path) - os.remove(large_cover_path) + os.remove(dl_cover_path) except Exception as e: logger.debug(e) diff --git a/streamrip/metadata.py b/streamrip/metadata.py index ee4780f..27ea068 100644 --- a/streamrip/metadata.py +++ b/streamrip/metadata.py @@ -1,6 +1,8 @@ import json import logging import re +import sys +from pprint import pprint from typing import Generator, Optional, Tuple, Union from .constants import ( @@ -83,7 +85,7 @@ class TrackMetadata: """Parse the metadata from an resp dict returned by the Qobuz API. - :param dict resp: from the Qobuz API + :param dict resp: from API """ if self.__source == "qobuz": self.album = resp.get("title") @@ -93,6 +95,10 @@ class TrackMetadata: self.copyright = resp.get("copyright") self.albumartist = resp.get("artist", {}).get("name") self.label = resp.get("label") + self.description = resp.get("description") + self.disctotal = max( + track.get("media_number", 1) for track in resp["tracks"]["items"] + ) if isinstance(self.label, dict): self.label = self.label.get("name") @@ -114,7 +120,7 @@ class TrackMetadata: self.albumartist = resp.get("artist", {}).get("name") self.label = resp.get("label") elif self.__source == "soundcloud": - raise Exception + raise NotImplementedError else: raise ValueError(self.__source) @@ -336,7 +342,7 @@ class TrackMetadata: if k == "tracknumber": text = f"{self.tracknumber}/{self.tracktotal}" elif k == "discnumber": - text = str(self.discnumber) + text = f"{self.discnumber}/{self.get('disctotal', 1)}" else: text = getattr(self, k) diff --git a/streamrip/utils.py b/streamrip/utils.py index 5a0b886..62099cf 100644 --- a/streamrip/utils.py +++ b/streamrip/utils.py @@ -173,7 +173,7 @@ def init_log( """ if not path: os.makedirs(LOG_DIR, exist_ok=True) - path = os.path.join(LOG_DIR, "qobuz_dl.log") + path = os.path.join(LOG_DIR, "streamrip") logger = logging.getLogger() level = logging.getLevelName(level) @@ -193,8 +193,7 @@ def init_log( logger.addHandler(printable) logger.addHandler(rotable) - logging.getLogger("urllib3").setLevel(logging.WARNING) - logging.getLogger("tidal_api").setLevel(logging.WARNING) + logging.getLogger("urllib3").setLevel(logging.DEBUG) def capitalize(s: str) -> str: