mirror of
https://github.com/bnair123/MusicAnalyser.git
synced 2026-02-25 11:46:07 +00:00
feat: implement AI-curated playlist service and dashboard integration
- Added hierarchical AGENTS.md knowledge base - Implemented PlaylistService with 6h themed and 24h devotion mix logic - Integrated AI theme generation for 6h playlists via Gemini/OpenAI - Added /playlists/refresh and metadata endpoints to API - Updated background worker with scheduled playlist curation - Created frontend PlaylistsSection, Tooltip components and integrated into Dashboard - Added Alembic migration for playlist tracking columns - Fixed Docker healthcheck with curl installation
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import os
|
||||
from fastapi import FastAPI, Depends, HTTPException, BackgroundTasks, Query
|
||||
from sqlalchemy.orm import Session, joinedload
|
||||
from datetime import datetime, timedelta
|
||||
@@ -11,9 +12,15 @@ from .models import (
|
||||
AnalysisSnapshot,
|
||||
)
|
||||
from . import schemas
|
||||
from .ingest import ingest_recently_played
|
||||
from .ingest import (
|
||||
ingest_recently_played,
|
||||
get_spotify_client,
|
||||
get_reccobeats_client,
|
||||
get_genius_client,
|
||||
)
|
||||
from .services.stats_service import StatsService
|
||||
from .services.narrative_service import NarrativeService
|
||||
from .services.playlist_service import PlaylistService
|
||||
|
||||
load_dotenv()
|
||||
|
||||
@@ -204,3 +211,107 @@ def get_sessions(
|
||||
"marathon_rate": session_stats.get("marathon_session_rate", 0),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@app.post("/playlists/refresh/six-hour")
|
||||
async def refresh_six_hour_playlist(db: Session = Depends(get_db)):
|
||||
"""Triggers a 6-hour themed playlist refresh."""
|
||||
try:
|
||||
end_date = datetime.utcnow()
|
||||
start_date = end_date - timedelta(hours=6)
|
||||
|
||||
playlist_service = PlaylistService(
|
||||
db=db,
|
||||
spotify_client=get_spotify_client(),
|
||||
recco_client=get_reccobeats_client(),
|
||||
narrative_service=NarrativeService(),
|
||||
)
|
||||
|
||||
result = await playlist_service.curate_six_hour_playlist(start_date, end_date)
|
||||
|
||||
snapshot = AnalysisSnapshot(
|
||||
date=datetime.utcnow(),
|
||||
period_start=start_date,
|
||||
period_end=end_date,
|
||||
period_label="6h_refresh",
|
||||
metrics_payload={},
|
||||
narrative_report={},
|
||||
playlist_theme=result.get("theme_name"),
|
||||
playlist_theme_reasoning=result.get("description"),
|
||||
six_hour_playlist_id=result.get("playlist_id"),
|
||||
)
|
||||
db.add(snapshot)
|
||||
db.commit()
|
||||
|
||||
return result
|
||||
except Exception as e:
|
||||
print(f"Playlist Refresh Failed: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@app.post("/playlists/refresh/daily")
|
||||
async def refresh_daily_playlist(db: Session = Depends(get_db)):
|
||||
"""Triggers a 24-hour daily playlist refresh."""
|
||||
try:
|
||||
end_date = datetime.utcnow()
|
||||
start_date = end_date - timedelta(days=1)
|
||||
|
||||
playlist_service = PlaylistService(
|
||||
db=db,
|
||||
spotify_client=get_spotify_client(),
|
||||
recco_client=get_reccobeats_client(),
|
||||
narrative_service=NarrativeService(),
|
||||
)
|
||||
|
||||
result = await playlist_service.curate_daily_playlist(start_date, end_date)
|
||||
|
||||
snapshot = AnalysisSnapshot(
|
||||
date=datetime.utcnow(),
|
||||
period_start=start_date,
|
||||
period_end=end_date,
|
||||
period_label="24h_refresh",
|
||||
metrics_payload={},
|
||||
narrative_report={},
|
||||
daily_playlist_id=result.get("playlist_id"),
|
||||
)
|
||||
db.add(snapshot)
|
||||
db.commit()
|
||||
|
||||
return result
|
||||
except Exception as e:
|
||||
print(f"Daily Playlist Refresh Failed: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@app.get("/playlists")
|
||||
async def get_playlists_metadata(db: Session = Depends(get_db)):
|
||||
"""Returns metadata for the managed playlists."""
|
||||
latest_snapshot = (
|
||||
db.query(AnalysisSnapshot)
|
||||
.filter(AnalysisSnapshot.six_hour_playlist_id != None)
|
||||
.order_by(AnalysisSnapshot.date.desc())
|
||||
.first()
|
||||
)
|
||||
|
||||
return {
|
||||
"six_hour": {
|
||||
"id": latest_snapshot.six_hour_playlist_id
|
||||
if latest_snapshot
|
||||
else os.getenv("SIX_HOUR_PLAYLIST_ID"),
|
||||
"theme": latest_snapshot.playlist_theme if latest_snapshot else "N/A",
|
||||
"reasoning": latest_snapshot.playlist_theme_reasoning
|
||||
if latest_snapshot
|
||||
else "N/A",
|
||||
"last_refresh": latest_snapshot.date.isoformat()
|
||||
if latest_snapshot
|
||||
else None,
|
||||
},
|
||||
"daily": {
|
||||
"id": latest_snapshot.daily_playlist_id
|
||||
if latest_snapshot
|
||||
else os.getenv("DAILY_PLAYLIST_ID"),
|
||||
"last_refresh": latest_snapshot.date.isoformat()
|
||||
if latest_snapshot
|
||||
else None,
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user