diff --git a/streamrip/client/deezer.py b/streamrip/client/deezer.py index d2642d96..388c2257 100644 --- a/streamrip/client/deezer.py +++ b/streamrip/client/deezer.py @@ -72,37 +72,120 @@ async def get_track(self, item_id: str) -> dict: except Exception as e: raise NonStreamableError(e) - album_id = item["album"]["id"] try: + album_id = item["album"]["id"] album_metadata, album_tracks = await asyncio.gather( asyncio.to_thread(self.client.api.get_album, album_id), asyncio.to_thread(self.client.api.get_album_tracks, album_id), ) + # album_metadata["tracks"] = await self.get_alternative_tracks(album_tracks["data"]) + album_metadata["tracks"] = album_tracks["data"] + album_metadata["track_total"] = len(album_tracks["data"]) + item["album"] = album_metadata except Exception as e: - logger.error(f"Error fetching album of track {item_id}: {e}") - return item + item = await self.find_alternative_track(item) + album_id = item["album"]["id"] + try: + album_metadata, album_tracks = await asyncio.gather( + asyncio.to_thread(self.client.api.get_album, album_id), + asyncio.to_thread(self.client.api.get_album_tracks, album_id), + ) + album_metadata["tracks"] = album_tracks["data"] + album_metadata["track_total"] = len(album_tracks["data"]) + item["album"] = album_metadata + except Exception as e: + logger.error(f"Error fetching album of track {item_id}: {e}") + + + - album_metadata["tracks"] = album_tracks["data"] - album_metadata["track_total"] = len(album_tracks["data"]) - item["album"] = album_metadata return item + async def find_alternative_track(self, track): + result = self.client.gw.search(f"{track['title']} - {track['artist']['name']}") + + for found_track in result['TRACK']['data']: + if (found_track["SNG_TITLE"].lower() == track['title'].lower() and + found_track["ARTISTS"][0]["ART_NAME"].lower() == track['artist']['name'].lower()): + track['id'] = found_track["SNG_ID"] + + track['album']["id"] = found_track["ALB_ID"] + return track + + return track + + async def get_album(self, item_id: str) -> dict: album_metadata, album_tracks = await asyncio.gather( asyncio.to_thread(self.client.api.get_album, item_id), asyncio.to_thread(self.client.api.get_album_tracks, item_id), ) - album_metadata["tracks"] = album_tracks["data"] + album_metadata["tracks"] = await self.get_alternative_tracks(album_tracks["data"]) album_metadata["track_total"] = len(album_tracks["data"]) return album_metadata + + async def get_alternative(self, track): + item_fallbacks = await asyncio.to_thread( + self.client.gw.get_track_with_fallback, track["id"] + ) + + if not "album" in track: + track["album"] = {} + if "ALBUM_FALLBACK" in item_fallbacks: + for album_fallback in item_fallbacks['ALBUM_FALLBACK']['data']: + if "RIGHTS" in album_fallback and len(album_fallback["RIGHTS"]) > 0: + for alternative_track in self.client.gw.get_album_tracks(album_fallback["ALB_ID"]): + if alternative_track['SNG_TITLE'].lower() == track['title'].lower(): + track["id"] = alternative_track["SNG_ID"] + track["album"]["id"] = alternative_track["ALB_ID"] + + track["readable"] = len(alternative_track["RIGHTS"]) > 0 + return track + + + while True: + if "FALLBACK" in item_fallbacks: + item_fallbacks = item_fallbacks['FALLBACK'] + track["id"] = item_fallbacks["SNG_ID"] + track["album"]["id"] = item_fallbacks["ALB_ID"] + track["readable"] = len(item_fallbacks["RIGHTS"]) > 0 + else: + break + + + + if not track['readable']: + raise NonStreamableError(f"Track {track} not readable") + + return track + + + + async def get_alternative_tracks(self, tracks): + for track in tracks: + if not track["readable"]: + try: + retries = 0 + while True: + retries += 1 + if retries > 4: + break + # todo: add it to tracks[index] instead + track = await self.get_alternative(track) + except Exception as e: + logger.error( + f"Error while getting fallbacks for track {track['id']}: {e}" + ) + return tracks + async def get_playlist(self, item_id: str) -> dict: pl_metadata, pl_tracks = await asyncio.gather( asyncio.to_thread(self.client.api.get_playlist, item_id), asyncio.to_thread(self.client.api.get_playlist_tracks, item_id), ) - pl_metadata["tracks"] = pl_tracks["data"] + pl_metadata["tracks"] = await self.get_alternative_tracks(pl_tracks["data"]) pl_metadata["track_total"] = len(pl_tracks["data"]) return pl_metadata diff --git a/streamrip/media/track.py b/streamrip/media/track.py index b09cfa13..13c78441 100644 --- a/streamrip/media/track.py +++ b/streamrip/media/track.py @@ -65,6 +65,7 @@ async def download(self): try: await self.downloadable.download(self.download_path, callback) except Exception as e: + # TODO: vremya logger.error( f"Persistent error downloading track '{self.meta.title}', skipping: {e}" )