diff --git a/rip/cli.py b/rip/cli.py index 06e8b5d..4a881dc 100644 --- a/rip/cli.py +++ b/rip/cli.py @@ -169,11 +169,12 @@ class SearchCommand(Command): class DiscoverCommand(Command): """ - Browse and download items in interactive mode (Qobuz only). + Browse and download items in interactive mode (Qobuz and Deezer only). discover - {--s|scrape : Download all of the items in the list} + {--scrape : Download all of the items in the list} {--m|max-items=50 : The number of items to fetch} + {--s|source=qobuz : The source to download from (qobuz or deezer)} {list=ideal-discography : The list to fetch} """ @@ -182,7 +183,7 @@ class DiscoverCommand(Command): "$ rip discover\n\n" "Browse the best-sellers list\n" "$ rip discover best-sellers\n\n" - "Available options for list:\n\n" + "Available options for Qobuz list:\n\n" " • most-streamed\n" " • recent-releases\n" " • best-sellers\n" @@ -197,21 +198,46 @@ class DiscoverCommand(Command): " • universal-classic\n" " • universal-jazz\n" " • universal-jeunesse\n" - " • universal-chanson\n" + " • universal-chanson\n\n" + "Browse the Deezer editorial releases list\n" + "$ rip discover --source deezer\n\n" + "Browse the Deezer charts\n" + "$ rip discover --source deezer charts\n\n" + "Available options for Deezer list:\n\n" + " • releases\n" + " • charts\n" + " • selection\n" ) def handle(self): - from streamrip.constants import QOBUZ_FEATURED_KEYS - - chosen_list = self.argument("list") + source = self.option("source") scrape = self.option("scrape") + chosen_list = self.argument("list") max_items = self.option("max-items") - if chosen_list not in QOBUZ_FEATURED_KEYS: + if source == "qobuz": + from streamrip.constants import QOBUZ_FEATURED_KEYS + + if chosen_list not in QOBUZ_FEATURED_KEYS: + self.line( + f'Error: list "{chosen_list}" not available' + ) + self.line(self.help) + return 1 + elif source == "deezer": + from streamrip.constants import DEEZER_FEATURED_KEYS + + if chosen_list not in DEEZER_FEATURED_KEYS: + self.line( + f'Error: list "{chosen_list}" not available' + ) + self.line(self.help) + return 1 + + else: self.line( - f'Error: list "{chosen_list}" not available' + "Invalid source. Choose either qobuz or deezer" ) - self.line(self.help) return 1 config = Config() @@ -223,12 +249,14 @@ class DiscoverCommand(Command): return 0 if core.interactive_search( - chosen_list, "qobuz", "featured", limit=int(max_items) + chosen_list, source, "featured", limit=int(max_items) ): core.download() else: self.line("No items chosen, exiting.") + return 0 + class LastfmCommand(Command): """ diff --git a/rip/core.py b/rip/core.py index 9bc59d9..c998412 100644 --- a/rip/core.py +++ b/rip/core.py @@ -654,6 +654,8 @@ class RipCore(list): client = self.get_client(source) results = client.search(query, media_type) + if media_type == "featured": + media_type = "album" if isinstance(results, Generator): # QobuzClient for page in results: @@ -670,11 +672,11 @@ class RipCore(list): if i >= limit - 1: return else: - logger.debug("Not generator") items = ( results.get("data") or results.get("items") or results.get("collection") + or results.get("albums", {}).get("data", False) ) if items is None: raise NoResultsFound(query) diff --git a/streamrip/clients.py b/streamrip/clients.py index ab9869e..1637fc3 100644 --- a/streamrip/clients.py +++ b/streamrip/clients.py @@ -499,7 +499,19 @@ class DeezerClient(Client): """ # TODO: use limit parameter try: - search_function = getattr(self.client.api, f"search_{media_type}") + if media_type == "featured": + if query: + print(query) + search_function = getattr( + self.client.api, f"get_editorial_{query}" + ) + else: + search_function = self.client.api.get_editorial_releases + + else: + search_function = getattr( + self.client.api, f"search_{media_type}" + ) except AttributeError: raise Exception diff --git a/streamrip/constants.py b/streamrip/constants.py index fb10724..ee00ed8 100644 --- a/streamrip/constants.py +++ b/streamrip/constants.py @@ -152,6 +152,7 @@ TIDAL_Q_MAP = { } DEEZER_MAX_Q = 6 +DEEZER_FEATURED_KEYS = {"releases", "charts", "selection"} AVAILABLE_QUALITY_IDS = (0, 1, 2, 3, 4) DEEZER_FORMATS = { "AAC_64", diff --git a/streamrip/media.py b/streamrip/media.py index fd09e03..b73b673 100644 --- a/streamrip/media.py +++ b/streamrip/media.py @@ -303,9 +303,11 @@ class Track(Media): url_id = self.id try: + print(url_id) + print(self.quality) dl_info = self.client.get_file_url(url_id, self.quality) except Exception as e: - # raise NonStreamable(repr(e)) + logger.debug(repr(e)) raise NonStreamable(e) if self.client.source == "qobuz": diff --git a/streamrip/utils.py b/streamrip/utils.py index 0b71b23..050d71b 100644 --- a/streamrip/utils.py +++ b/streamrip/utils.py @@ -103,12 +103,17 @@ class DownloadStream: assert isinstance(self.id, str), self.id blowfish_key = self._generate_blowfish_key(self.id) - decryptor = self._create_deezer_decryptor(blowfish_key) + # decryptor = self._create_deezer_decryptor(blowfish_key) + CHUNK_SIZE = 2048 * 3 return ( - (decryptor.decrypt(chunk[:2048]) + chunk[2048:]) - # (self._decrypt_chunk(blowfish_key, chunk[:2048]) + chunk[2048:]) - if len(chunk) >= 2048 else chunk - for chunk in self.request.iter_content(2048 * 3) + # (decryptor.decrypt(chunk[:2048]) + chunk[2048:]) + ( + self._decrypt_chunk(blowfish_key, chunk[:2048]) + + chunk[2048:] + ) + if len(chunk) >= 2048 + else chunk + for chunk in self.request.iter_content(CHUNK_SIZE) ) return self.request.iter_content(chunk_size=1024) @@ -155,6 +160,7 @@ class DownloadStream: return Blowfish.new( key, Blowfish.MODE_CBC, + b"\x00\x01\x02\x03\x04\x05\x06\x07", ).decrypt(data)