Implemented quality select
This commit is contained in:
@@ -27,7 +27,7 @@ class FlushingFileWrapper:
|
||||
def flush(self):
|
||||
self.file.flush()
|
||||
|
||||
def download_task(service, url, main, fallback, prg_path):
|
||||
def download_task(service, url, main, fallback, quality, fall_quality, prg_path):
|
||||
try:
|
||||
from routes.utils.album import download_album
|
||||
with open(prg_path, 'w') as f:
|
||||
@@ -40,7 +40,9 @@ def download_task(service, url, main, fallback, prg_path):
|
||||
service=service,
|
||||
url=url,
|
||||
main=main,
|
||||
fallback=fallback
|
||||
fallback=fallback,
|
||||
quality=quality,
|
||||
fall_quality=fall_quality
|
||||
)
|
||||
flushing_file.write(json.dumps({"status": "complete"}) + "\n")
|
||||
except Exception as e:
|
||||
@@ -67,6 +69,14 @@ def handle_download():
|
||||
url = request.args.get('url')
|
||||
main = request.args.get('main')
|
||||
fallback = request.args.get('fallback')
|
||||
quality = request.args.get('quality')
|
||||
fall_quality = request.args.get('fall_quality')
|
||||
|
||||
# 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]):
|
||||
return Response(
|
||||
@@ -75,6 +85,56 @@ def handle_download():
|
||||
mimetype='application/json'
|
||||
)
|
||||
|
||||
# Validate credentials based on service and fallback
|
||||
try:
|
||||
if service == 'spotify':
|
||||
if fallback:
|
||||
# Validate Deezer main 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()
|
||||
prg_dir = './prgs'
|
||||
os.makedirs(prg_dir, exist_ok=True)
|
||||
@@ -82,7 +142,7 @@ def handle_download():
|
||||
|
||||
Process(
|
||||
target=download_task,
|
||||
args=(service, url, main, fallback, prg_path)
|
||||
args=(service, url, main, fallback, quality, fall_quality, prg_path)
|
||||
).start()
|
||||
|
||||
return Response(
|
||||
|
||||
@@ -26,7 +26,7 @@ class FlushingFileWrapper:
|
||||
def flush(self):
|
||||
self.file.flush()
|
||||
|
||||
def download_task(service, url, main, fallback, prg_path):
|
||||
def download_task(service, url, main, fallback, quality, fall_quality, prg_path):
|
||||
try:
|
||||
from routes.utils.playlist import download_playlist
|
||||
with open(prg_path, 'w') as f:
|
||||
@@ -39,7 +39,9 @@ def download_task(service, url, main, fallback, prg_path):
|
||||
service=service,
|
||||
url=url,
|
||||
main=main,
|
||||
fallback=fallback
|
||||
fallback=fallback,
|
||||
quality=quality,
|
||||
fall_quality=fall_quality
|
||||
)
|
||||
flushing_file.write(json.dumps({"status": "complete"}) + "\n")
|
||||
except Exception as e:
|
||||
@@ -66,6 +68,8 @@ def handle_download():
|
||||
url = request.args.get('url')
|
||||
main = request.args.get('main')
|
||||
fallback = request.args.get('fallback')
|
||||
quality = request.args.get('quality')
|
||||
fall_quality = request.args.get('fall_quality')
|
||||
|
||||
if not all([service, url, main]):
|
||||
return Response(
|
||||
@@ -81,7 +85,7 @@ def handle_download():
|
||||
|
||||
Process(
|
||||
target=download_task,
|
||||
args=(service, url, main, fallback, prg_path)
|
||||
args=(service, url, main, fallback, quality, fall_quality, prg_path)
|
||||
).start()
|
||||
|
||||
return Response(
|
||||
|
||||
@@ -26,7 +26,7 @@ class FlushingFileWrapper:
|
||||
def flush(self):
|
||||
self.file.flush()
|
||||
|
||||
def download_task(service, url, main, fallback, prg_path):
|
||||
def download_task(service, url, main, fallback, quality, fall_quality, prg_path):
|
||||
try:
|
||||
from routes.utils.track import download_track
|
||||
with open(prg_path, 'w') as f:
|
||||
@@ -39,7 +39,9 @@ def download_task(service, url, main, fallback, prg_path):
|
||||
service=service,
|
||||
url=url,
|
||||
main=main,
|
||||
fallback=fallback
|
||||
fallback=fallback,
|
||||
quality=quality,
|
||||
fall_quality=fall_quality
|
||||
)
|
||||
flushing_file.write(json.dumps({"status": "complete"}) + "\n")
|
||||
except Exception as e:
|
||||
@@ -66,6 +68,8 @@ def handle_download():
|
||||
url = request.args.get('url')
|
||||
main = request.args.get('main')
|
||||
fallback = request.args.get('fallback')
|
||||
quality = request.args.get('quality')
|
||||
fall_quality = request.args.get('fall_quality')
|
||||
|
||||
if not all([service, url, main]):
|
||||
return Response(
|
||||
@@ -81,7 +85,7 @@ def handle_download():
|
||||
|
||||
Process(
|
||||
target=download_task,
|
||||
args=(service, url, main, fallback, prg_path)
|
||||
args=(service, url, main, fallback, quality, fall_quality, prg_path)
|
||||
).start()
|
||||
|
||||
return Response(
|
||||
|
||||
@@ -4,10 +4,15 @@ import traceback
|
||||
from deezspot.spotloader import SpoLogin
|
||||
from deezspot.deezloader import DeeLogin
|
||||
|
||||
def download_album(service, url, main, fallback=None):
|
||||
def download_album(service, url, main, fallback=None, quality=None, fall_quality=None):
|
||||
try:
|
||||
if service == 'spotify':
|
||||
|
||||
if fallback:
|
||||
if quality is None:
|
||||
quality = 'FLAC'
|
||||
if fall_quality is None:
|
||||
fall_quality='HIGH'
|
||||
# First attempt: use DeeLogin's download_albumspo with the 'main' (Deezer credentials)
|
||||
try:
|
||||
# Load Deezer credentials from 'main' under deezer directory
|
||||
@@ -23,7 +28,7 @@ def download_album(service, url, main, fallback=None):
|
||||
dl.download_albumspo(
|
||||
link_album=url,
|
||||
output_dir="./downloads",
|
||||
quality_download="FLAC",
|
||||
quality_download=quality,
|
||||
recursive_quality=True,
|
||||
recursive_download=False,
|
||||
not_interface=False,
|
||||
@@ -39,7 +44,7 @@ def download_album(service, url, main, fallback=None):
|
||||
spo.download_album(
|
||||
link_album=url,
|
||||
output_dir="./downloads",
|
||||
quality_download="HIGH",
|
||||
quality_download=fall_quality,
|
||||
recursive_quality=True,
|
||||
recursive_download=False,
|
||||
not_interface=False,
|
||||
@@ -54,13 +59,15 @@ def download_album(service, url, main, fallback=None):
|
||||
) from e2
|
||||
else:
|
||||
# Original behavior: use Spotify main
|
||||
if quality is None:
|
||||
quality ='HIGH'
|
||||
creds_dir = os.path.join('./creds/spotify', main)
|
||||
credentials_path = os.path.abspath(os.path.join(creds_dir, 'credentials.json'))
|
||||
spo = SpoLogin(credentials_path=credentials_path)
|
||||
spo.download_album(
|
||||
link_album=url,
|
||||
output_dir="./downloads",
|
||||
quality_download="HIGH",
|
||||
quality_download=quality,
|
||||
recursive_quality=True,
|
||||
recursive_download=False,
|
||||
not_interface=False,
|
||||
@@ -68,6 +75,8 @@ def download_album(service, url, main, fallback=None):
|
||||
make_zip=False
|
||||
)
|
||||
elif service == 'deezer':
|
||||
if quality is None:
|
||||
quality='FLAC'
|
||||
# Existing code remains the same, ignoring fallback
|
||||
creds_dir = os.path.join('./creds/deezer', main)
|
||||
creds_path = os.path.abspath(os.path.join(creds_dir, 'credentials.json'))
|
||||
@@ -79,7 +88,7 @@ def download_album(service, url, main, fallback=None):
|
||||
dl.download_albumdee(
|
||||
link_album=url,
|
||||
output_dir="./downloads",
|
||||
quality_download="FLAC",
|
||||
quality_download=quality,
|
||||
recursive_quality=True,
|
||||
recursive_download=False,
|
||||
method_save=1,
|
||||
|
||||
@@ -4,10 +4,15 @@ import traceback
|
||||
from deezspot.spotloader import SpoLogin
|
||||
from deezspot.deezloader import DeeLogin
|
||||
|
||||
def download_playlist(service, url, main, fallback=None):
|
||||
def download_playlist(service, url, main, fallback=None, quality=None, fall_quality=None):
|
||||
try:
|
||||
|
||||
if service == 'spotify':
|
||||
if fallback:
|
||||
if quality is None:
|
||||
quality = 'FLAC'
|
||||
if fall_quality is None:
|
||||
fall_quality='HIGH'
|
||||
# First attempt: use DeeLogin's download_playlistspo with the 'main' (Deezer credentials)
|
||||
try:
|
||||
# Load Deezer credentials from 'main' under deezer directory
|
||||
@@ -23,7 +28,7 @@ def download_playlist(service, url, main, fallback=None):
|
||||
dl.download_playlistspo(
|
||||
link_playlist=url,
|
||||
output_dir="./downloads",
|
||||
quality_download="FLAC",
|
||||
quality_download=quality,
|
||||
recursive_quality=True,
|
||||
recursive_download=False,
|
||||
not_interface=False,
|
||||
@@ -39,7 +44,7 @@ def download_playlist(service, url, main, fallback=None):
|
||||
spo.download_playlist(
|
||||
link_playlist=url,
|
||||
output_dir="./downloads",
|
||||
quality_download="HIGH",
|
||||
quality_download=fall_quality,
|
||||
recursive_quality=True,
|
||||
recursive_download=False,
|
||||
not_interface=False,
|
||||
@@ -54,13 +59,15 @@ def download_playlist(service, url, main, fallback=None):
|
||||
) from e2
|
||||
else:
|
||||
# Original behavior: use Spotify main
|
||||
if quality is None:
|
||||
quality='HIGH'
|
||||
creds_dir = os.path.join('./creds/spotify', main)
|
||||
credentials_path = os.path.abspath(os.path.join(creds_dir, 'credentials.json'))
|
||||
spo = SpoLogin(credentials_path=credentials_path)
|
||||
spo.download_playlist(
|
||||
link_playlist=url,
|
||||
output_dir="./downloads",
|
||||
quality_download="HIGH",
|
||||
quality_download=quality,
|
||||
recursive_quality=True,
|
||||
recursive_download=False,
|
||||
not_interface=False,
|
||||
@@ -68,6 +75,8 @@ def download_playlist(service, url, main, fallback=None):
|
||||
make_zip=False
|
||||
)
|
||||
elif service == 'deezer':
|
||||
if quality is None:
|
||||
quality='FLAC'
|
||||
# Existing code for Deezer, using main as Deezer account
|
||||
creds_dir = os.path.join('./creds/deezer', main)
|
||||
creds_path = os.path.abspath(os.path.join(creds_dir, 'credentials.json'))
|
||||
@@ -79,7 +88,7 @@ def download_playlist(service, url, main, fallback=None):
|
||||
dl.download_playlistdee(
|
||||
link_playlist=url,
|
||||
output_dir="./downloads",
|
||||
quality_download="FLAC",
|
||||
quality_download=quality,
|
||||
recursive_quality=False,
|
||||
recursive_download=False,
|
||||
method_save=1,
|
||||
|
||||
@@ -4,10 +4,15 @@ import traceback
|
||||
from deezspot.spotloader import SpoLogin
|
||||
from deezspot.deezloader import DeeLogin
|
||||
|
||||
def download_track(service, url, main, fallback=None):
|
||||
def download_track(service, url, main, fallback=None, quality=None, fall_quality=None):
|
||||
try:
|
||||
|
||||
if service == 'spotify':
|
||||
if fallback:
|
||||
if quality is None:
|
||||
quality = 'FLAC'
|
||||
if fall_quality is None:
|
||||
fall_quality='HIGH'
|
||||
# First attempt: use Deezer's download_trackspo with 'main' (Deezer credentials)
|
||||
try:
|
||||
deezer_creds_dir = os.path.join('./creds/deezer', main)
|
||||
@@ -20,7 +25,7 @@ def download_track(service, url, main, fallback=None):
|
||||
dl.download_trackspo(
|
||||
link_track=url,
|
||||
output_dir="./downloads",
|
||||
quality_download="FLAC",
|
||||
quality_download=quality,
|
||||
recursive_quality=False,
|
||||
recursive_download=False,
|
||||
not_interface=False,
|
||||
@@ -33,7 +38,7 @@ def download_track(service, url, main, fallback=None):
|
||||
spo.download_track(
|
||||
link_track=url,
|
||||
output_dir="./downloads",
|
||||
quality_download="HIGH",
|
||||
quality_download=fall_quality,
|
||||
recursive_quality=False,
|
||||
recursive_download=False,
|
||||
not_interface=False,
|
||||
@@ -41,19 +46,23 @@ def download_track(service, url, main, fallback=None):
|
||||
)
|
||||
else:
|
||||
# Directly use Spotify main account
|
||||
if quality is None:
|
||||
quality='HIGH'
|
||||
creds_dir = os.path.join('./creds/spotify', main)
|
||||
credentials_path = os.path.abspath(os.path.join(creds_dir, 'credentials.json'))
|
||||
spo = SpoLogin(credentials_path=credentials_path)
|
||||
spo.download_track(
|
||||
link_track=url,
|
||||
output_dir="./downloads",
|
||||
quality_download="HIGH",
|
||||
quality_download=quality,
|
||||
recursive_quality=False,
|
||||
recursive_download=False,
|
||||
not_interface=False,
|
||||
method_save=1
|
||||
)
|
||||
elif service == 'deezer':
|
||||
if quality is None:
|
||||
quality='FLAC'
|
||||
# Deezer download logic remains unchanged
|
||||
creds_dir = os.path.join('./creds/deezer', main)
|
||||
creds_path = os.path.abspath(os.path.join(creds_dir, 'credentials.json'))
|
||||
@@ -65,7 +74,7 @@ def download_track(service, url, main, fallback=None):
|
||||
dl.download_trackdee(
|
||||
link_track=url,
|
||||
output_dir="./downloads",
|
||||
quality_download="FLAC",
|
||||
quality_download=quality,
|
||||
recursive_quality=False,
|
||||
recursive_download=False,
|
||||
method_save=1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -76,23 +76,40 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
async function initConfig() {
|
||||
loadConfig();
|
||||
console.log(loadConfig())
|
||||
await updateAccountSelectors();
|
||||
|
||||
// Event listeners
|
||||
document.getElementById('fallbackToggle').addEventListener('change', () => {
|
||||
// Existing listeners
|
||||
const fallbackToggle = document.getElementById('fallbackToggle');
|
||||
if (fallbackToggle) {
|
||||
fallbackToggle.addEventListener('change', () => {
|
||||
saveConfig();
|
||||
updateAccountSelectors();
|
||||
});
|
||||
}
|
||||
|
||||
const accountSelects = ['spotifyAccountSelect', 'deezerAccountSelect'];
|
||||
accountSelects.forEach(id => {
|
||||
document.getElementById(id).addEventListener('change', () => {
|
||||
const element = document.getElementById(id);
|
||||
if (element) {
|
||||
element.addEventListener('change', () => {
|
||||
saveConfig();
|
||||
updateAccountSelectors();
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Add quality select listeners with null checks
|
||||
const spotifyQuality = document.getElementById('spotifyQualitySelect');
|
||||
if (spotifyQuality) {
|
||||
spotifyQuality.addEventListener('change', saveConfig);
|
||||
}
|
||||
|
||||
const deezerQuality = document.getElementById('deezerQualitySelect');
|
||||
if (deezerQuality) {
|
||||
deezerQuality.addEventListener('change', saveConfig);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function updateAccountSelectors() {
|
||||
try {
|
||||
@@ -273,18 +290,38 @@ async function startDownload(url, type, item) {
|
||||
const spotifyAccount = document.getElementById('spotifyAccountSelect').value;
|
||||
const deezerAccount = document.getElementById('deezerAccountSelect').value;
|
||||
|
||||
let apiUrl = `/api/${type}/download?service=spotify&url=${encodeURIComponent(url)}`;
|
||||
|
||||
if (fallbackEnabled) {
|
||||
apiUrl += `&main=${deezerAccount}&fallback=${spotifyAccount}`;
|
||||
// Determine service from URL
|
||||
let service;
|
||||
if (url.includes('open.spotify.com')) {
|
||||
service = 'spotify';
|
||||
} else if (url.includes('deezer.com')) {
|
||||
service = 'deezer';
|
||||
} else {
|
||||
apiUrl += `&main=${spotifyAccount}`;
|
||||
showError('Unsupported service URL');
|
||||
return;
|
||||
}
|
||||
|
||||
let apiUrl = `/api/${type}/download?service=${service}&url=${encodeURIComponent(url)}`;
|
||||
|
||||
// Get quality settings
|
||||
const spotifyQuality = document.getElementById('spotifyQualitySelect').value;
|
||||
const deezerQuality = document.getElementById('deezerQualitySelect').value;
|
||||
|
||||
if (fallbackEnabled && service === 'spotify') {
|
||||
// Deezer fallback for Spotify URLs
|
||||
apiUrl += `&main=${deezerAccount}&fallback=${spotifyAccount}`;
|
||||
apiUrl += `&quality=${encodeURIComponent(deezerQuality)}`;
|
||||
apiUrl += `&fall_quality=${encodeURIComponent(spotifyQuality)}`;
|
||||
} else {
|
||||
// Standard download without fallback
|
||||
const mainAccount = service === 'spotify' ? spotifyAccount : deezerAccount;
|
||||
apiUrl += `&main=${mainAccount}`;
|
||||
apiUrl += `&quality=${encodeURIComponent(service === 'spotify' ? spotifyQuality : deezerQuality)}`;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(apiUrl);
|
||||
const data = await response.json();
|
||||
|
||||
addToQueue(item, type, data.prg_file);
|
||||
} catch (error) {
|
||||
showError('Download failed: ' + error.message);
|
||||
@@ -632,7 +669,9 @@ function saveConfig() {
|
||||
const config = {
|
||||
spotify: document.getElementById('spotifyAccountSelect').value,
|
||||
deezer: document.getElementById('deezerAccountSelect').value,
|
||||
fallback: document.getElementById('fallbackToggle').checked
|
||||
fallback: document.getElementById('fallbackToggle').checked,
|
||||
spotifyQuality: document.getElementById('spotifyQualitySelect').value,
|
||||
deezerQuality: document.getElementById('deezerQualitySelect').value
|
||||
};
|
||||
localStorage.setItem('activeConfig', JSON.stringify(config));
|
||||
}
|
||||
@@ -641,15 +680,23 @@ function saveConfig() {
|
||||
function loadConfig() {
|
||||
const saved = JSON.parse(localStorage.getItem('activeConfig')) || {};
|
||||
|
||||
// Set values only if they exist in the DOM
|
||||
// Account selects
|
||||
const spotifySelect = document.getElementById('spotifyAccountSelect');
|
||||
const deezerSelect = document.getElementById('deezerAccountSelect');
|
||||
|
||||
if (spotifySelect) spotifySelect.value = saved.spotify || '';
|
||||
|
||||
const deezerSelect = document.getElementById('deezerAccountSelect');
|
||||
if (deezerSelect) deezerSelect.value = saved.deezer || '';
|
||||
|
||||
// Fallback toggle
|
||||
const fallbackToggle = document.getElementById('fallbackToggle');
|
||||
if (fallbackToggle) fallbackToggle.checked = !!saved.fallback;
|
||||
|
||||
// Quality selects
|
||||
const spotifyQuality = document.getElementById('spotifyQualitySelect');
|
||||
if (spotifyQuality) spotifyQuality.value = saved.spotifyQuality || 'NORMAL';
|
||||
|
||||
const deezerQuality = document.getElementById('deezerQualitySelect');
|
||||
if (deezerQuality) deezerQuality.value = saved.deezerQuality || 'MP3_128';
|
||||
}
|
||||
|
||||
function isSpotifyUrl(url) {
|
||||
|
||||
@@ -19,10 +19,26 @@
|
||||
<label>Active Spotify Account:</label>
|
||||
<select id="spotifyAccountSelect"></select>
|
||||
</div>
|
||||
<div class="config-item">
|
||||
<label>Spotify Quality:</label>
|
||||
<select id="spotifyQualitySelect">
|
||||
<option value="NORMAL">Normal</option>
|
||||
<option value="HIGH">High</option>
|
||||
<option value="VERY_HIGH">Very High</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="config-item">
|
||||
<label>Active Deezer Account:</label>
|
||||
<select id="deezerAccountSelect"></select>
|
||||
</div>
|
||||
<div class="config-item">
|
||||
<label>Deezer Quality:</label>
|
||||
<select id="deezerQualitySelect">
|
||||
<option value="MP3_128">MP3 128</option>
|
||||
<option value="MP3_320">MP3 320</option>
|
||||
<option value="FLAC">FLAC</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="config-item">
|
||||
<label>Download Fallback:</label>
|
||||
<label class="switch">
|
||||
|
||||
Reference in New Issue
Block a user