97 lines
2.7 KiB
Python
97 lines
2.7 KiB
Python
"""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()
|