Add Bandcamp/YouTube links on all recs, Fix My Playlist, configurable rec count

- Bandcamp: match artist+song, fall back to artist-only page
- YouTube fallback: if not on Bandcamp, link to YouTube music video search
- Fix My Playlist: AI analyzes playlist, finds outliers, suggests replacements
- User chooses recommendation count (5, 10, 15, 20)
This commit is contained in:
root
2026-03-31 08:45:02 -05:00
parent 47ab3dd847
commit 240032d972
8 changed files with 93 additions and 21 deletions

View File

@@ -1,5 +1,6 @@
import json
from datetime import datetime, timezone, timedelta
from urllib.parse import quote_plus
import anthropic
from sqlalchemy import select, func
@@ -90,6 +91,7 @@ async def generate_recommendations(
mode: str = "discover",
adventurousness: int = 3,
exclude: str | None = None,
count: int = 5,
) -> tuple[list[Recommendation], int | None]:
"""Generate AI music recommendations using Claude."""
@@ -184,7 +186,7 @@ Already in their library (do NOT recommend these):
{disliked_instruction}
{exclude_instruction}
Respond with exactly {"15" if bandcamp_mode else "5"} music recommendations as a JSON array. Each item should have:
Respond with exactly {count * 3 if bandcamp_mode else count} music recommendations as a JSON array. Each item should have:
- "title": song title
- "artist": artist name
- "album": album name (if known)
@@ -219,33 +221,41 @@ Return ONLY the JSON array, no other text."""
# Save to DB — in bandcamp mode, only keep results verified on Bandcamp
recommendations = []
for rec in recs_data:
if len(recommendations) >= 5:
if len(recommendations) >= count:
break
artist = rec.get("artist", "Unknown")
title = rec.get("title", "Unknown")
bandcamp_url = None
if bandcamp_mode:
try:
match = await search_bandcamp_verified(
rec.get("artist", ""), rec.get("title", "")
)
if match:
bandcamp_url = match.get("bandcamp_url")
else:
# Not verified on Bandcamp — skip
continue
except Exception:
continue
youtube_url = None
# Try Bandcamp for every recommendation
try:
match = await search_bandcamp_verified(artist, title)
if match:
bandcamp_url = match.get("bandcamp_url")
except Exception:
pass
if bandcamp_mode and not bandcamp_url:
# In bandcamp mode, skip recommendations not found on Bandcamp
continue
# If not on Bandcamp, build a YouTube search link
if not bandcamp_url:
youtube_url = f"https://www.youtube.com/results?search_query={quote_plus(f'{artist} {title} official music video')}"
r = Recommendation(
user_id=user.id,
playlist_id=playlist_id,
title=rec.get("title", "Unknown"),
artist=rec.get("artist", "Unknown"),
title=title,
artist=artist,
album=rec.get("album"),
reason=rec.get("reason", ""),
score=rec.get("score"),
query=query,
bandcamp_url=bandcamp_url,
youtube_url=youtube_url,
)
db.add(r)
recommendations.append(r)