[Bug] get_tracks_by_isrc acting strangly
Closed this issue ยท 5 comments
Running even something as basic as this:
def convertToTidal(isrc):
tracks = session.get_tracks_by_isrc(isrc)
if len(tracks) > 0:
return tracks[0].id
else:
return None
print(convertToTidal("USUM70972068"))
Almost always returns a bunch of errors.
Track '34354645' is unavailable
Traceback (most recent call last):
File "C:\Users\*****\*****\venv\Lib\site-packages\tidalapi\request.py", line 151, in request
request.raise_for_status()
~~~~~~~~~~~~~~~~~~~~~~~~^^
File "C:\Users\*****\*****\venv\Lib\site-packages\requests\models.py", line 1024, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: Not Found for url: https://api.tidal.com/v1/tracks/34354645?sessionId=REDACTED&countryCode=US&limit=1000
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\*****\*****\venv\Lib\site-packages\tidalapi\media.py", line 331, in _get
request = self.requests.request("GET", "tracks/%s" % media_id)
File "C:\Users\*****\*****\venv\Lib\site-packages\tidalapi\request.py", line 166, in request
raise ObjectNotFound
tidalapi.exceptions.ObjectNotFound
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "c:\Users\*****\*****\import tidalapi.py", line 50, in <module>
print(convertToTidal("USUM70972068"))
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
File "c:\Users\*****\*****\import tidalapi.py", line 44, in convertToTidal
tracks = session.get_tracks_by_isrc(isrc)
File "C:\Users\*****\*****\venv\Lib\site-packages\tidalapi\session.py", line 958, in get_tracks_by_isrc
return [self.track(tr["id"]) for tr in res["data"]]
~~~~~~~~~~^^^^^^^^^^
File "C:\Users\*****\*****\venv\Lib\site-packages\tidalapi\session.py", line 928, in track
item = media.Track(session=self, media_id=track_id)
File "C:\Users\*****\*****\venv\Lib\site-packages\tidalapi\media.py", line 212, in __init__
self._get(self.id)
~~~~~~~~~^^^^^^^^^
File "C:\Users\*****\*****\venv\Lib\site-packages\tidalapi\media.py", line 333, in _get
raise ObjectNotFound("Track not found or unavailable")
tidalapi.exceptions.ObjectNotFound: Track not found or unavailable
I don't think it always did this, or I'm just stupid, which is a possibility, in which case I apologize. But it's quite strange if, you put the track ID into the Tidal listen URL (https://listen.tidal.com/track/34354645) it returns a not found page. But in the browse URL it returns like a mix or something? (https://tidal.com/browse/track/34354645) Clicking play brings to the same not found page...
I don't think it always did this, or I'm just stupid, which is a possibility, in which case I apologize.
The issue is related to the ISRC (The API endpoint returns a list of tracks, of which one of them is not available for playback. The current python-tidal code assumes that all results are valid for playback, but clearly they are not.
For instance, session.get_tracks_by_isrc("USSM12209515") works fine.
But in the browse URL it returns like a mix or something?
The same ID can be reused for a track and mix, even though it is not the same item.
I believe this is indeed a bug, as the results returned from tidal should be validated somehow when returning the list of Tracks.
This fixes the issue that you found (looks like quite a few of the results are not valid for playback). The fact that Tidal returns "invalid" tracks in the results sounds like a bug in TIDAL's own API (https://developer.tidal.com/apiref?spec=catalogue-v2&ref=get-all-tracks&at=THIRD_PARTY). Or perhaps the misuse of the way we get tracks using python-tidal.
def get_tracks_by_isrc(self, isrc: str) -> list[media.Track]:
"""Function to search all tracks with a specific ISRC code. (eg. "USSM12209515")
This method uses the TIDAL openapi (v2). See the apiref below for more details:
https://apiref.developer.tidal.com/apiref?spec=catalogue-v2&ref=get-tracks-v2
:param isrc: The ISRC of the Track.
:return: Returns a list of :class:`.Track` objects that have access to the session instance used.
An empty list will be returned if no tracks matches the ISRC
"""
try:
params = {
"filter[isrc]": isrc,
}
res = self.request.request(
"GET",
"tracks",
params=params,
base_url=self.config.openapi_v2_location,
).json()
if res["data"]:
tracks = []
for tr in res["data"]:
try:
tracks.append(self.track(tr["id"]))
except ObjectNotFound:
continue
return tracks
...I'll add it in the next release ๐
This fixes the issue that you found (looks like quite a few of the results are not valid for playback). The fact that Tidal returns "invalid" tracks in the results sounds like a bug in TIDAL's own API (developer.tidal.com/apiref?spec=catalogue-v2&ref=get-all-tracks&at=THIRD_PARTY). Or perhaps the misuse of the way we get tracks using python-tidal.
I'll add it in the next release ๐
So I cloned the repo and fixed the function to be like what you recommended:
def get_tracks_by_isrc(self, isrc: str) -> list[media.Track]:
"""Function to search all tracks with a specific ISRC code. (eg. "USSM12209515")
This method uses the TIDAL openapi (v2). See the apiref below for more details:
https://apiref.developer.tidal.com/apiref?spec=catalogue-v2&ref=get-tracks-v2
:param isrc: The ISRC of the Track.
:return: Returns a list of :class:`.Track` objects that have access to the session instance used.
An empty list will be returned if no tracks matches the ISRC
"""
try:
params = {
"filter[isrc]": isrc,
}
res = self.request.request(
"GET",
"tracks",
params=params,
base_url=self.config.openapi_v2_location,
).json()
if res["data"]:
tracks = []
for tr in res["data"]:
try:
tracks.append(self.track(tr["id"]))
except ObjectNotFound:
continue
return tracks
except HTTPError:
log.error("Invalid ISRC code '%s'", isrc)
# Get latest detailed error response and return the response given from the TIDAL api
resp_str = self.request.get_latest_err_response_str()
if resp_str:
log.error("API Response: '%s'", resp_str)
raise InvalidISRC
That does make it not completely crash, and outputs this from the same example:
Track '123904398' is unavailable
Track '34354645' is unavailable
316416376
However, going to https://tidal.com/browse/track/316416376 it still seems to be one of those weird Mixes, though trying to play it is possible https://listen.tidal.com/album/316416364/track/316416376 and this does indeed confirm it is a part of a mix of some sort. Is it possible to also filter these out?
With and without my above fix, no errors are returned anymore. So perhaps Tidal fixed it in their end?
Can confirm it seems to be fixed on Tidal's end, thank you!