from datetime import datetime, timedelta from flask import Blueprint, abort, jsonify, request, url_for from ..extensions import db from ..models import Display, DisplaySession bp = Blueprint("api", __name__, url_prefix="/api") MAX_ACTIVE_SESSIONS_PER_DISPLAY = 2 SESSION_TTL_SECONDS = 90 @bp.get("/display//playlist") def display_playlist(token: str): display = Display.query.filter_by(token=token).first() if not display: abort(404) # Enforce: a display URL/token can be opened by max 2 concurrently active sessions. # Player sends a stable `sid` via querystring. sid = (request.args.get("sid") or "").strip() if sid: cutoff = datetime.utcnow() - timedelta(seconds=SESSION_TTL_SECONDS) DisplaySession.query.filter( DisplaySession.display_id == display.id, DisplaySession.last_seen_at < cutoff, ).delete(synchronize_session=False) db.session.commit() existing = DisplaySession.query.filter_by(display_id=display.id, sid=sid).first() if existing: existing.last_seen_at = datetime.utcnow() db.session.commit() else: active_count = ( DisplaySession.query.filter( DisplaySession.display_id == display.id, DisplaySession.last_seen_at >= cutoff, ).count() ) if active_count >= MAX_ACTIVE_SESSIONS_PER_DISPLAY: return ( jsonify( { "error": "display_limit_reached", "message": f"This display URL is already open on {MAX_ACTIVE_SESSIONS_PER_DISPLAY} displays.", } ), 429, ) s = DisplaySession( display_id=display.id, sid=sid, last_seen_at=datetime.utcnow(), ip=request.headers.get("X-Forwarded-For", request.remote_addr), user_agent=(request.headers.get("User-Agent") or "")[:300], ) db.session.add(s) db.session.commit() playlist = display.assigned_playlist if not playlist: return jsonify({"display": display.name, "playlist": None, "items": []}) items = [] for item in playlist.items: payload = { "id": item.id, "type": item.item_type, "title": item.title, "duration": item.duration_seconds, } if item.item_type in ("image", "video") and item.file_path: payload["src"] = url_for("static", filename=item.file_path) if item.item_type == "webpage": payload["url"] = item.url items.append(payload) return jsonify( { "display": display.name, "playlist": {"id": playlist.id, "name": playlist.name}, "items": items, } )