commit inicial
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
"""Background task que consulta recently_played cada 30s y persiste el historial."""
|
||||
import asyncio
|
||||
import logging
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from app.database import SessionLocal
|
||||
from app.models import PlayHistory
|
||||
from app import spotify
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
POLL_INTERVAL = 30 # segundos
|
||||
|
||||
|
||||
async def start_poller():
|
||||
while True:
|
||||
try:
|
||||
await asyncio.to_thread(_fetch_and_save)
|
||||
except Exception as exc:
|
||||
logger.warning("history_poller error: %s", exc)
|
||||
await asyncio.sleep(POLL_INTERVAL)
|
||||
|
||||
|
||||
def _fetch_and_save():
|
||||
if not spotify.is_authenticated():
|
||||
return
|
||||
|
||||
sp = spotify.get_client()
|
||||
result = sp.current_user_recently_played(limit=50)
|
||||
items = result.get("items", [])
|
||||
if not items:
|
||||
return
|
||||
|
||||
# Recolectar IDs de artistas únicos para lookup de géneros en batch
|
||||
artist_ids: set[str] = set()
|
||||
for item in items:
|
||||
for artist in item["track"]["artists"]:
|
||||
artist_ids.add(artist["id"])
|
||||
|
||||
genre_map: dict[str, list[str]] = {}
|
||||
artist_id_list = list(artist_ids)
|
||||
for i in range(0, len(artist_id_list), 50):
|
||||
batch = artist_id_list[i : i + 50]
|
||||
try:
|
||||
data = sp.artists(batch)
|
||||
for a in data.get("artists") or []:
|
||||
if a:
|
||||
genre_map[a["id"]] = a.get("genres", [])
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
db = SessionLocal()
|
||||
try:
|
||||
saved = 0
|
||||
for item in items:
|
||||
track = item["track"]
|
||||
played_at = datetime.fromisoformat(
|
||||
item["played_at"].replace("Z", "+00:00")
|
||||
)
|
||||
|
||||
exists = (
|
||||
db.query(PlayHistory)
|
||||
.filter(
|
||||
PlayHistory.track_id == track["id"],
|
||||
PlayHistory.played_at == played_at,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if exists:
|
||||
continue
|
||||
|
||||
track_artists = track.get("artists", [])
|
||||
artist_names = [a["name"] for a in track_artists]
|
||||
genres: set[str] = set()
|
||||
for a in track_artists:
|
||||
genres.update(genre_map.get(a["id"], []))
|
||||
|
||||
db.add(
|
||||
PlayHistory(
|
||||
track_id=track["id"],
|
||||
track_name=track["name"],
|
||||
artists=", ".join(artist_names),
|
||||
genres=", ".join(sorted(genres)),
|
||||
played_at=played_at,
|
||||
)
|
||||
)
|
||||
saved += 1
|
||||
|
||||
if saved:
|
||||
db.commit()
|
||||
logger.info("history_poller: guardadas %d reproducciones", saved)
|
||||
except Exception:
|
||||
db.rollback()
|
||||
raise
|
||||
finally:
|
||||
db.close()
|
||||
Reference in New Issue
Block a user