Initial import

This commit is contained in:
2026-01-25 13:26:45 +01:00
parent a5fe0f73a0
commit f4b7fb62f5
8 changed files with 834 additions and 149 deletions

View File

@@ -15,6 +15,16 @@ MAX_ACTIVE_SESSIONS_PER_DISPLAY = 3
SESSION_TTL_SECONDS = 90
def _is_playlist_active_now(p: Playlist, now_utc: datetime) -> bool:
"""Return True if playlist is active based on its optional schedule window."""
if p.schedule_start and now_utc < p.schedule_start:
return False
if p.schedule_end and now_utc > p.schedule_end:
return False
return True
def _enforce_and_touch_display_session(display: Display, sid: str | None):
"""Enforce concurrent display viewer limit and touch last_seen.
@@ -103,6 +113,18 @@ def _playlist_signature(display: Display) -> tuple[int | None, str]:
raw = "no-playlist"
return None, hashlib.sha1(raw.encode("utf-8")).hexdigest()
# Apply scheduling + priority rule so a schedule change triggers a player refresh.
playlists = Playlist.query.filter(Playlist.id.in_(active_ids)).all()
now_utc = datetime.utcnow()
scheduled = [p for p in playlists if _is_playlist_active_now(p, now_utc)]
if any(p.is_priority for p in scheduled):
scheduled = [p for p in scheduled if p.is_priority]
active_ids = [x for x in active_ids if any(p.id == x for p in scheduled)]
if not active_ids:
raw = "no-active-playlist"
return None, hashlib.sha1(raw.encode("utf-8")).hexdigest()
# Pull items in a stable order so reordering affects signature.
if use_mapping:
items = (
@@ -174,11 +196,30 @@ def display_playlist(token: str):
use_mapping = False
if not active_ids:
return jsonify({"display": display.name, "playlists": [], "items": []})
return jsonify(
{
"display": display.name,
"transition": display.transition or "none",
"playlists": [],
"items": [],
}
)
playlists = Playlist.query.filter(Playlist.id.in_(active_ids)).all()
pl_by_id = {p.id: p for p in playlists}
ordered_playlists = [pl_by_id[x] for x in active_ids if x in pl_by_id]
# Filter playlists by schedule
now_utc = datetime.utcnow()
scheduled = [p for p in playlists if _is_playlist_active_now(p, now_utc)]
# Priority rule:
# If any active (scheduled) playlist is marked priority, only play priority playlists.
any_priority = any(p.is_priority for p in scheduled)
if any_priority:
scheduled = [p for p in scheduled if p.is_priority]
pl_by_id = {p.id: p for p in scheduled}
scheduled_ids = [x for x in active_ids if x in pl_by_id]
ordered_playlists = [pl_by_id[x] for x in scheduled_ids]
# Merge items across active playlists.
if use_mapping:
@@ -186,17 +227,21 @@ def display_playlist(token: str):
PlaylistItem.query.join(DisplayPlaylist, DisplayPlaylist.playlist_id == PlaylistItem.playlist_id)
.filter(
DisplayPlaylist.display_id == display.id,
PlaylistItem.playlist_id.in_(active_ids),
PlaylistItem.playlist_id.in_(scheduled_ids),
)
.order_by(DisplayPlaylist.position.asc(), PlaylistItem.position.asc())
.all()
)
else:
merged = (
PlaylistItem.query.filter(PlaylistItem.playlist_id == active_ids[0])
.order_by(PlaylistItem.position.asc())
.all()
)
# single-playlist fallback; apply schedule filter too.
if scheduled_ids:
merged = (
PlaylistItem.query.filter(PlaylistItem.playlist_id == scheduled_ids[0])
.order_by(PlaylistItem.position.asc())
.all()
)
else:
merged = []
items = []
for item in merged:
@@ -217,6 +262,7 @@ def display_playlist(token: str):
return jsonify(
{
"display": display.name,
"transition": display.transition or "none",
"playlists": [{"id": p.id, "name": p.name} for p in ordered_playlists],
"items": items,
}