mirror of
https://github.com/nathom/streamrip.git
synced 2025-05-09 14:11:55 -04:00
Added support for Tidal lyrics and fixed parsing error when preferred quality too high (#736)
* fixed json error when preferred quality not found for track * added tidal lyrics support * improve mp3 lyrics support * handle error when there are no lyrics (404) * change error to warning
This commit is contained in:
parent
1aad9f0f65
commit
4c9baf9bb0
3 changed files with 22 additions and 2 deletions
|
@ -4,6 +4,7 @@ import json
|
|||
import logging
|
||||
import re
|
||||
import time
|
||||
from json import JSONDecodeError
|
||||
|
||||
import aiohttp
|
||||
|
||||
|
@ -101,6 +102,17 @@ class TidalClient(Client):
|
|||
|
||||
item["albums"] = album_resp["items"]
|
||||
item["albums"].extend(ep_resp["items"])
|
||||
elif media_type == "track":
|
||||
try:
|
||||
resp = await self._api_request(f"tracks/{str(item_id)}/lyrics", base="https://listen.tidal.com/v1")
|
||||
|
||||
# Use unsynced lyrics for MP3, synced for others (FLAC, OPUS, etc)
|
||||
if self.global_config.session.conversion.enabled and self.global_config.session.conversion.codec.upper() == "MP3":
|
||||
item["lyrics"] = resp.get("lyrics") or ''
|
||||
else:
|
||||
item["lyrics"] = resp.get("subtitles") or resp.get("lyrics") or ''
|
||||
except TypeError as e:
|
||||
logger.warning(f"Failed to get lyrics for {item_id}: {e}")
|
||||
|
||||
logger.debug(item)
|
||||
return item
|
||||
|
@ -140,6 +152,9 @@ class TidalClient(Client):
|
|||
manifest = json.loads(base64.b64decode(resp["manifest"]).decode("utf-8"))
|
||||
except KeyError:
|
||||
raise Exception(resp["userMessage"])
|
||||
except JSONDecodeError:
|
||||
logger.warning(f"Failed to get manifest for {track_id}. Retrying with lower quality.")
|
||||
return await self.get_downloadable(track_id, quality - 1)
|
||||
|
||||
logger.debug(manifest)
|
||||
enc_key = manifest.get("keyId")
|
||||
|
@ -306,7 +321,7 @@ class TidalClient(Client):
|
|||
async with self.session.post(url, data=data, auth=auth) as resp:
|
||||
return await resp.json()
|
||||
|
||||
async def _api_request(self, path: str, params=None) -> dict:
|
||||
async def _api_request(self, path: str, params=None, base: str = BASE) -> dict:
|
||||
"""Handle Tidal API requests.
|
||||
|
||||
:param path:
|
||||
|
@ -321,7 +336,7 @@ class TidalClient(Client):
|
|||
params["limit"] = 100
|
||||
|
||||
async with self.rate_limiter:
|
||||
async with self.session.get(f"{BASE}/{path}", params=params) as resp:
|
||||
async with self.session.get(f"{base}/{path}", params=params) as resp:
|
||||
if resp.status == 404:
|
||||
logger.warning("TIDAL: track not found", resp)
|
||||
raise NonStreamableError("TIDAL: Track not found")
|
||||
|
|
|
@ -183,6 +183,7 @@ class Container(Enum):
|
|||
"discnumber",
|
||||
"composer",
|
||||
"isrc",
|
||||
"lyrics",
|
||||
}
|
||||
if attr in in_trackmetadata:
|
||||
if attr == "album":
|
||||
|
|
|
@ -32,6 +32,7 @@ class TrackMetadata:
|
|||
discnumber: int
|
||||
composer: str | None
|
||||
isrc: str | None = None
|
||||
lyrics: str | None = ""
|
||||
|
||||
@classmethod
|
||||
def from_qobuz(cls, album: AlbumMetadata, resp: dict) -> TrackMetadata | None:
|
||||
|
@ -170,6 +171,8 @@ class TrackMetadata:
|
|||
else:
|
||||
artist = track["artist"]["name"]
|
||||
|
||||
lyrics = track.get("lyrics", "")
|
||||
|
||||
quality_map: dict[str, int] = {
|
||||
"LOW": 0,
|
||||
"HIGH": 1,
|
||||
|
@ -209,6 +212,7 @@ class TrackMetadata:
|
|||
discnumber=discnumber,
|
||||
composer=None,
|
||||
isrc=isrc,
|
||||
lyrics=lyrics
|
||||
)
|
||||
|
||||
@classmethod
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue