now it remembers the queue
This commit is contained in:
@@ -14,16 +14,26 @@ download_processes = {}
|
||||
|
||||
def generate_random_filename(length=6):
|
||||
chars = string.ascii_lowercase + string.digits
|
||||
return ''.join(random.choice(chars) for _ in range(length)) + '.prg'
|
||||
return ''.join(random.choice(chars) for _ in range(length)) + '.album.prg'
|
||||
|
||||
class FlushingFileWrapper:
|
||||
def __init__(self, file):
|
||||
self.file = file
|
||||
|
||||
def write(self, text):
|
||||
# Filter lines to only write JSON objects
|
||||
# Process each line separately.
|
||||
for line in text.split('\n'):
|
||||
if line.startswith('{'):
|
||||
line = line.strip()
|
||||
# Only process non-empty lines that look like JSON objects.
|
||||
if line and line.startswith('{'):
|
||||
try:
|
||||
obj = json.loads(line)
|
||||
# Skip writing if the JSON object has a "type" of "track"
|
||||
if obj.get("type") == "track":
|
||||
continue
|
||||
except ValueError:
|
||||
# If not valid JSON, write the line as is.
|
||||
pass
|
||||
self.file.write(line + '\n')
|
||||
self.file.flush()
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ download_processes = {}
|
||||
|
||||
def generate_random_filename(length=6):
|
||||
chars = string.ascii_lowercase + string.digits
|
||||
return ''.join(random.choice(chars) for _ in range(length)) + '.prg'
|
||||
return ''.join(random.choice(chars) for _ in range(length)) + '.artist.prg'
|
||||
|
||||
class FlushingFileWrapper:
|
||||
def __init__(self, file):
|
||||
@@ -28,7 +28,16 @@ class FlushingFileWrapper:
|
||||
def write(self, text):
|
||||
# Only write lines that start with '{'
|
||||
for line in text.split('\n'):
|
||||
if line.startswith('{'):
|
||||
line = line.strip()
|
||||
if line and line.startswith('{'):
|
||||
try:
|
||||
obj = json.loads(line)
|
||||
# Skip writing if the JSON object has type "track"
|
||||
if obj.get("type") == "track":
|
||||
continue
|
||||
except ValueError:
|
||||
# If not valid JSON, write the line as is.
|
||||
pass
|
||||
self.file.write(line + '\n')
|
||||
self.file.flush()
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ playlist_processes = {}
|
||||
|
||||
def generate_random_filename(length=6):
|
||||
chars = string.ascii_lowercase + string.digits
|
||||
return ''.join(random.choice(chars) for _ in range(length)) + '.prg'
|
||||
return ''.join(random.choice(chars) for _ in range(length)) + '.playlist.prg'
|
||||
|
||||
class FlushingFileWrapper:
|
||||
def __init__(self, file):
|
||||
@@ -22,7 +22,18 @@ class FlushingFileWrapper:
|
||||
|
||||
def write(self, text):
|
||||
for line in text.split('\n'):
|
||||
if line.startswith('{'):
|
||||
line = line.strip()
|
||||
# Only process non-empty lines that start with '{'
|
||||
if line and line.startswith('{'):
|
||||
try:
|
||||
# Try to parse the line as JSON
|
||||
obj = json.loads(line)
|
||||
# If the object has a "type" key with the value "track", skip writing it.
|
||||
if obj.get("type") == "track":
|
||||
continue
|
||||
except ValueError:
|
||||
# If the line isn't valid JSON, we don't filter it.
|
||||
pass
|
||||
self.file.write(line + '\n')
|
||||
self.file.flush()
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from flask import Blueprint, abort
|
||||
from flask import Blueprint, abort, jsonify
|
||||
import os
|
||||
import json
|
||||
|
||||
prgs_bp = Blueprint('prgs', __name__, url_prefix='/api/prgs')
|
||||
|
||||
@@ -9,23 +10,104 @@ PRGS_DIR = os.path.join(os.getcwd(), 'prgs')
|
||||
@prgs_bp.route('/<filename>', methods=['GET'])
|
||||
def get_prg_file(filename):
|
||||
"""
|
||||
Return the last line of the specified file from the prgs directory.
|
||||
Return a JSON object with the resource type, its name (title) and the last line (progress update) of the PRG file.
|
||||
If the file is empty, return default values.
|
||||
"""
|
||||
try:
|
||||
# Security check to prevent path traversal attacks
|
||||
# Security check to prevent path traversal attacks.
|
||||
if '..' in filename or '/' in filename:
|
||||
abort(400, "Invalid file request")
|
||||
|
||||
filepath = os.path.join(PRGS_DIR, filename)
|
||||
|
||||
# Read the last line of the file
|
||||
with open(filepath, 'r') as f:
|
||||
content = f.read()
|
||||
lines = content.splitlines()
|
||||
last_line = lines[-1] if lines else ''
|
||||
|
||||
return last_line
|
||||
# If the file is empty, return default values.
|
||||
if not lines:
|
||||
return jsonify({
|
||||
"type": "",
|
||||
"name": "",
|
||||
"last_line": None
|
||||
})
|
||||
|
||||
# Process the initialization line (first line) to extract type and name.
|
||||
try:
|
||||
init_data = json.loads(lines[0])
|
||||
except Exception as e:
|
||||
# If parsing fails, use defaults.
|
||||
init_data = {}
|
||||
|
||||
resource_type = init_data.get("type", "")
|
||||
# Determine the name based on type.
|
||||
if resource_type == "track":
|
||||
resource_name = init_data.get("song", "")
|
||||
elif resource_type == "album":
|
||||
resource_name = init_data.get("album", "")
|
||||
elif resource_type == "playlist":
|
||||
resource_name = init_data.get("name", "")
|
||||
elif resource_type == "artist":
|
||||
resource_name = init_data.get("artist", "")
|
||||
else:
|
||||
resource_name = ""
|
||||
|
||||
# Get the last line from the file.
|
||||
last_line_raw = lines[-1]
|
||||
# Try to parse the last line as JSON.
|
||||
try:
|
||||
last_line_parsed = json.loads(last_line_raw)
|
||||
except Exception:
|
||||
last_line_parsed = last_line_raw # Fallback to returning raw string if JSON parsing fails.
|
||||
|
||||
return jsonify({
|
||||
"type": resource_type,
|
||||
"name": resource_name,
|
||||
"last_line": last_line_parsed
|
||||
})
|
||||
except FileNotFoundError:
|
||||
abort(404, "File not found")
|
||||
except Exception as e:
|
||||
abort(500, f"An error occurred: {e}")
|
||||
abort(500, f"An error occurred: {e}")
|
||||
|
||||
|
||||
@prgs_bp.route('/delete/<filename>', methods=['DELETE'])
|
||||
def delete_prg_file(filename):
|
||||
"""
|
||||
Delete the specified .prg file from the prgs directory.
|
||||
"""
|
||||
try:
|
||||
# Security checks to prevent path traversal and ensure correct file type.
|
||||
if '..' in filename or '/' in filename:
|
||||
abort(400, "Invalid file request")
|
||||
if not filename.endswith('.prg'):
|
||||
abort(400, "Only .prg files can be deleted")
|
||||
|
||||
filepath = os.path.join(PRGS_DIR, filename)
|
||||
|
||||
if not os.path.isfile(filepath):
|
||||
abort(404, "File not found")
|
||||
|
||||
os.remove(filepath)
|
||||
return {'message': f'File {filename} deleted successfully'}, 200
|
||||
except FileNotFoundError:
|
||||
abort(404, "File not found")
|
||||
except Exception as e:
|
||||
abort(500, f"An error occurred: {e}")
|
||||
|
||||
|
||||
@prgs_bp.route('/list', methods=['GET'])
|
||||
def list_prg_files():
|
||||
"""
|
||||
Retrieve a list of all .prg files in the prgs directory.
|
||||
"""
|
||||
try:
|
||||
prg_files = []
|
||||
if os.path.isdir(PRGS_DIR):
|
||||
with os.scandir(PRGS_DIR) as entries:
|
||||
for entry in entries:
|
||||
if entry.is_file() and entry.name.endswith('.prg'):
|
||||
prg_files.append(entry.name)
|
||||
return jsonify(prg_files)
|
||||
except Exception as e:
|
||||
abort(500, f"An error occurred: {e}")
|
||||
|
||||
@@ -14,7 +14,7 @@ track_processes = {}
|
||||
|
||||
def generate_random_filename(length=6):
|
||||
chars = string.ascii_lowercase + string.digits
|
||||
return ''.join(random.choice(chars) for _ in range(length)) + '.prg'
|
||||
return ''.join(random.choice(chars) for _ in range(length)) + '.track.prg'
|
||||
|
||||
class FlushingFileWrapper:
|
||||
def __init__(self, file):
|
||||
|
||||
@@ -49,10 +49,14 @@ def download_artist_albums(service, artist_url, main, fallback=None, quality=Non
|
||||
except Exception as e:
|
||||
log_json({"status": "error", "message": f"Error retrieving artist discography: {e}"})
|
||||
raise
|
||||
|
||||
albums = discography.get('items', [])
|
||||
# Attempt to extract the artist name from the discography; fallback to artist_url if not available.
|
||||
artist_name = discography.get("name", artist_url)
|
||||
# Extract artist name from the first album's artists
|
||||
artist_name = artist_url # default fallback
|
||||
if albums:
|
||||
first_album = albums[0]
|
||||
artists = first_album.get('artists', [])
|
||||
if artists:
|
||||
artist_name = artists[0].get('name', artist_url)
|
||||
|
||||
if not albums:
|
||||
log_json({
|
||||
@@ -64,7 +68,7 @@ def download_artist_albums(service, artist_url, main, fallback=None, quality=Non
|
||||
})
|
||||
return
|
||||
|
||||
log_json({"status": "initializing", "type": "artist", "total_albums": len(albums)})
|
||||
log_json({"status": "initializing", "type": "artist", "artist": artist_name, "total_albums": len(albums)})
|
||||
|
||||
for album in albums:
|
||||
try:
|
||||
@@ -109,4 +113,4 @@ def download_artist_albums(service, artist_url, main, fallback=None, quality=Non
|
||||
"type": "artist",
|
||||
"artist": artist_name,
|
||||
"album_type": album_type
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user