Improve recursive_quality behaviour
This commit is contained in:
@@ -187,15 +187,15 @@ class Download_JOB:
|
||||
# Post-process each returned media in the chunk
|
||||
for idx in range(len(chunk_medias)):
|
||||
if "errors" in chunk_medias[idx]:
|
||||
c_media_json = cls.__get_url(non_episode_tracks[len(non_episode_medias) + idx], quality_download)
|
||||
chunk_medias[idx] = c_media_json
|
||||
# Do not fallback to legacy URL; mark as unavailable for this quality
|
||||
chunk_medias[idx] = {"media": []}
|
||||
else:
|
||||
if not chunk_medias[idx]['media']:
|
||||
c_media_json = cls.__get_url(non_episode_tracks[len(non_episode_medias) + idx], quality_download)
|
||||
chunk_medias[idx] = c_media_json
|
||||
# Do not fallback to legacy URL; mark as unavailable
|
||||
chunk_medias[idx] = {"media": []}
|
||||
elif len(chunk_medias[idx]['media'][0]['sources']) == 1:
|
||||
c_media_json = cls.__get_url(non_episode_tracks[len(non_episode_medias) + idx], quality_download)
|
||||
chunk_medias[idx] = c_media_json
|
||||
# Keep single-source media as-is; do not fallback
|
||||
pass
|
||||
non_episode_medias.extend(chunk_medias)
|
||||
except NoRightOnMedia:
|
||||
for c_track in tokens_chunk:
|
||||
@@ -585,7 +585,9 @@ class EASY_DW:
|
||||
if filesize == 0:
|
||||
song = self.__song_metadata['music']
|
||||
artist = self.__song_metadata['artist']
|
||||
# Switch quality settings to MP3_320.
|
||||
if not self.__recursive_quality:
|
||||
raise QualityNotFound(f"FLAC not available for {song} - {artist} and recursive quality search is disabled.")
|
||||
# Fallback to MP3_320 if recursive_quality is enabled
|
||||
self.__quality_download = 'MP3_320'
|
||||
self.__file_format = '.mp3'
|
||||
self.__song_path = self.__song_path.rsplit('.', 1)[0] + '.mp3'
|
||||
@@ -598,51 +600,97 @@ class EASY_DW:
|
||||
# Continue with the normal download process.
|
||||
try:
|
||||
media_list = self.__infos_dw['media_url']['media']
|
||||
song_link = media_list[0]['sources'][0]['url']
|
||||
|
||||
# Try all sources for the requested quality before attempting any fallback
|
||||
crypted_audio = None
|
||||
last_error = None
|
||||
for media_entry in media_list:
|
||||
sources = media_entry.get('sources') or []
|
||||
for src in sources:
|
||||
song_link = src.get('url')
|
||||
if not song_link:
|
||||
continue
|
||||
try:
|
||||
crypted_audio = API_GW.song_exist(song_link)
|
||||
except TrackNotFound:
|
||||
if crypted_audio:
|
||||
last_error = None
|
||||
break
|
||||
except Exception as e_try_src:
|
||||
last_error = e_try_src
|
||||
continue
|
||||
if crypted_audio:
|
||||
break
|
||||
|
||||
if not crypted_audio:
|
||||
song = self.__song_metadata['music']
|
||||
artist = self.__song_metadata['artist']
|
||||
|
||||
if self.__file_format == '.flac':
|
||||
if not self.__recursive_quality:
|
||||
raise QualityNotFound(f"FLAC not available for {song} - {artist} and recursive quality search is disabled.")
|
||||
logger.warning(f"\n⚠ {song} - {artist} is not available in FLAC format. Trying MP3...")
|
||||
self.__quality_download = 'MP3_320'
|
||||
self.__file_format = '.mp3'
|
||||
self.__song_path = self.__song_path.rsplit('.', 1)[0] + '.mp3'
|
||||
|
||||
media = Download_JOB.check_sources(
|
||||
[self.__infos_dw], 'MP3_320'
|
||||
)
|
||||
media = Download_JOB.check_sources([self.__infos_dw], 'MP3_320')
|
||||
if media:
|
||||
self.__infos_dw['media_url'] = media[0]
|
||||
song_link = media[0]['media'][0]['sources'][0]['url']
|
||||
media_list = self.__infos_dw['media_url']['media']
|
||||
# Try all sources for fallback quality
|
||||
for media_entry in media_list:
|
||||
sources = media_entry.get('sources') or []
|
||||
for src in sources:
|
||||
song_link = src.get('url')
|
||||
if not song_link:
|
||||
continue
|
||||
try:
|
||||
crypted_audio = API_GW.song_exist(song_link)
|
||||
if crypted_audio:
|
||||
last_error = None
|
||||
break
|
||||
except Exception as e_try_src2:
|
||||
last_error = e_try_src2
|
||||
continue
|
||||
if crypted_audio:
|
||||
break
|
||||
if not crypted_audio:
|
||||
raise TrackNotFound(f"Track {song} - {artist} not available in MP3 after FLAC attempt failed (all sources unreachable). Last error: {last_error}")
|
||||
else:
|
||||
raise TrackNotFound(f"Track {song} - {artist} not available in MP3 after FLAC attempt failed (media not found for MP3).")
|
||||
else:
|
||||
if not self.__recursive_quality:
|
||||
# msg was not defined, provide a more specific message
|
||||
raise QualityNotFound(f"Quality {self.__quality_download} not found for {song} - {artist} and recursive quality search is disabled.")
|
||||
for c_quality in qualities:
|
||||
if self.__quality_download == c_quality:
|
||||
continue
|
||||
media = Download_JOB.check_sources(
|
||||
[self.__infos_dw], c_quality
|
||||
)
|
||||
media = Download_JOB.check_sources([self.__infos_dw], c_quality)
|
||||
if media:
|
||||
self.__infos_dw['media_url'] = media[0]
|
||||
song_link = media[0]['media'][0]['sources'][0]['url']
|
||||
media_list = self.__infos_dw['media_url']['media']
|
||||
# Try all sources for alternative quality
|
||||
for media_entry in media_list:
|
||||
sources = media_entry.get('sources') or []
|
||||
for src in sources:
|
||||
song_link = src.get('url')
|
||||
if not song_link:
|
||||
continue
|
||||
try:
|
||||
crypted_audio = API_GW.song_exist(song_link)
|
||||
if crypted_audio:
|
||||
self.__c_quality = qualities[c_quality]
|
||||
self.__set_quality()
|
||||
last_error = None
|
||||
break
|
||||
except TrackNotFound:
|
||||
if c_quality == "MP3_128":
|
||||
raise TrackNotFound(f"Error with {song} - {artist}. All available qualities failed, last attempt was {c_quality}. Link: {self.__link}")
|
||||
except Exception as e_try_src3:
|
||||
last_error = e_try_src3
|
||||
continue
|
||||
if crypted_audio:
|
||||
break
|
||||
if crypted_audio:
|
||||
break
|
||||
if not crypted_audio:
|
||||
raise TrackNotFound(f"Error with {song} - {artist}. All available qualities failed. Last error: {last_error}. Link: {self.__link}")
|
||||
|
||||
c_crypted_audio = crypted_audio.iter_content(2048)
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@ from requests import (
|
||||
post as req_post,
|
||||
)
|
||||
from deezspot.libutils.logging_utils import logger
|
||||
import re
|
||||
from urllib.parse import urlparse, urlunparse
|
||||
|
||||
class API_GW:
|
||||
|
||||
@@ -271,28 +273,39 @@ class API_GW:
|
||||
if song_link and 'spreaker.com' in song_link:
|
||||
return req_get(song_link, stream=True)
|
||||
|
||||
crypted_audio = req_get(song_link)
|
||||
|
||||
try:
|
||||
crypted_audio = req_get(song_link, stream=True, timeout=15)
|
||||
if len(crypted_audio.content) == 0:
|
||||
raise TrackNotFound
|
||||
|
||||
return crypted_audio
|
||||
except Exception as e:
|
||||
# DNS fallback across dzcdn proxy hosts (e-cdns-proxy-0..7)
|
||||
try:
|
||||
parsed = urlparse(song_link)
|
||||
host = parsed.netloc
|
||||
if re.search(r"e-cdns-proxy-\d+\.dzcdn\.net", host):
|
||||
m = re.search(r"e-cdns-proxy-(\d+)\.dzcdn\.net", host)
|
||||
original_idx = int(m.group(1)) if m else -1
|
||||
for i in range(0, 8):
|
||||
if i == original_idx:
|
||||
continue
|
||||
new_host = re.sub(r"e-cdns-proxy-\d+\.dzcdn\.net", f"e-cdns-proxy-{i}.dzcdn.net", host)
|
||||
new_url = urlunparse((parsed.scheme, new_host, parsed.path, parsed.params, parsed.query, parsed.fragment))
|
||||
try:
|
||||
alt_resp = req_get(new_url, stream=True, timeout=15)
|
||||
if len(alt_resp.content) == 0:
|
||||
continue
|
||||
return alt_resp
|
||||
except Exception:
|
||||
continue
|
||||
except Exception:
|
||||
pass
|
||||
# If all fallbacks failed, re-raise as TrackNotFound/Connection error
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
def get_medias_url(cls, tracks_token, quality):
|
||||
others_qualities = []
|
||||
|
||||
for c_quality in qualities:
|
||||
if c_quality == quality:
|
||||
continue
|
||||
|
||||
c_quality_set = {
|
||||
"cipher": "BF_CBC_STRIPE",
|
||||
"format": c_quality
|
||||
}
|
||||
|
||||
others_qualities.append(c_quality_set)
|
||||
|
||||
# Only request the specific desired quality to avoid unexpected fallbacks
|
||||
json_data = {
|
||||
"license_token": cls.__license_token,
|
||||
"media": [
|
||||
@@ -303,7 +316,7 @@ class API_GW:
|
||||
"cipher": "BF_CBC_STRIPE",
|
||||
"format": quality
|
||||
}
|
||||
] + others_qualities
|
||||
]
|
||||
}
|
||||
],
|
||||
"track_tokens": tracks_token
|
||||
|
||||
@@ -38,7 +38,7 @@ class QualityNotFound(Exception):
|
||||
if not msg:
|
||||
self.msg = (
|
||||
f"The {quality} quality doesn't exist :)\
|
||||
\nThe qualities have to be FLAC or MP3_320 or MP3_256 or MP3_128"
|
||||
\nThe qualities have to be FLAC, MP3_320 or MP3_128"
|
||||
)
|
||||
else:
|
||||
self.msg = msg
|
||||
|
||||
Reference in New Issue
Block a user