added real time downloading
This commit is contained in:
@@ -27,7 +27,7 @@ class FlushingFileWrapper:
|
|||||||
def flush(self):
|
def flush(self):
|
||||||
self.file.flush()
|
self.file.flush()
|
||||||
|
|
||||||
def download_task(service, url, main, fallback, quality, fall_quality, prg_path):
|
def download_task(service, url, main, fallback, quality, fall_quality, real_time, prg_path):
|
||||||
try:
|
try:
|
||||||
from routes.utils.album import download_album
|
from routes.utils.album import download_album
|
||||||
with open(prg_path, 'w') as f:
|
with open(prg_path, 'w') as f:
|
||||||
@@ -42,7 +42,8 @@ def download_task(service, url, main, fallback, quality, fall_quality, prg_path)
|
|||||||
main=main,
|
main=main,
|
||||||
fallback=fallback,
|
fallback=fallback,
|
||||||
quality=quality,
|
quality=quality,
|
||||||
fall_quality=fall_quality
|
fall_quality=fall_quality,
|
||||||
|
real_time=real_time
|
||||||
)
|
)
|
||||||
flushing_file.write(json.dumps({"status": "complete"}) + "\n")
|
flushing_file.write(json.dumps({"status": "complete"}) + "\n")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -71,6 +72,10 @@ def handle_download():
|
|||||||
fallback = request.args.get('fallback')
|
fallback = request.args.get('fallback')
|
||||||
quality = request.args.get('quality')
|
quality = request.args.get('quality')
|
||||||
fall_quality = request.args.get('fall_quality')
|
fall_quality = request.args.get('fall_quality')
|
||||||
|
|
||||||
|
# Retrieve and normalize the real_time parameter; defaults to False.
|
||||||
|
real_time_arg = request.args.get('real_time', 'false')
|
||||||
|
real_time = real_time_arg.lower() in ['true', '1', 'yes']
|
||||||
|
|
||||||
# Sanitize main and fallback to prevent directory traversal
|
# Sanitize main and fallback to prevent directory traversal
|
||||||
if main:
|
if main:
|
||||||
@@ -142,11 +147,11 @@ def handle_download():
|
|||||||
|
|
||||||
Process(
|
Process(
|
||||||
target=download_task,
|
target=download_task,
|
||||||
args=(service, url, main, fallback, quality, fall_quality, prg_path)
|
args=(service, url, main, fallback, quality, fall_quality, real_time, prg_path)
|
||||||
).start()
|
).start()
|
||||||
|
|
||||||
return Response(
|
return Response(
|
||||||
json.dumps({"prg_file": filename}),
|
json.dumps({"prg_file": filename}),
|
||||||
status=202,
|
status=202,
|
||||||
mimetype='application/json'
|
mimetype='application/json'
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class FlushingFileWrapper:
|
|||||||
def flush(self):
|
def flush(self):
|
||||||
self.file.flush()
|
self.file.flush()
|
||||||
|
|
||||||
def download_task(service, url, main, fallback, quality, fall_quality, prg_path):
|
def download_task(service, url, main, fallback, quality, fall_quality, real_time, prg_path):
|
||||||
try:
|
try:
|
||||||
from routes.utils.playlist import download_playlist
|
from routes.utils.playlist import download_playlist
|
||||||
with open(prg_path, 'w') as f:
|
with open(prg_path, 'w') as f:
|
||||||
@@ -41,7 +41,8 @@ def download_task(service, url, main, fallback, quality, fall_quality, prg_path)
|
|||||||
main=main,
|
main=main,
|
||||||
fallback=fallback,
|
fallback=fallback,
|
||||||
quality=quality,
|
quality=quality,
|
||||||
fall_quality=fall_quality
|
fall_quality=fall_quality,
|
||||||
|
real_time=real_time
|
||||||
)
|
)
|
||||||
flushing_file.write(json.dumps({"status": "complete"}) + "\n")
|
flushing_file.write(json.dumps({"status": "complete"}) + "\n")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -71,6 +72,11 @@ def handle_download():
|
|||||||
quality = request.args.get('quality')
|
quality = request.args.get('quality')
|
||||||
fall_quality = request.args.get('fall_quality')
|
fall_quality = request.args.get('fall_quality')
|
||||||
|
|
||||||
|
# Retrieve the real_time parameter from the request query string.
|
||||||
|
# Here, if real_time is provided as "true", "1", or "yes" (case-insensitive) it will be interpreted as True.
|
||||||
|
real_time_str = request.args.get('real_time', 'false').lower()
|
||||||
|
real_time = real_time_str in ['true', '1', 'yes']
|
||||||
|
|
||||||
if not all([service, url, main]):
|
if not all([service, url, main]):
|
||||||
return Response(
|
return Response(
|
||||||
json.dumps({"error": "Missing parameters"}),
|
json.dumps({"error": "Missing parameters"}),
|
||||||
@@ -85,11 +91,11 @@ def handle_download():
|
|||||||
|
|
||||||
Process(
|
Process(
|
||||||
target=download_task,
|
target=download_task,
|
||||||
args=(service, url, main, fallback, quality, fall_quality, prg_path)
|
args=(service, url, main, fallback, quality, fall_quality, real_time, prg_path)
|
||||||
).start()
|
).start()
|
||||||
|
|
||||||
return Response(
|
return Response(
|
||||||
json.dumps({"prg_file": filename}),
|
json.dumps({"prg_file": filename}),
|
||||||
status=202,
|
status=202,
|
||||||
mimetype='application/json'
|
mimetype='application/json'
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ class FlushingFileWrapper:
|
|||||||
self.file = file
|
self.file = file
|
||||||
|
|
||||||
def write(self, text):
|
def write(self, text):
|
||||||
|
# Write only lines that start with a JSON object
|
||||||
for line in text.split('\n'):
|
for line in text.split('\n'):
|
||||||
if line.startswith('{'):
|
if line.startswith('{'):
|
||||||
self.file.write(line + '\n')
|
self.file.write(line + '\n')
|
||||||
@@ -26,13 +27,13 @@ class FlushingFileWrapper:
|
|||||||
def flush(self):
|
def flush(self):
|
||||||
self.file.flush()
|
self.file.flush()
|
||||||
|
|
||||||
def download_task(service, url, main, fallback, quality, fall_quality, prg_path):
|
def download_task(service, url, main, fallback, quality, fall_quality, real_time, prg_path):
|
||||||
try:
|
try:
|
||||||
from routes.utils.track import download_track
|
from routes.utils.track import download_track
|
||||||
with open(prg_path, 'w') as f:
|
with open(prg_path, 'w') as f:
|
||||||
flushing_file = FlushingFileWrapper(f)
|
flushing_file = FlushingFileWrapper(f)
|
||||||
original_stdout = sys.stdout
|
original_stdout = sys.stdout
|
||||||
sys.stdout = flushing_file # Redirect stdout per process
|
sys.stdout = flushing_file # Redirect stdout for this process
|
||||||
|
|
||||||
try:
|
try:
|
||||||
download_track(
|
download_track(
|
||||||
@@ -41,7 +42,8 @@ def download_task(service, url, main, fallback, quality, fall_quality, prg_path)
|
|||||||
main=main,
|
main=main,
|
||||||
fallback=fallback,
|
fallback=fallback,
|
||||||
quality=quality,
|
quality=quality,
|
||||||
fall_quality=fall_quality
|
fall_quality=fall_quality,
|
||||||
|
real_time=real_time
|
||||||
)
|
)
|
||||||
flushing_file.write(json.dumps({"status": "complete"}) + "\n")
|
flushing_file.write(json.dumps({"status": "complete"}) + "\n")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -71,6 +73,16 @@ def handle_download():
|
|||||||
quality = request.args.get('quality')
|
quality = request.args.get('quality')
|
||||||
fall_quality = request.args.get('fall_quality')
|
fall_quality = request.args.get('fall_quality')
|
||||||
|
|
||||||
|
# Retrieve and normalize the real_time parameter; defaults to False.
|
||||||
|
real_time_arg = request.args.get('real_time', 'false')
|
||||||
|
real_time = real_time_arg.lower() in ['true', '1', 'yes']
|
||||||
|
|
||||||
|
# Sanitize main and fallback to prevent directory traversal
|
||||||
|
if main:
|
||||||
|
main = os.path.basename(main)
|
||||||
|
if fallback:
|
||||||
|
fallback = os.path.basename(fallback)
|
||||||
|
|
||||||
if not all([service, url, main]):
|
if not all([service, url, main]):
|
||||||
return Response(
|
return Response(
|
||||||
json.dumps({"error": "Missing parameters"}),
|
json.dumps({"error": "Missing parameters"}),
|
||||||
@@ -78,6 +90,56 @@ def handle_download():
|
|||||||
mimetype='application/json'
|
mimetype='application/json'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Validate credentials based on service and fallback
|
||||||
|
try:
|
||||||
|
if service == 'spotify':
|
||||||
|
if fallback:
|
||||||
|
# Validate Deezer main credentials and Spotify fallback credentials
|
||||||
|
deezer_creds_path = os.path.abspath(os.path.join('./creds/deezer', main, 'credentials.json'))
|
||||||
|
if not os.path.isfile(deezer_creds_path):
|
||||||
|
return Response(
|
||||||
|
json.dumps({"error": "Invalid Deezer credentials directory"}),
|
||||||
|
status=400,
|
||||||
|
mimetype='application/json'
|
||||||
|
)
|
||||||
|
spotify_fallback_path = os.path.abspath(os.path.join('./creds/spotify', fallback, 'credentials.json'))
|
||||||
|
if not os.path.isfile(spotify_fallback_path):
|
||||||
|
return Response(
|
||||||
|
json.dumps({"error": "Invalid Spotify fallback credentials directory"}),
|
||||||
|
status=400,
|
||||||
|
mimetype='application/json'
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# Validate Spotify main credentials
|
||||||
|
spotify_creds_path = os.path.abspath(os.path.join('./creds/spotify', main, 'credentials.json'))
|
||||||
|
if not os.path.isfile(spotify_creds_path):
|
||||||
|
return Response(
|
||||||
|
json.dumps({"error": "Invalid Spotify credentials directory"}),
|
||||||
|
status=400,
|
||||||
|
mimetype='application/json'
|
||||||
|
)
|
||||||
|
elif service == 'deezer':
|
||||||
|
# Validate Deezer main credentials
|
||||||
|
deezer_creds_path = os.path.abspath(os.path.join('./creds/deezer', main, 'credentials.json'))
|
||||||
|
if not os.path.isfile(deezer_creds_path):
|
||||||
|
return Response(
|
||||||
|
json.dumps({"error": "Invalid Deezer credentials directory"}),
|
||||||
|
status=400,
|
||||||
|
mimetype='application/json'
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return Response(
|
||||||
|
json.dumps({"error": "Unsupported service"}),
|
||||||
|
status=400,
|
||||||
|
mimetype='application/json'
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
return Response(
|
||||||
|
json.dumps({"error": f"Credential validation failed: {str(e)}"}),
|
||||||
|
status=500,
|
||||||
|
mimetype='application/json'
|
||||||
|
)
|
||||||
|
|
||||||
filename = generate_random_filename()
|
filename = generate_random_filename()
|
||||||
prg_dir = './prgs'
|
prg_dir = './prgs'
|
||||||
os.makedirs(prg_dir, exist_ok=True)
|
os.makedirs(prg_dir, exist_ok=True)
|
||||||
@@ -85,11 +147,11 @@ def handle_download():
|
|||||||
|
|
||||||
Process(
|
Process(
|
||||||
target=download_task,
|
target=download_task,
|
||||||
args=(service, url, main, fallback, quality, fall_quality, prg_path)
|
args=(service, url, main, fallback, quality, fall_quality, real_time, prg_path)
|
||||||
).start()
|
).start()
|
||||||
|
|
||||||
return Response(
|
return Response(
|
||||||
json.dumps({"prg_file": filename}),
|
json.dumps({"prg_file": filename}),
|
||||||
status=202,
|
status=202,
|
||||||
mimetype='application/json'
|
mimetype='application/json'
|
||||||
)
|
)
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -4,15 +4,14 @@ import traceback
|
|||||||
from deezspot.spotloader import SpoLogin
|
from deezspot.spotloader import SpoLogin
|
||||||
from deezspot.deezloader import DeeLogin
|
from deezspot.deezloader import DeeLogin
|
||||||
|
|
||||||
def download_album(service, url, main, fallback=None, quality=None, fall_quality=None):
|
def download_album(service, url, main, fallback=None, quality=None, fall_quality=None, real_time=False):
|
||||||
try:
|
try:
|
||||||
if service == 'spotify':
|
if service == 'spotify':
|
||||||
|
|
||||||
if fallback:
|
if fallback:
|
||||||
if quality is None:
|
if quality is None:
|
||||||
quality = 'FLAC'
|
quality = 'FLAC'
|
||||||
if fall_quality is None:
|
if fall_quality is None:
|
||||||
fall_quality='HIGH'
|
fall_quality = 'HIGH'
|
||||||
# First attempt: use DeeLogin's download_albumspo with the 'main' (Deezer credentials)
|
# First attempt: use DeeLogin's download_albumspo with the 'main' (Deezer credentials)
|
||||||
try:
|
try:
|
||||||
# Load Deezer credentials from 'main' under deezer directory
|
# Load Deezer credentials from 'main' under deezer directory
|
||||||
@@ -24,7 +23,7 @@ def download_album(service, url, main, fallback=None, quality=None, fall_quality
|
|||||||
dl = DeeLogin(
|
dl = DeeLogin(
|
||||||
arl=deezer_creds.get('arl', ''),
|
arl=deezer_creds.get('arl', ''),
|
||||||
)
|
)
|
||||||
# Download using download_albumspo
|
# Download using download_albumspo; pass real_time_dl accordingly
|
||||||
dl.download_albumspo(
|
dl.download_albumspo(
|
||||||
link_album=url,
|
link_album=url,
|
||||||
output_dir="./downloads",
|
output_dir="./downloads",
|
||||||
@@ -33,7 +32,8 @@ def download_album(service, url, main, fallback=None, quality=None, fall_quality
|
|||||||
recursive_download=False,
|
recursive_download=False,
|
||||||
not_interface=False,
|
not_interface=False,
|
||||||
make_zip=False,
|
make_zip=False,
|
||||||
method_save=1
|
method_save=1,
|
||||||
|
real_time_dl=real_time
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Load fallback Spotify credentials and attempt download
|
# Load fallback Spotify credentials and attempt download
|
||||||
@@ -49,7 +49,8 @@ def download_album(service, url, main, fallback=None, quality=None, fall_quality
|
|||||||
recursive_download=False,
|
recursive_download=False,
|
||||||
not_interface=False,
|
not_interface=False,
|
||||||
method_save=1,
|
method_save=1,
|
||||||
make_zip=False
|
make_zip=False,
|
||||||
|
real_time_dl=real_time
|
||||||
)
|
)
|
||||||
except Exception as e2:
|
except Exception as e2:
|
||||||
# If fallback also fails, raise an error indicating both attempts failed
|
# If fallback also fails, raise an error indicating both attempts failed
|
||||||
@@ -60,7 +61,7 @@ def download_album(service, url, main, fallback=None, quality=None, fall_quality
|
|||||||
else:
|
else:
|
||||||
# Original behavior: use Spotify main
|
# Original behavior: use Spotify main
|
||||||
if quality is None:
|
if quality is None:
|
||||||
quality ='HIGH'
|
quality = 'HIGH'
|
||||||
creds_dir = os.path.join('./creds/spotify', main)
|
creds_dir = os.path.join('./creds/spotify', main)
|
||||||
credentials_path = os.path.abspath(os.path.join(creds_dir, 'credentials.json'))
|
credentials_path = os.path.abspath(os.path.join(creds_dir, 'credentials.json'))
|
||||||
spo = SpoLogin(credentials_path=credentials_path)
|
spo = SpoLogin(credentials_path=credentials_path)
|
||||||
@@ -72,11 +73,12 @@ def download_album(service, url, main, fallback=None, quality=None, fall_quality
|
|||||||
recursive_download=False,
|
recursive_download=False,
|
||||||
not_interface=False,
|
not_interface=False,
|
||||||
method_save=1,
|
method_save=1,
|
||||||
make_zip=False
|
make_zip=False,
|
||||||
|
real_time_dl=real_time
|
||||||
)
|
)
|
||||||
elif service == 'deezer':
|
elif service == 'deezer':
|
||||||
if quality is None:
|
if quality is None:
|
||||||
quality='FLAC'
|
quality = 'FLAC'
|
||||||
# Existing code remains the same, ignoring fallback
|
# Existing code remains the same, ignoring fallback
|
||||||
creds_dir = os.path.join('./creds/deezer', main)
|
creds_dir = os.path.join('./creds/deezer', main)
|
||||||
creds_path = os.path.abspath(os.path.join(creds_dir, 'credentials.json'))
|
creds_path = os.path.abspath(os.path.join(creds_dir, 'credentials.json'))
|
||||||
@@ -92,10 +94,11 @@ def download_album(service, url, main, fallback=None, quality=None, fall_quality
|
|||||||
recursive_quality=True,
|
recursive_quality=True,
|
||||||
recursive_download=False,
|
recursive_download=False,
|
||||||
method_save=1,
|
method_save=1,
|
||||||
make_zip=False
|
make_zip=False,
|
||||||
|
real_time_dl=real_time
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Unsupported service: {service}")
|
raise ValueError(f"Unsupported service: {service}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
raise # Re-raise the exception after logging
|
raise # Re-raise the exception after logging
|
||||||
|
|||||||
@@ -4,15 +4,14 @@ import traceback
|
|||||||
from deezspot.spotloader import SpoLogin
|
from deezspot.spotloader import SpoLogin
|
||||||
from deezspot.deezloader import DeeLogin
|
from deezspot.deezloader import DeeLogin
|
||||||
|
|
||||||
def download_playlist(service, url, main, fallback=None, quality=None, fall_quality=None):
|
def download_playlist(service, url, main, fallback=None, quality=None, fall_quality=None, real_time=False):
|
||||||
try:
|
try:
|
||||||
|
|
||||||
if service == 'spotify':
|
if service == 'spotify':
|
||||||
if fallback:
|
if fallback:
|
||||||
if quality is None:
|
if quality is None:
|
||||||
quality = 'FLAC'
|
quality = 'FLAC'
|
||||||
if fall_quality is None:
|
if fall_quality is None:
|
||||||
fall_quality='HIGH'
|
fall_quality = 'HIGH'
|
||||||
# First attempt: use DeeLogin's download_playlistspo with the 'main' (Deezer credentials)
|
# First attempt: use DeeLogin's download_playlistspo with the 'main' (Deezer credentials)
|
||||||
try:
|
try:
|
||||||
# Load Deezer credentials from 'main' under deezer directory
|
# Load Deezer credentials from 'main' under deezer directory
|
||||||
@@ -33,7 +32,8 @@ def download_playlist(service, url, main, fallback=None, quality=None, fall_qual
|
|||||||
recursive_download=False,
|
recursive_download=False,
|
||||||
not_interface=False,
|
not_interface=False,
|
||||||
make_zip=False,
|
make_zip=False,
|
||||||
method_save=1
|
method_save=1,
|
||||||
|
real_time_dl=real_time
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Load fallback Spotify credentials and attempt download
|
# Load fallback Spotify credentials and attempt download
|
||||||
@@ -49,7 +49,8 @@ def download_playlist(service, url, main, fallback=None, quality=None, fall_qual
|
|||||||
recursive_download=False,
|
recursive_download=False,
|
||||||
not_interface=False,
|
not_interface=False,
|
||||||
method_save=1,
|
method_save=1,
|
||||||
make_zip=False
|
make_zip=False,
|
||||||
|
real_time_dl=real_time
|
||||||
)
|
)
|
||||||
except Exception as e2:
|
except Exception as e2:
|
||||||
# If fallback also fails, raise an error indicating both attempts failed
|
# If fallback also fails, raise an error indicating both attempts failed
|
||||||
@@ -60,7 +61,7 @@ def download_playlist(service, url, main, fallback=None, quality=None, fall_qual
|
|||||||
else:
|
else:
|
||||||
# Original behavior: use Spotify main
|
# Original behavior: use Spotify main
|
||||||
if quality is None:
|
if quality is None:
|
||||||
quality='HIGH'
|
quality = 'HIGH'
|
||||||
creds_dir = os.path.join('./creds/spotify', main)
|
creds_dir = os.path.join('./creds/spotify', main)
|
||||||
credentials_path = os.path.abspath(os.path.join(creds_dir, 'credentials.json'))
|
credentials_path = os.path.abspath(os.path.join(creds_dir, 'credentials.json'))
|
||||||
spo = SpoLogin(credentials_path=credentials_path)
|
spo = SpoLogin(credentials_path=credentials_path)
|
||||||
@@ -72,11 +73,12 @@ def download_playlist(service, url, main, fallback=None, quality=None, fall_qual
|
|||||||
recursive_download=False,
|
recursive_download=False,
|
||||||
not_interface=False,
|
not_interface=False,
|
||||||
method_save=1,
|
method_save=1,
|
||||||
make_zip=False
|
make_zip=False,
|
||||||
|
real_time_dl=real_time
|
||||||
)
|
)
|
||||||
elif service == 'deezer':
|
elif service == 'deezer':
|
||||||
if quality is None:
|
if quality is None:
|
||||||
quality='FLAC'
|
quality = 'FLAC'
|
||||||
# Existing code for Deezer, using main as Deezer account
|
# Existing code for Deezer, using main as Deezer account
|
||||||
creds_dir = os.path.join('./creds/deezer', main)
|
creds_dir = os.path.join('./creds/deezer', main)
|
||||||
creds_path = os.path.abspath(os.path.join(creds_dir, 'credentials.json'))
|
creds_path = os.path.abspath(os.path.join(creds_dir, 'credentials.json'))
|
||||||
@@ -92,10 +94,11 @@ def download_playlist(service, url, main, fallback=None, quality=None, fall_qual
|
|||||||
recursive_quality=False,
|
recursive_quality=False,
|
||||||
recursive_download=False,
|
recursive_download=False,
|
||||||
method_save=1,
|
method_save=1,
|
||||||
make_zip=False
|
make_zip=False,
|
||||||
|
real_time_dl=real_time
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Unsupported service: {service}")
|
raise ValueError(f"Unsupported service: {service}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
raise # Re-raise the exception after logging
|
raise # Re-raise the exception after logging
|
||||||
|
|||||||
@@ -4,15 +4,14 @@ import traceback
|
|||||||
from deezspot.spotloader import SpoLogin
|
from deezspot.spotloader import SpoLogin
|
||||||
from deezspot.deezloader import DeeLogin
|
from deezspot.deezloader import DeeLogin
|
||||||
|
|
||||||
def download_track(service, url, main, fallback=None, quality=None, fall_quality=None):
|
def download_track(service, url, main, fallback=None, quality=None, fall_quality=None, real_time=False):
|
||||||
try:
|
try:
|
||||||
|
|
||||||
if service == 'spotify':
|
if service == 'spotify':
|
||||||
if fallback:
|
if fallback:
|
||||||
if quality is None:
|
if quality is None:
|
||||||
quality = 'FLAC'
|
quality = 'FLAC'
|
||||||
if fall_quality is None:
|
if fall_quality is None:
|
||||||
fall_quality='HIGH'
|
fall_quality = 'HIGH'
|
||||||
# First attempt: use Deezer's download_trackspo with 'main' (Deezer credentials)
|
# First attempt: use Deezer's download_trackspo with 'main' (Deezer credentials)
|
||||||
try:
|
try:
|
||||||
deezer_creds_dir = os.path.join('./creds/deezer', main)
|
deezer_creds_dir = os.path.join('./creds/deezer', main)
|
||||||
@@ -29,7 +28,8 @@ def download_track(service, url, main, fallback=None, quality=None, fall_quality
|
|||||||
recursive_quality=False,
|
recursive_quality=False,
|
||||||
recursive_download=False,
|
recursive_download=False,
|
||||||
not_interface=False,
|
not_interface=False,
|
||||||
method_save=1
|
method_save=1,
|
||||||
|
real_time_dl=real_time
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
spo_creds_dir = os.path.join('./creds/spotify', fallback)
|
spo_creds_dir = os.path.join('./creds/spotify', fallback)
|
||||||
@@ -42,12 +42,13 @@ def download_track(service, url, main, fallback=None, quality=None, fall_quality
|
|||||||
recursive_quality=False,
|
recursive_quality=False,
|
||||||
recursive_download=False,
|
recursive_download=False,
|
||||||
not_interface=False,
|
not_interface=False,
|
||||||
method_save=1
|
method_save=1,
|
||||||
|
real_time_dl=real_time
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# Directly use Spotify main account
|
# Directly use Spotify main account
|
||||||
if quality is None:
|
if quality is None:
|
||||||
quality='HIGH'
|
quality = 'HIGH'
|
||||||
creds_dir = os.path.join('./creds/spotify', main)
|
creds_dir = os.path.join('./creds/spotify', main)
|
||||||
credentials_path = os.path.abspath(os.path.join(creds_dir, 'credentials.json'))
|
credentials_path = os.path.abspath(os.path.join(creds_dir, 'credentials.json'))
|
||||||
spo = SpoLogin(credentials_path=credentials_path)
|
spo = SpoLogin(credentials_path=credentials_path)
|
||||||
@@ -58,12 +59,13 @@ def download_track(service, url, main, fallback=None, quality=None, fall_quality
|
|||||||
recursive_quality=False,
|
recursive_quality=False,
|
||||||
recursive_download=False,
|
recursive_download=False,
|
||||||
not_interface=False,
|
not_interface=False,
|
||||||
method_save=1
|
method_save=1,
|
||||||
|
real_time_dl=real_time
|
||||||
)
|
)
|
||||||
elif service == 'deezer':
|
elif service == 'deezer':
|
||||||
if quality is None:
|
if quality is None:
|
||||||
quality='FLAC'
|
quality = 'FLAC'
|
||||||
# Deezer download logic remains unchanged
|
# Deezer download logic remains unchanged, with real_time_dl passed accordingly
|
||||||
creds_dir = os.path.join('./creds/deezer', main)
|
creds_dir = os.path.join('./creds/deezer', main)
|
||||||
creds_path = os.path.abspath(os.path.join(creds_dir, 'credentials.json'))
|
creds_path = os.path.abspath(os.path.join(creds_dir, 'credentials.json'))
|
||||||
with open(creds_path, 'r') as f:
|
with open(creds_path, 'r') as f:
|
||||||
@@ -77,10 +79,11 @@ def download_track(service, url, main, fallback=None, quality=None, fall_quality
|
|||||||
quality_download=quality,
|
quality_download=quality,
|
||||||
recursive_quality=False,
|
recursive_quality=False,
|
||||||
recursive_download=False,
|
recursive_download=False,
|
||||||
method_save=1
|
method_save=1,
|
||||||
|
real_time_dl=real_time
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Unsupported service: {service}")
|
raise ValueError(f"Unsupported service: {service}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
raise
|
raise
|
||||||
|
|||||||
@@ -319,6 +319,12 @@ async function startDownload(url, type, item) {
|
|||||||
apiUrl += `&quality=${encodeURIComponent(service === 'spotify' ? spotifyQuality : deezerQuality)}`;
|
apiUrl += `&quality=${encodeURIComponent(service === 'spotify' ? spotifyQuality : deezerQuality)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New: append real_time parameter if Real time downloading is enabled
|
||||||
|
const realTimeEnabled = document.getElementById('realTimeToggle').checked;
|
||||||
|
if (realTimeEnabled) {
|
||||||
|
apiUrl += `&real_time=true`;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(apiUrl);
|
const response = await fetch(apiUrl);
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
@@ -326,7 +332,8 @@ async function startDownload(url, type, item) {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
showError('Download failed: ' + error.message);
|
showError('Download failed: ' + error.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function addToQueue(item, type, prgFile) {
|
function addToQueue(item, type, prgFile) {
|
||||||
const queueId = Date.now().toString() + Math.random().toString(36).substr(2, 9);
|
const queueId = Date.now().toString() + Math.random().toString(36).substr(2, 9);
|
||||||
@@ -673,12 +680,12 @@ function saveConfig() {
|
|||||||
deezer: document.getElementById('deezerAccountSelect').value,
|
deezer: document.getElementById('deezerAccountSelect').value,
|
||||||
fallback: document.getElementById('fallbackToggle').checked,
|
fallback: document.getElementById('fallbackToggle').checked,
|
||||||
spotifyQuality: document.getElementById('spotifyQualitySelect').value,
|
spotifyQuality: document.getElementById('spotifyQualitySelect').value,
|
||||||
deezerQuality: document.getElementById('deezerQualitySelect').value
|
deezerQuality: document.getElementById('deezerQualitySelect').value,
|
||||||
|
realTime: document.getElementById('realTimeToggle').checked // new property
|
||||||
};
|
};
|
||||||
localStorage.setItem('activeConfig', JSON.stringify(config));
|
localStorage.setItem('activeConfig', JSON.stringify(config));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function loadConfig() {
|
function loadConfig() {
|
||||||
const saved = JSON.parse(localStorage.getItem('activeConfig')) || {};
|
const saved = JSON.parse(localStorage.getItem('activeConfig')) || {};
|
||||||
|
|
||||||
@@ -699,7 +706,11 @@ function loadConfig() {
|
|||||||
|
|
||||||
const deezerQuality = document.getElementById('deezerQualitySelect');
|
const deezerQuality = document.getElementById('deezerQualitySelect');
|
||||||
if (deezerQuality) deezerQuality.value = saved.deezerQuality || 'MP3_128';
|
if (deezerQuality) deezerQuality.value = saved.deezerQuality || 'MP3_128';
|
||||||
}
|
|
||||||
|
// New: Real time downloading toggle
|
||||||
|
const realTimeToggle = document.getElementById('realTimeToggle');
|
||||||
|
if (realTimeToggle) realTimeToggle.checked = !!saved.realTime;
|
||||||
|
}
|
||||||
|
|
||||||
function isSpotifyUrl(url) {
|
function isSpotifyUrl(url) {
|
||||||
return url.startsWith('https://open.spotify.com/');
|
return url.startsWith('https://open.spotify.com/');
|
||||||
|
|||||||
@@ -46,6 +46,13 @@
|
|||||||
<span class="slider"></span>
|
<span class="slider"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="config-item">
|
||||||
|
<label>Real time downloading:</label>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox" id="realTimeToggle">
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Service Tabs -->
|
<!-- Service Tabs -->
|
||||||
|
|||||||
Reference in New Issue
Block a user