Remove Bandcamp scraping (TOS violation), use YouTube links for all recommendations

This commit is contained in:
root
2026-03-31 09:51:20 -05:00
parent ccb49aa693
commit be30a47bbb
4 changed files with 7 additions and 56 deletions

View File

@@ -2,7 +2,7 @@ from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from app.core.config import settings from app.core.config import settings
from app.api.endpoints import auth, bandcamp, billing, lastfm, manual_import, playlist_fix, playlists, profile, recommendations, youtube_music from app.api.endpoints import auth, billing, lastfm, manual_import, playlist_fix, playlists, profile, recommendations, youtube_music
app = FastAPI(title="Vynl API", version="1.0.0", redirect_slashes=False) app = FastAPI(title="Vynl API", version="1.0.0", redirect_slashes=False)
@@ -22,7 +22,6 @@ app.include_router(recommendations.router, prefix="/api")
app.include_router(youtube_music.router, prefix="/api") app.include_router(youtube_music.router, prefix="/api")
app.include_router(manual_import.router, prefix="/api") app.include_router(manual_import.router, prefix="/api")
app.include_router(lastfm.router, prefix="/api") app.include_router(lastfm.router, prefix="/api")
app.include_router(bandcamp.router, prefix="/api")
app.include_router(profile.router, prefix="/api") app.include_router(profile.router, prefix="/api")

View File

@@ -186,7 +186,7 @@ Already in their library (do NOT recommend these):
{disliked_instruction} {disliked_instruction}
{exclude_instruction} {exclude_instruction}
Respond with exactly {count * 3 if bandcamp_mode else count} music recommendations as a JSON array. Each item should have: Respond with exactly {count} music recommendations as a JSON array. Each item should have:
- "title": song title - "title": song title
- "artist": artist name - "artist": artist name
- "album": album name (if known) - "album": album name (if known)
@@ -216,9 +216,7 @@ Return ONLY the JSON array, no other text."""
except json.JSONDecodeError: except json.JSONDecodeError:
return [], remaining return [], remaining
from app.services.bandcamp import search_bandcamp_verified # Save to DB with YouTube links
# Save to DB — in bandcamp mode, only keep results verified on Bandcamp
recommendations = [] recommendations = []
for rec in recs_data: for rec in recs_data:
if len(recommendations) >= count: if len(recommendations) >= count:
@@ -226,23 +224,8 @@ Return ONLY the JSON array, no other text."""
artist = rec.get("artist", "Unknown") artist = rec.get("artist", "Unknown")
title = rec.get("title", "Unknown") title = rec.get("title", "Unknown")
bandcamp_url = None
youtube_url = None
# Try Bandcamp for every recommendation # YouTube search link 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')}" youtube_url = f"https://www.youtube.com/results?search_query={quote_plus(f'{artist} {title} official music video')}"
r = Recommendation( r = Recommendation(
@@ -254,7 +237,6 @@ Return ONLY the JSON array, no other text."""
reason=rec.get("reason", ""), reason=rec.get("reason", ""),
score=rec.get("score"), score=rec.get("score"),
query=query, query=query,
bandcamp_url=bandcamp_url,
youtube_url=youtube_url, youtube_url=youtube_url,
) )
db.add(r) db.add(r)

View File

@@ -80,17 +80,7 @@ export default function RecommendationCard({ recommendation, onToggleSave, onDis
</button> </button>
)} )}
{recommendation.bandcamp_url ? ( {recommendation.youtube_url && (
<a
href={recommendation.bandcamp_url}
target="_blank"
rel="noopener noreferrer"
className="p-2 rounded-full bg-amber-50 text-amber-700 hover:bg-amber-100 transition-colors"
title="Listen on Bandcamp"
>
<ExternalLink className="w-4 h-4" />
</a>
) : recommendation.youtube_url ? (
<a <a
href={recommendation.youtube_url} href={recommendation.youtube_url}
target="_blank" target="_blank"
@@ -100,7 +90,7 @@ export default function RecommendationCard({ recommendation, onToggleSave, onDis
> >
<ExternalLink className="w-4 h-4" /> <ExternalLink className="w-4 h-4" />
</a> </a>
) : null} )}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -260,26 +260,6 @@ export default function Discover() {
/> />
</div> </div>
{/* Bandcamp Mode Toggle */}
<div className="flex items-center gap-3">
<button
type="button"
onClick={() => setBandcampMode(!bandcampMode)}
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors cursor-pointer border-none ${
bandcampMode ? 'bg-purple' : 'bg-charcoal-muted/30'
}`}
>
<span
className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
bandcampMode ? 'translate-x-6' : 'translate-x-1'
}`}
/>
</button>
<span className="text-sm text-charcoal">
Bandcamp mode
<span className="text-charcoal-muted ml-1"> prioritize indie & underground artists</span>
</span>
</div>
{/* Remaining count */} {/* Remaining count */}
{!user?.is_pro && ( {!user?.is_pro && (