Files
Fossign/app/routes/api.py
2026-01-23 13:54:58 +01:00

89 lines
2.9 KiB
Python

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/<token>/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,
}
)