"""Download-related API endpoints.""" import uuid from flask import Blueprint, request from models import QueueItem from utils import make_error_response, make_response download_bp = Blueprint('download', __name__, url_prefix='/api') @download_bp.route('/download', methods=['POST']) def download_video(): """Queue a video for download or start an existing queue item.""" from app import download_engine, queue_store, yt_cli try: data = request.get_json() url = data.get('url', '').strip() if data else '' category = data.get('category') if data else None network_folder = data.get('network_folder') if data else None quality = data.get('quality') if data else None queue_id = data.get('queueId') if data else None # If queueId provided, use existing queue item if queue_id: item = queue_store.get_item(queue_id) if not item: return make_error_response("Queue item not found", 404) if item.status != "pending": return make_error_response(f"Cannot download item with status '{item.status}'", 400) # Check if already downloaded if yt_cli.is_video_downloaded(item.video_id): return make_error_response(f"Video {item.video_id} has already been downloaded", 409) # Enqueue for sequential processing download_engine.enqueue_download(item) return make_response({ "queueId": queue_id, "status": "pending", "message": "Added to download queue", }), 202 # No queueId — create new queue item if not url: return make_error_response("Video URL is required", 400) # Extract video ID from URL import re video_id = None id_match = re.search(r"(?:v=|\/)([0-9A-Za-z_-]{11})", url) if id_match: video_id = id_match.group(1) # Check if already downloaded if video_id and yt_cli.is_video_downloaded(video_id): return make_error_response(f"Video {video_id} has already been downloaded", 409) # Generate queue ID queue_id = str(uuid.uuid4()) # Get video info for title/thumbnail title = "Unknown Title" thumbnail = "" try: import yt_dlp ydl_opts = { 'dump_single_json': True, 'no_warnings': True, 'quiet': True, 'no_progress': True, 'write_thumbnail': False, } with yt_dlp.YoutubeDL(ydl_opts) as ydl: info = ydl.extract_info(url, download=False) if info: title = info.get("title", "Unknown Title") thumbnail = info.get("thumbnail", "") except Exception: pass # Create queue item queue_item = QueueItem( id=queue_id, video_id=video_id or "", title=title, url=url, thumbnail=thumbnail, category=category or "", network_folder=network_folder, quality=quality, ) # Enqueue for sequential processing download_engine.enqueue_download(queue_item) return make_response({ "queueId": queue_id, "status": "pending", "message": "Added to download queue", }), 202 except Exception as e: return make_error_response(f"Failed to queue download: {str(e)}", 500) @download_bp.route('/download/playlist', methods=['POST']) def download_playlist(): """Queue a playlist for download.""" from app import download_engine try: data = request.get_json() url = data.get('url', '').strip() if data else '' category = data.get('category') if data else None network_folder = data.get('network_folder') if data else None quality = data.get('quality') if data else None if not url: return make_error_response("Playlist URL is required", 400) # Generate queue ID queue_id = str(uuid.uuid4()) # Get playlist title title = "Unknown Playlist" try: import yt_dlp ydl_opts = { 'flat_playlist': True, 'dump_single_json': True, 'no_warnings': True, 'quiet': True, 'no_progress': True, } with yt_dlp.YoutubeDL(ydl_opts) as ydl: info = ydl.extract_info(url, download=False) if info: title = info.get("title", "Unknown Playlist") except Exception: pass # Create queue item queue_item = QueueItem( id=queue_id, video_id="", title=title, url=url, category=category or "", network_folder=network_folder, item_type="playlist", quality=quality, ) # Enqueue for sequential processing download_engine.enqueue_download(queue_item) return make_response({ "queueId": queue_id, "status": "pending", "message": "Added to download queue", }), 202 except Exception as e: return make_error_response(f"Failed to queue playlist: {str(e)}", 500) @download_bp.route('/download/direct', methods=['POST']) def download_video_direct(): """Download a video directly (legacy endpoint, synchronous).""" from app import download_engine, yt_cli try: data = request.get_json() url = data.get('url', '').strip() if data else '' category = data.get('category') if data else None network_folder = data.get('network_folder') if data else None quality = data.get('quality') if data else None if not url: return make_error_response("Video URL is required", 400) # Extract video ID from URL import re video_id = None id_match = re.search(r"(?:v=|\/)([0-9A-Za-z_-]{11})", url) if id_match: video_id = id_match.group(1) # Check if already downloaded if video_id and yt_cli.is_video_downloaded(video_id): return make_error_response(f"Video {video_id} has already been downloaded", 409) # Generate queue ID queue_id = str(uuid.uuid4()) # Create queue item queue_item = QueueItem( id=queue_id, video_id=video_id or "", title="Unknown Title", url=url, category=category or "", network_folder=network_folder, quality=quality, ) # Enqueue for sequential processing download_engine.enqueue_download(queue_item) return make_response({ "queueId": queue_id, "status": "pending", "message": "Added to download queue", }), 202 except Exception as e: return make_error_response(f"Failed to queue direct download: {str(e)}", 500)