From 2cd31e5a8a2f056831a833b69a3dcf6e0826b856 Mon Sep 17 00:00:00 2001 From: vitiko98 Date: Wed, 16 Dec 2020 14:21:15 -0400 Subject: [PATCH] New feature and error handling with downloads Playlist m3u for playlist download [Enhancement]. Close #31 Fix #32 Update README.md --- README.md | 5 +++-- qobuz_dl/core.py | 29 ++++++++++++++++++++++------- qobuz_dl/downloader.py | 14 +++++++++++--- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 6ade344..6151b6d 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ Search, discover and download Lossless and Hi-Res music from [Qobuz](https://www * Download music from last.fm playlists (Spotify, Apple Music and Youtube playlists are also supported through this method) * Queue support on **interactive** mode * Support for albums with multiple discs +* Support for M3U playlists * Downloads URLs from text file * And more @@ -67,7 +68,7 @@ qobuz-dl dl https://play.qobuz.com/artist/2528676 --albums-only ``` #### Last.fm playlists -Last.fm has a new feature for creating playlists: you can create your own based on the music you listen to or you can import one from popular streaming services like Spotify, Apple Music and Youtube. Visit: `https://www.last.fm/user//playlists` (e.g. https://www.last.fm/user/vitiko98/playlists) to get started. +> Last.fm has a new feature for creating playlists: you can create your own based on the music you listen to or you can import one from popular streaming services like Spotify, Apple Music and Youtube. Visit: `https://www.last.fm/user//playlists` (e.g. https://www.last.fm/user/vitiko98/playlists) to get started. Download a last.fm playlist in the maximum quality ``` @@ -157,7 +158,7 @@ qobuz.handle_url("https://play.qobuz.com/album/va4j3hdlwaubc") Attributes, methods and parameters have been named as self-explanatory as possible. ## A note about Qo-DL -`qobuz-dl` is inspired in the discontinued Qo-DL-Reborn. This program uses two modules from Qo-DL: `qopy` and `spoofer`, both written by Sorrow446 and DashLt. +`qobuz-dl` is inspired in the discontinued Qo-DL-Reborn. This tool uses two modules from Qo-DL: `qopy` and `spoofer`, both written by Sorrow446 and DashLt. ## Disclaimer * This tool was written for educational purposes. I will not be responsible if you use this program in bad faith. By using it, you are accepting the [Qobuz API Terms of Use](https://static.qobuz.com/apps/api/QobuzAPI-TermsofUse.pdf). * `qobuz-dl` is not affiliated with Qobuz diff --git a/qobuz_dl/core.py b/qobuz_dl/core.py index b68ba60..60f4157 100644 --- a/qobuz_dl/core.py +++ b/qobuz_dl/core.py @@ -53,6 +53,7 @@ class QobuzDL: interactive_limit=20, ignore_singles_eps=False, no_m3u_for_playlists=False, + raise_request_exceptions=False, ): self.directory = self.create_dir(directory) self.quality = quality @@ -353,7 +354,7 @@ class QobuzDL: pl_title = sanitize_filename(soup.select_one("h1").text) pl_directory = os.path.join(self.directory, pl_title) - print("Downloading playlist: " + pl_title) + print("Downloading playlist: {} ({} tracks)".format(pl_title, len(track_list))) for i in track_list: track_id = self.get_id(self.search_by_type(i, "track", 1, lucky=True)[0]) @@ -365,30 +366,44 @@ class QobuzDL: def make_m3u(self, pl_directory): if self.no_m3u_for_playlists: return + track_list = ["#EXTM3U"] - pl_name = os.path.basename(os.path.normpath(pl_directory)) + ".m3u" + rel_folder = os.path.basename(os.path.normpath(pl_directory)) + pl_name = rel_folder + ".m3u" for local, dirs, files in os.walk(pl_directory): dirs.sort() + audio_rel_files = [ + # os.path.abspath(os.path.join(local, file_)) + # os.path.join(rel_folder, os.path.basename(os.path.normpath(local)), file_) + os.path.join(os.path.basename(os.path.normpath(local)), file_) + for file_ in files + if os.path.splitext(file_)[-1] in EXTENSIONS + ] audio_files = [ os.path.abspath(os.path.join(local, file_)) for file_ in files if os.path.splitext(file_)[-1] in EXTENSIONS ] - if not audio_files: + if not audio_files or len(audio_files) != len(audio_rel_files): continue - for audio in audio_files: + + for audio_rel_file, audio_file in zip(audio_rel_files, audio_files): try: - pl_item = EasyMP3(audio) if ".mp3" in audio else FLAC(audio) + pl_item = ( + EasyMP3(audio_file) + if ".mp3" in audio_file + else FLAC(audio_file) + ) title = pl_item["TITLE"][0] artist = pl_item["ARTIST"][0] length = int(pl_item.info.length) index = "#EXTINF:{}, {} - {}\n{}".format( - length, artist, title, audio + length, artist, title, audio_rel_file ) except: # noqa continue track_list.append(index) if len(track_list) > 1: - with open(os.path.join(self.directory, pl_name), "w") as pl: + with open(os.path.join(pl_directory, pl_name), "w") as pl: pl.write("\n\n".join(track_list)) diff --git a/qobuz_dl/downloader.py b/qobuz_dl/downloader.py index f1c09de..5c35782 100644 --- a/qobuz_dl/downloader.py +++ b/qobuz_dl/downloader.py @@ -46,7 +46,7 @@ def get_format(client, item_dict, quality, is_track_id=False): ): return "FLAC" return "Hi-Res" - except KeyError: + except (KeyError, requests.exceptions.HTTPError): return "Unknown" @@ -196,7 +196,11 @@ def download_id_by_type( media_numbers = [track["media_number"] for track in meta["tracks"]["items"]] is_multiple = True if len([*{*media_numbers}]) > 1 else False for i in meta["tracks"]["items"]: - parse = client.get_track_url(i["id"], quality) + try: + parse = client.get_track_url(i["id"], quality) + except requests.exceptions.HTTPError: + print("Nothing found") + continue if "sample" not in parse and parse["sampling_rate"]: is_mp3 = True if int(quality) == 5 else False download_and_tag( @@ -214,7 +218,11 @@ def download_id_by_type( print("Demo. Skipping") count = count + 1 else: - parse = client.get_track_url(item_id, quality) + try: + parse = client.get_track_url(item_id, quality) + except requests.exceptions.HTTPError: + print("Nothing found") + return if "sample" not in parse and parse["sampling_rate"]: meta = client.get_track_meta(item_id)