Show the queued show and its start time in the index.php sidebar
- Shows get a description and an icon upload; broadcasts get a scheduled_at start time. schema.sql adds the columns to existing databases and seeds the descriptions from the old hand-written sidebar. - The dashboard and cli/set_show.php take an optional date and Eastern start time when queuing; index.php shows it with the UTC conversion. - liveBroadcast() and currentShow() ignore broadcasts unseen for longer than the grace period, so a stopped poller can't leave a show stuck as live. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3fb49e816c
commit
f659b09a0b
9 files changed
+297
-77
No files matched your search
+25
-5
@@ -12,11 +12,17 @@ require_once __DIR__ . '/icecast.php';
|
||||
const BROADCAST_GRACE_MINUTES = 5;
|
||||
// Tracks are cleared this long after their broadcast ends
|
||||
const TRACK_RETENTION_MINUTES = 10;
|
||||
// Show times are entered and displayed in the station's time zone; the database stores UTC
|
||||
const STATION_TIMEZONE = 'America/New_York';
|
||||
const STATION_TIMEZONE_LABEL = 'Eastern';
|
||||
|
||||
// A broadcast unseen for longer than the grace period is treated as over even before the poller marks it
|
||||
// ended, so a stopped poller or a long status API outage can't leave a show showing as live.
|
||||
function liveBroadcast(PDO $db): ?array {
|
||||
$row = $db->query(
|
||||
'SELECT * FROM broadcasts
|
||||
WHERE started_at IS NOT NULL AND ended_at IS NULL
|
||||
AND last_seen_at >= NOW() - INTERVAL ' . BROADCAST_GRACE_MINUTES . ' MINUTE
|
||||
ORDER BY started_at DESC LIMIT 1'
|
||||
)->fetch();
|
||||
return $row ?: null;
|
||||
@@ -31,28 +37,42 @@ function pendingBroadcast(PDO $db): ?array {
|
||||
return $row ?: null;
|
||||
}
|
||||
|
||||
// The show for the live broadcast, or the queued one if nothing is live yet
|
||||
// The show for the live broadcast, or the queued one if nothing is live yet,
|
||||
// with the broadcast's scheduled_at and started_at. Stale broadcasts are skipped as in liveBroadcast().
|
||||
function currentShow(PDO $db): ?array {
|
||||
$row = $db->query(
|
||||
'SELECT s.* FROM broadcasts b
|
||||
'SELECT s.*, b.scheduled_at, b.started_at FROM broadcasts b
|
||||
JOIN shows s ON s.id = b.show_id
|
||||
WHERE b.ended_at IS NULL
|
||||
AND (b.started_at IS NULL OR b.last_seen_at >= NOW() - INTERVAL ' . BROADCAST_GRACE_MINUTES . ' MINUTE)
|
||||
ORDER BY b.started_at IS NULL, b.started_at DESC, b.created_at DESC
|
||||
LIMIT 1'
|
||||
)->fetch();
|
||||
return $row ?: null;
|
||||
}
|
||||
|
||||
// Converts a 'YYYY-MM-DD HH:MM' station time to a UTC DATETIME string, or null if it isn't a valid time
|
||||
function stationTimeToUtc(string $local): ?string {
|
||||
$dt = DateTimeImmutable::createFromFormat('!Y-m-d H:i', $local, new DateTimeZone(STATION_TIMEZONE));
|
||||
// Reformatting catches overflowing dates (Feb 30) and times skipped by the DST change
|
||||
if ($dt === false || $dt->format('Y-m-d H:i') !== $local) return null;
|
||||
return $dt->setTimezone(new DateTimeZone('UTC'))->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
function utcToStationTime(string $utc): DateTimeImmutable {
|
||||
return (new DateTimeImmutable($utc, new DateTimeZone('UTC')))->setTimezone(new DateTimeZone(STATION_TIMEZONE));
|
||||
}
|
||||
|
||||
// Assigns a show to the live broadcast, or queues it for the next one if nothing is live.
|
||||
// Returns 'live' or 'queued'.
|
||||
function setBroadcastShow(PDO $db, int $showId): string {
|
||||
// $scheduledAt (UTC) is the advertised start time of a queued show. Returns 'live' or 'queued'.
|
||||
function setBroadcastShow(PDO $db, int $showId, ?string $scheduledAt = null): string {
|
||||
$live = liveBroadcast($db);
|
||||
if ($live !== null) {
|
||||
$db->prepare('UPDATE broadcasts SET show_id = ? WHERE id = ?')->execute([$showId, $live['id']]);
|
||||
return 'live';
|
||||
}
|
||||
clearQueuedShow($db);
|
||||
$db->prepare('INSERT INTO broadcasts (show_id) VALUES (?)')->execute([$showId]);
|
||||
$db->prepare('INSERT INTO broadcasts (show_id, scheduled_at) VALUES (?, ?)')->execute([$showId, $scheduledAt]);
|
||||
return 'queued';
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user