updated utils

This commit is contained in:
cool.gitter.choco
2025-01-28 13:11:32 -06:00
parent 942d921ce7
commit 8a48fd3140
4 changed files with 21 additions and 32 deletions

View File

@@ -11,4 +11,5 @@
/test.sh /test.sh
/__pycache__/ /__pycache__/
/Dockerfile /Dockerfile
/docker-compose.yaml /docker-compose.yaml
/README.md

View File

@@ -5,38 +5,37 @@ import random
import string import string
import sys import sys
import traceback import traceback
from multiprocessing import Process # Use multiprocessing instead of threading from multiprocessing import Process
# Define the Blueprint for album-related routes
album_bp = Blueprint('album', __name__) album_bp = Blueprint('album', __name__)
# Function to generate random filenames
def generate_random_filename(length=6): def generate_random_filename(length=6):
chars = string.ascii_lowercase + string.digits 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)) + '.prg'
# File wrapper to flush writes immediately
class FlushingFileWrapper: class FlushingFileWrapper:
def __init__(self, file): def __init__(self, file):
self.file = file self.file = file
def write(self, text): def write(self, text):
self.file.write(text) # Filter lines to only write JSON objects
for line in text.split('\n'):
if line.startswith('{'):
self.file.write(line + '\n')
self.file.flush() self.file.flush()
def flush(self): def flush(self):
self.file.flush() self.file.flush()
# Define the download task as a top-level function for picklability
def download_task(service, url, main, fallback, prg_path): def download_task(service, url, main, fallback, 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:
flushing_file = FlushingFileWrapper(f) flushing_file = FlushingFileWrapper(f)
original_stdout = sys.stdout original_stdout = sys.stdout
sys.stdout = flushing_file # Redirect stdout to the file sys.stdout = flushing_file # Redirect stdout
try: try:
# Execute the download process
download_album( download_album(
service=service, service=service,
url=url, url=url,
@@ -45,7 +44,6 @@ def download_task(service, url, main, fallback, prg_path):
) )
flushing_file.write(json.dumps({"status": "complete"}) + "\n") flushing_file.write(json.dumps({"status": "complete"}) + "\n")
except Exception as e: except Exception as e:
# Capture exceptions and write to file
error_data = json.dumps({ error_data = json.dumps({
"status": "error", "status": "error",
"message": str(e), "message": str(e),
@@ -53,9 +51,8 @@ def download_task(service, url, main, fallback, prg_path):
}) })
flushing_file.write(error_data + "\n") flushing_file.write(error_data + "\n")
finally: finally:
sys.stdout = original_stdout # Restore original stdout sys.stdout = original_stdout # Restore stdout
except Exception as e: except Exception as e:
# Handle exceptions that occur outside the main download process
with open(prg_path, 'w') as f: with open(prg_path, 'w') as f:
error_data = json.dumps({ error_data = json.dumps({
"status": "error", "status": "error",
@@ -64,16 +61,13 @@ def download_task(service, url, main, fallback, prg_path):
}) })
f.write(error_data + "\n") f.write(error_data + "\n")
# Define the route to handle album download requests
@album_bp.route('/download', methods=['GET']) @album_bp.route('/download', methods=['GET'])
def handle_download(): def handle_download():
# Extract query parameters
service = request.args.get('service') service = request.args.get('service')
url = request.args.get('url') url = request.args.get('url')
main = request.args.get('main') main = request.args.get('main')
fallback = request.args.get('fallback') # Optional parameter fallback = request.args.get('fallback')
# Validate required parameters
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"}),
@@ -81,19 +75,16 @@ def handle_download():
mimetype='application/json' mimetype='application/json'
) )
# Generate a unique file for storing the download progress
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)
prg_path = os.path.join(prg_dir, filename) prg_path = os.path.join(prg_dir, filename)
# Start a new process for each download task
Process( Process(
target=download_task, target=download_task,
args=(service, url, main, fallback, prg_path) args=(service, url, main, fallback, prg_path)
).start() ).start()
# Return the filename to the client for progress tracking
return Response( return Response(
json.dumps({"prg_file": filename}), json.dumps({"prg_file": filename}),
status=202, status=202,

View File

@@ -5,12 +5,10 @@ import random
import string import string
import sys import sys
import traceback import traceback
from multiprocessing import Process # Changed from Thread to Process from multiprocessing import Process
playlist_bp = Blueprint('playlist', __name__) playlist_bp = Blueprint('playlist', __name__)
# Removed thread-local stdout setup since we're using process isolation
def generate_random_filename(length=6): def generate_random_filename(length=6):
chars = string.ascii_lowercase + string.digits 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)) + '.prg'
@@ -20,13 +18,14 @@ class FlushingFileWrapper:
self.file = file self.file = file
def write(self, text): def write(self, text):
self.file.write(text) for line in text.split('\n'):
if line.startswith('{'):
self.file.write(line + '\n')
self.file.flush() self.file.flush()
def flush(self): def flush(self):
self.file.flush() self.file.flush()
# Moved download_task to top-level for picklability
def download_task(service, url, main, fallback, prg_path): def download_task(service, url, main, fallback, prg_path):
try: try:
from routes.utils.playlist import download_playlist from routes.utils.playlist import download_playlist
@@ -53,7 +52,6 @@ def download_task(service, url, main, fallback, prg_path):
finally: finally:
sys.stdout = original_stdout # Restore original stdout sys.stdout = original_stdout # Restore original stdout
except Exception as e: except Exception as e:
# Handle exceptions outside the main logic
with open(prg_path, 'w') as f: with open(prg_path, 'w') as f:
error_data = json.dumps({ error_data = json.dumps({
"status": "error", "status": "error",
@@ -81,7 +79,6 @@ def handle_download():
os.makedirs(prg_dir, exist_ok=True) os.makedirs(prg_dir, exist_ok=True)
prg_path = os.path.join(prg_dir, filename) prg_path = os.path.join(prg_dir, filename)
# Start a new process with required arguments
Process( Process(
target=download_task, target=download_task,
args=(service, url, main, fallback, prg_path) args=(service, url, main, fallback, prg_path)

View File

@@ -5,7 +5,7 @@ import random
import string import string
import sys import sys
import traceback import traceback
from multiprocessing import Process # Changed from threading import Thread from multiprocessing import Process
track_bp = Blueprint('track', __name__) track_bp = Blueprint('track', __name__)
@@ -18,13 +18,14 @@ class FlushingFileWrapper:
self.file = file self.file = file
def write(self, text): def write(self, text):
self.file.write(text) for line in text.split('\n'):
if line.startswith('{'):
self.file.write(line + '\n')
self.file.flush() self.file.flush()
def flush(self): def flush(self):
self.file.flush() self.file.flush()
# Moved download_task to top-level for multiprocessing compatibility
def download_task(service, url, main, fallback, prg_path): def download_task(service, url, main, fallback, prg_path):
try: try:
from routes.utils.track import download_track from routes.utils.track import download_track
@@ -78,7 +79,6 @@ def handle_download():
os.makedirs(prg_dir, exist_ok=True) os.makedirs(prg_dir, exist_ok=True)
prg_path = os.path.join(prg_dir, filename) prg_path = os.path.join(prg_dir, filename)
# Start a new process with required arguments
Process( Process(
target=download_task, target=download_task,
args=(service, url, main, fallback, prg_path) args=(service, url, main, fallback, prg_path)