213 lines
7.0 KiB
Python
213 lines
7.0 KiB
Python
"""Download-related API endpoints."""
|
|
|
|
import uuid
|
|
from flask import Blueprint, request
|
|
from utils import make_response, make_error_response
|
|
from models import QueueItem
|
|
|
|
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, 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
|
|
|
|
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 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
|
|
|
|
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) |