134 lines
5.0 KiB
Python
134 lines
5.0 KiB
Python
import re
|
|
from typing import List
|
|
from fastapi import APIRouter, Request, Depends, Request, Depends
|
|
from pydantic import BaseModel
|
|
import logging
|
|
|
|
# Import authentication dependencies
|
|
from routes.auth.middleware import require_auth_from_state, User
|
|
|
|
# Import queue management and Spotify info
|
|
from routes.utils.get_info import get_spotify_info
|
|
from routes.utils.celery_queue_manager import download_queue_manager
|
|
|
|
# Import authentication dependencies
|
|
from routes.auth.middleware import require_auth_from_state, User
|
|
|
|
# Import queue management and Spotify info
|
|
from routes.utils.get_info import (
|
|
get_client,
|
|
get_track,
|
|
get_album,
|
|
get_playlist,
|
|
get_artist,
|
|
)
|
|
from routes.utils.celery_queue_manager import download_queue_manager
|
|
|
|
router = APIRouter()
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class BulkAddLinksRequest(BaseModel):
|
|
links: List[str]
|
|
|
|
|
|
@router.post("/bulk-add-spotify-links")
|
|
async def bulk_add_spotify_links(request: BulkAddLinksRequest, req: Request, current_user: User = Depends(require_auth_from_state)):
|
|
added_count = 0
|
|
failed_links = []
|
|
total_links = len(request.links)
|
|
|
|
client = get_client()
|
|
for link in request.links:
|
|
# Assuming links are pre-filtered by the frontend,
|
|
# but still handle potential errors during info retrieval or unsupported types
|
|
# Extract type and ID from the link directly using regex
|
|
match = re.match(
|
|
r"https://open\.spotify\.com(?:/[a-z]{2})?/(track|album|playlist|artist)/([a-zA-Z0-9]+)(?:\?.*)?",
|
|
link,
|
|
)
|
|
if not match:
|
|
logger.warning(
|
|
f"Could not parse Spotify link (unexpected format after frontend filter): {link}"
|
|
)
|
|
failed_links.append(link)
|
|
continue
|
|
|
|
spotify_type = match.group(1)
|
|
spotify_id = match.group(2)
|
|
logger.debug(f"Extracted from link: spotify_type={spotify_type}, spotify_id={spotify_id}")
|
|
logger.debug(f"Extracted from link: spotify_type={spotify_type}, spotify_id={spotify_id}")
|
|
|
|
try:
|
|
# Get basic info to confirm existence and get name/artist
|
|
if spotify_type == "playlist":
|
|
item_info = get_playlist(client, spotify_id, expand_items=False)
|
|
elif spotify_type == "track":
|
|
item_info = get_track(client, spotify_id)
|
|
elif spotify_type == "album":
|
|
item_info = get_album(client, spotify_id)
|
|
elif spotify_type == "artist":
|
|
# Not queued below, but fetch to validate link and name if needed
|
|
item_info = get_artist(client, spotify_id)
|
|
else:
|
|
logger.warning(
|
|
f"Unsupported Spotify type: {spotify_type} for link: {link}"
|
|
)
|
|
failed_links.append(link)
|
|
continue
|
|
|
|
item_name = item_info.get("name", "Unknown Name")
|
|
artist_name = ""
|
|
if spotify_type in ["track", "album"]:
|
|
artists = item_info.get("artists", [])
|
|
if artists:
|
|
artist_name = ", ".join(
|
|
[a.get("name", "Unknown Artist") for a in artists]
|
|
)
|
|
elif spotify_type == "playlist":
|
|
owner = item_info.get("owner", {})
|
|
artist_name = owner.get("display_name", "Unknown Owner")
|
|
|
|
# Construct URL for the download task
|
|
spotify_url = f"https://open.spotify.com/{spotify_type}/{spotify_id}"
|
|
|
|
# Prepare task data for the queue manager
|
|
task_data = {
|
|
"download_type": spotify_type,
|
|
"url": spotify_url,
|
|
"name": item_name,
|
|
"artist": artist_name,
|
|
"spotify_id": spotify_id,
|
|
"type": spotify_type,
|
|
"username": current_user.username,
|
|
"orig_request": dict(req.query_params),
|
|
}
|
|
|
|
# Add to download queue using the queue manager
|
|
task_id = download_queue_manager.add_task(task_data)
|
|
|
|
if task_id:
|
|
added_count += 1
|
|
logger.debug(f"Added {added_count}/{total_links} {spotify_type} '{item_name}' ({spotify_id}) to queue with task_id: {task_id}.")
|
|
else:
|
|
logger.warning(f"Failed to add {spotify_type} '{item_name}' ({spotify_id}) to queue.")
|
|
failed_links.append(link)
|
|
continue
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error processing Spotify link {link}: {e}", exc_info=True)
|
|
failed_links.append(link)
|
|
|
|
message = f"Successfully added {added_count}/{total_links} links to queue."
|
|
if failed_links:
|
|
message += f" Failed to add {len(failed_links)} links."
|
|
logger.warning(f"Bulk add completed with {len(failed_links)} failures.")
|
|
else:
|
|
logger.info(f"Bulk add completed successfully. Added {added_count} links.")
|
|
|
|
return {
|
|
"message": message,
|
|
"count": added_count,
|
|
"failed_links": failed_links,
|
|
}
|