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:
@@ -26,6 +26,7 @@ async def search_bandcamp_verified(artist: str, title: str) -> dict | None:
|
||||
"""Search Bandcamp and only return a result if the artist actually matches.
|
||||
|
||||
Returns the best matching result or None if no good match found.
|
||||
First tries artist+song, then falls back to artist-only search.
|
||||
"""
|
||||
# Try track search first: "artist title"
|
||||
results = await search_bandcamp(f"{artist} {title}", item_type="t")
|
||||
@@ -36,12 +37,12 @@ async def search_bandcamp_verified(artist: str, title: str) -> dict | None:
|
||||
if artist_sim >= 0.75 and title_sim >= 0.5:
|
||||
return r
|
||||
|
||||
# Try artist/band search as fallback — very strict matching
|
||||
# Try artist/band search as fallback — return their artist page URL
|
||||
results = await search_bandcamp(artist, item_type="b")
|
||||
for r in results:
|
||||
# For band results, title IS the band name
|
||||
name = r.get("title", "") or r.get("artist", "")
|
||||
if _similarity(name, artist) >= 0.8:
|
||||
if _similarity(name, artist) >= 0.7:
|
||||
return r
|
||||
|
||||
return None
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user