diff --git a/streamrip/client/deezer.py b/streamrip/client/deezer.py index 1071c78..3cc1d8b 100644 --- a/streamrip/client/deezer.py +++ b/streamrip/client/deezer.py @@ -212,7 +212,7 @@ class DeezerClient(Client): "quality allowed is 1.", ) except deezer.WrongGeolocation: - if not is_retry: + if not is_retry and fallback_id: return await self.get_downloadable(fallback_id, quality, is_retry=True) raise NonStreamableError( "The requested track is not available. This may be due to your country/location.", diff --git a/streamrip/client/downloadable.py b/streamrip/client/downloadable.py index 9eba477..d778a8f 100644 --- a/streamrip/client/downloadable.py +++ b/streamrip/client/downloadable.py @@ -124,9 +124,14 @@ class DeezerDownloadable(Downloadable): self.session = session self.url = info["url"] self.source: str = "deezer" - max_quality_available = max( + qualities_available = [ i for i, size in enumerate(info["quality_to_size"]) if size > 0 - ) + ] + if len(qualities_available) == 0: + raise NonStreamableError( + "Missing download info. Skipping.", + ) + max_quality_available = max(qualities_available) self.quality = min(info["quality"], max_quality_available) self._size = info["quality_to_size"][self.quality] if self.quality <= 1: diff --git a/streamrip/client/qobuz.py b/streamrip/client/qobuz.py index c181f9d..411979e 100644 --- a/streamrip/client/qobuz.py +++ b/streamrip/client/qobuz.py @@ -162,20 +162,20 @@ class QobuzClient(Client): f.qobuz.secrets = c.secrets f.set_modified() - self.session.headers.update({"X-App-Id": c.app_id}) + self.session.headers.update({"X-App-Id": str(c.app_id)}) self.secret = await self._get_valid_secret(c.secrets) if c.use_auth_token: params = { "user_id": c.email_or_userid, "user_auth_token": c.password_or_token, - "app_id": c.app_id, + "app_id": str(c.app_id), } else: params = { "email": c.email_or_userid, "password": c.password_or_token, - "app_id": c.app_id, + "app_id": str(c.app_id), } logger.debug("Request params %s", params) @@ -203,7 +203,7 @@ class QobuzClient(Client): c = self.config.session.qobuz params = { - "app_id": c.app_id, + "app_id": str(c.app_id), f"{media_type}_id": item, # Do these matter? "limit": 500, @@ -236,7 +236,7 @@ class QobuzClient(Client): c = self.config.session.qobuz page_limit = 500 params = { - "app_id": c.app_id, + "app_id": str(c.app_id), "label_id": label_id, "limit": page_limit, "offset": 0, @@ -254,7 +254,7 @@ class QobuzClient(Client): self._api_request( epoint, { - "app_id": c.app_id, + "app_id": str(c.app_id), "label_id": label_id, "limit": page_limit, "offset": offset, diff --git a/streamrip/filepath_utils.py b/streamrip/filepath_utils.py index 0613e76..2018954 100644 --- a/streamrip/filepath_utils.py +++ b/streamrip/filepath_utils.py @@ -5,8 +5,15 @@ from pathvalidate import sanitize_filename, sanitize_filepath # type: ignore ALLOWED_CHARS = set(printable) +# TODO: remove this when new pathvalidate release arrives with https://github.com/thombashi/pathvalidate/pull/48 +def truncate_str(text: str) -> str: + str_bytes = text.encode() + str_bytes = str_bytes[:255] + return str_bytes.decode(errors="ignore") + + def clean_filename(fn: str, restrict: bool = False) -> str: - path = str(sanitize_filename(fn)) + path = truncate_str(str(sanitize_filename(fn))) if restrict: path = "".join(c for c in path if c in ALLOWED_CHARS) diff --git a/streamrip/media/playlist.py b/streamrip/media/playlist.py index 0ed1c16..a38fdf3 100644 --- a/streamrip/media/playlist.py +++ b/streamrip/media/playlist.py @@ -80,7 +80,7 @@ class PendingPlaylistTrack(Pending): self.client.get_downloadable(self.id, quality), ) except NonStreamableError as e: - logger.error("Error fetching download info for track: %s", e) + logger.error(f"Error fetching download info for track {self.id}: {e}") self.db.set_failed(self.client.source, "track", self.id) return None diff --git a/streamrip/media/track.py b/streamrip/media/track.py index 695ad9b..b09cfa1 100644 --- a/streamrip/media/track.py +++ b/streamrip/media/track.py @@ -138,7 +138,7 @@ class PendingTrack(Pending): try: meta = TrackMetadata.from_resp(self.album, source, resp) except Exception as e: - logger.error(f"Error building track metadata for {id=}: {e}") + logger.error(f"Error building track metadata for {self.id}: {e}") return None if meta is None: @@ -147,7 +147,13 @@ class PendingTrack(Pending): return None quality = self.config.session.get_source(source).quality - downloadable = await self.client.get_downloadable(self.id, quality) + try: + downloadable = await self.client.get_downloadable(self.id, quality) + except NonStreamableError as e: + logger.error( + f"Error getting downloadable data for track {meta.tracknumber} [{self.id}]: {e}" + ) + return None downloads_config = self.config.session.downloads if downloads_config.disc_subdirectories and self.album.disctotal > 1: diff --git a/streamrip/metadata/album.py b/streamrip/metadata/album.py index aa0fb95..6264939 100644 --- a/streamrip/metadata/album.py +++ b/streamrip/metadata/album.py @@ -77,8 +77,8 @@ class AlbumMetadata: "year": self.year, "container": self.info.container, } - - return formatter.format(**info) + + return clean_filename(formatter.format(**info)) @classmethod def from_qobuz(cls, resp: dict) -> AlbumMetadata: