From 26da00f1a27576ffb6169908eaa7cf334410a93f Mon Sep 17 00:00:00 2001 From: Nathan Thomas Date: Tue, 14 Jun 2022 12:35:08 -0700 Subject: [PATCH 1/6] Add option to not truncate filname #340 --- rip/config.toml | 5 ++++- rip/core.py | 1 + streamrip/media.py | 12 ++++++++---- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/rip/config.toml b/rip/config.toml index 8f37bf0..7549e7b 100644 --- a/rip/config.toml +++ b/rip/config.toml @@ -153,6 +153,9 @@ folder_format = "{albumartist} - {title} ({year}) [{container}] [{bit_depth}B-{s track_format = "{tracknumber}. {artist} - {title}{explicit}" # Only allow printable ASCII characters in filenames. restrict_characters = false +# Truncate the filename if it is greater than 120 characters +# Setting this to false may cause downloads to fail on some systems +truncate = true # Last.fm playlists are downloaded by searching for the titles of the tracks @@ -169,4 +172,4 @@ progress_bar = "dainty" [misc] # Metadata to identify this config file. Do not change. -version = "1.9.2" +version = "1.9.6" diff --git a/rip/core.py b/rip/core.py index dd33652..3f075a8 100644 --- a/rip/core.py +++ b/rip/core.py @@ -216,6 +216,7 @@ class RipCore(list): concurrency = session["downloads"]["concurrency"] return { "restrict_filenames": filepaths["restrict_characters"], + "truncate_filenames": filepaths["truncate"], "parent_folder": session["downloads"]["folder"], "folder_format": filepaths["folder_format"], "track_format": filepaths["track_format"], diff --git a/streamrip/media.py b/streamrip/media.py index afff293..f9eba6a 100644 --- a/streamrip/media.py +++ b/streamrip/media.py @@ -1516,7 +1516,9 @@ class Album(Tracklist, Media): parent_folder = kwargs.get("parent_folder", "StreamripDownloads") if self.folder_format: self.folder = self._get_formatted_folder( - parent_folder, restrict=kwargs.get("restrict_filenames", False) + parent_folder, + restrict=kwargs.get("restrict_filenames", False), + truncate=kwargs.get("truncate_filenames", True), ) else: self.folder = parent_folder @@ -1660,7 +1662,9 @@ class Album(Tracklist, Media): logger.debug("Formatter: %s", fmt) return fmt - def _get_formatted_folder(self, parent_folder: str, restrict: bool = False) -> str: + def _get_formatted_folder( + self, parent_folder: str, restrict: bool = False, truncate: bool = True + ) -> str: """Generate the folder name for this album. :param parent_folder: @@ -1675,8 +1679,8 @@ class Album(Tracklist, Media): self._get_formatter(), restrict=restrict, ) - if len(formatted_folder) > 120: - formatted_folder = f"{formatted_folder[:120]}..." + if truncate and len(formatted_folder) > 120: + formatted_folder = formatted_folder[:120] return os.path.join(parent_folder, formatted_folder) From 15c826d03e25a34ef10511fc10fac0afb36c547b Mon Sep 17 00:00:00 2001 From: Nathan Thomas Date: Tue, 14 Jun 2022 12:35:55 -0700 Subject: [PATCH 2/6] Improve version comparison --- pyproject.toml | 2 +- rip/cli.py | 13 +++++++++++-- streamrip/__init__.py | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index a3fd028..dbc30f8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "streamrip" -version = "1.9.4" +version = "1.9.6" description = "A fast, all-in-one music ripper for Qobuz, Deezer, Tidal, and SoundCloud" authors = ["nathom "] license = "GPL-3.0-only" diff --git a/rip/cli.py b/rip/cli.py index fe2154c..845c4d2 100644 --- a/rip/cli.py +++ b/rip/cli.py @@ -20,7 +20,7 @@ logging.basicConfig(level="WARNING") logger = logging.getLogger("streamrip") outdated = False -newest_version = __version__ +newest_version: Optional[str] = None class DownloadCommand(Command): @@ -126,6 +126,7 @@ class DownloadCommand(Command): self.line("Must pass arguments. See rip url -h.") update_check.join() + if outdated: import re import subprocess @@ -814,7 +815,15 @@ def is_outdated(): global newest_version r = requests.get("https://pypi.org/pypi/streamrip/json").json() newest_version = r["info"]["version"] - outdated = newest_version != __version__ + + # Compare versions + curr_version_parsed = map(int, __version__.split(".")) + newest_version_parsed = map(int, newest_version.split(".")) + outdated = False + for c, n in zip(curr_version_parsed, newest_version_parsed): + outdated = c < n + if c != n: + break def main(): diff --git a/streamrip/__init__.py b/streamrip/__init__.py index 832f100..0d23a03 100644 --- a/streamrip/__init__.py +++ b/streamrip/__init__.py @@ -1,5 +1,5 @@ """streamrip: the all in one music downloader.""" -__version__ = "1.9.4" +__version__ = "1.9.6" from . import clients, constants, converter, downloadtools, media From f31c40353cc3470bf550879e37d90e3b265237b7 Mon Sep 17 00:00:00 2001 From: Nathan Thomas Date: Mon, 20 Jun 2022 10:28:57 -0700 Subject: [PATCH 3/6] Handle missing TIDAL cover #341 --- streamrip/media.py | 12 ++++++------ streamrip/utils.py | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/streamrip/media.py b/streamrip/media.py index f9eba6a..9db8c35 100644 --- a/streamrip/media.py +++ b/streamrip/media.py @@ -1844,13 +1844,13 @@ class Playlist(Tracklist, Media): self.append(Track(self.client, id=track["id"])) else: for track in tracklist: - # TODO: This should be managed with .m3u files and alike. Arbitrary - # tracknumber tags might cause conflicts if the playlist files are - # inside of a library folder meta = TrackMetadata(track=track, source=self.client.source) - cover_url = get_cover_urls(track["album"], self.client.source)[ - kwargs.get("embed_cover_size", "large") - ] + cover_urls = get_cover_urls(track["album"], self.client.source) + cover_url = ( + cover_urls[kwargs.get("embed_cover_size", "large")] + if cover_urls is not None + else None + ) self.append( Track( diff --git a/streamrip/utils.py b/streamrip/utils.py index e9ccf90..6f34539 100644 --- a/streamrip/utils.py +++ b/streamrip/utils.py @@ -306,7 +306,7 @@ def get_container(quality: int, source: str) -> str: return "MP3" -def get_cover_urls(resp: dict, source: str) -> dict: +def get_cover_urls(resp: dict, source: str) -> Optional[dict]: """Parse a response dict containing cover info according to the source. :param resp: From be087c01cd61dc2a2421161465cea02b121e691a Mon Sep 17 00:00:00 2001 From: Nathan Thomas Date: Mon, 20 Jun 2022 16:04:13 -0700 Subject: [PATCH 4/6] Fix lastfm duplicate downloads issue --- rip/core.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/rip/core.py b/rip/core.py index 3f075a8..b9dcb33 100644 --- a/rip/core.py +++ b/rip/core.py @@ -313,7 +313,8 @@ class RipCore(list): try: item.download(**arguments) for item_id in item.downloaded_ids: - self.db.add([item_id]) + # Add items row by row + self.db.add((item_id,)) except NonStreamable as e: e.print(item) self.failed_db.add((item.client.source, item.type, item.id)) @@ -816,7 +817,7 @@ class RipCore(list): info = [] words = re.compile(r"[\w\s]+") - title_tags = re.compile('title="([^"]+)"') + title_tags = re.compile(r' 0: with concurrent.futures.ThreadPoolExecutor(max_workers=15) as executor: - last_page = int(remaining_tracks // 50) + int( - remaining_tracks % 50 != 0 + last_page = ( + 1 + int(remaining_tracks // 50) + int(remaining_tracks % 50 != 0) ) + logger.debug("Fetching up to page %d", last_page) futures = [ executor.submit(requests.get, f"{url}?page={page}") - for page in range(1, last_page + 1) + for page in range(2, last_page + 1) ] for future in concurrent.futures.as_completed(futures): From 615a36257bf924178805e2acceb54f7716a33fc1 Mon Sep 17 00:00:00 2001 From: Nathan Thomas Date: Thu, 4 Aug 2022 18:40:38 -0700 Subject: [PATCH 5/6] Handle no artwork case #303 --- streamrip/media.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/streamrip/media.py b/streamrip/media.py index 9db8c35..530ce5a 100644 --- a/streamrip/media.py +++ b/streamrip/media.py @@ -29,12 +29,7 @@ from pathvalidate import sanitize_filepath from . import converter from .clients import Client, DeezloaderClient -from .constants import ( - ALBUM_KEYS, - FLAC_MAX_BLOCKSIZE, - FOLDER_FORMAT, - TRACK_FORMAT, -) +from .constants import ALBUM_KEYS, FLAC_MAX_BLOCKSIZE, FOLDER_FORMAT, TRACK_FORMAT from .downloadtools import DownloadPool, DownloadStream from .exceptions import ( InvalidQuality, @@ -1527,7 +1522,7 @@ class Album(Tracklist, Media): self.download_message() - cover_path = ( + cover_path: Optional[str] = ( _choose_and_download_cover( self.cover_urls, kwargs.get("embed_cover_size", "large"), @@ -2056,7 +2051,7 @@ class Artist(Tracklist, Media): else: self.folder = parent_folder - logger.debug("Artist folder: %s", folder) + logger.debug("Artist folder: %s", self.folder) logger.debug("Length of tracklist %d", len(self)) logger.debug("Filters: %s", filters) @@ -2326,7 +2321,7 @@ def _choose_and_download_cover( directory: str, keep_hires_cover: bool = True, downsize: Tuple[int, int] = (999999, 999999), -) -> str: +) -> Optional[str]: # choose optimal cover size and download it hashcode: str = hashlib.md5( @@ -2350,12 +2345,16 @@ def _choose_and_download_cover( ), f"Invalid cover size. Must be in {cover_urls.keys()}" embed_cover_url = cover_urls[preferred_size] + logger.debug("Chosen cover url: %s", embed_cover_url) if not os.path.exists(temp_cover_path): # Sometimes a size isn't available. When this is the case, find # the first `not None` url. if embed_cover_url is None: - embed_cover_url = next(filter(None, cover_urls.values())) + urls = tuple(filter(None, cover_urls.values())) + if len(urls) == 0: + return None + embed_cover_url = urls[0] logger.debug("Downloading cover from url %s", embed_cover_url) From 4af7c6a365f7d2045344cb6f265c247913a90cda Mon Sep 17 00:00:00 2001 From: reaitten Date: Wed, 14 Sep 2022 19:12:21 -0400 Subject: [PATCH 6/6] fix: multiple "600" in original cover URL filename - Fixes a minor issue when trying to set a Qobuz original cover URL. Streamrip replaces all occurrences of `600` when setting `cover_urls["original"]` which leads to raising an error when downloading the cover art for this album: https://www.qobuz.com/no-en/album/swan-alexandros/0060040678390 --- streamrip/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/streamrip/utils.py b/streamrip/utils.py index 6f34539..b409402 100644 --- a/streamrip/utils.py +++ b/streamrip/utils.py @@ -318,7 +318,7 @@ def get_cover_urls(resp: dict, source: str) -> Optional[dict]: if source == "qobuz": cover_urls = resp["image"] - cover_urls["original"] = cover_urls["large"].replace("600", "org") + cover_urls["original"] = "org".join(cover_urls["large"].rsplit('600', 1)) return cover_urls if source == "tidal":