- 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>
106 lines
4.6 KiB
PHP
106 lines
4.6 KiB
PHP
<?php
|
|
require __DIR__ . '/../includes/auth.php';
|
|
require __DIR__ . '/../includes/admin_layout.php';
|
|
require __DIR__ . '/../includes/broadcasts.php';
|
|
|
|
$admin = requireAdmin();
|
|
$db = getDB();
|
|
|
|
// e.g. "Friday, October 30 at 7:30pm Eastern (23:30 UTC)"
|
|
function describeScheduledAt(string $utc): string {
|
|
$local = utcToStationTime($utc);
|
|
$text = $local->format('l, F j \a\t g:ia') . ' ' . STATION_TIMEZONE_LABEL . ' (' . substr($utc, 11, 5) . ' UTC';
|
|
if (substr($utc, 0, 10) !== $local->format('Y-m-d')) $text .= ' on ' . (new DateTimeImmutable($utc))->format('l');
|
|
return $text . ')';
|
|
}
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
verifyCsrf();
|
|
$action = $_POST['action'] ?? '';
|
|
|
|
if ($action === 'set_show') {
|
|
$stmt = $db->prepare('SELECT id, name FROM shows WHERE id = ?');
|
|
$stmt->execute([(int)($_POST['show_id'] ?? 0)]);
|
|
$show = $stmt->fetch();
|
|
$date = trim((string)($_POST['date'] ?? ''));
|
|
$time = substr(trim((string)($_POST['time'] ?? '')), 0, 5);
|
|
$scheduledAt = $date === '' && $time === '' ? null : stationTimeToUtc("$date $time");
|
|
if (!$show) {
|
|
flash('Please choose a show.', 'error');
|
|
} elseif (($date !== '' || $time !== '') && $scheduledAt === null) {
|
|
flash('Please enter both a valid date and time, or leave both blank.', 'error');
|
|
} elseif (setBroadcastShow($db, (int)$show['id'], $scheduledAt) === 'live') {
|
|
flash("The live broadcast is now {$show['name']}.");
|
|
} else {
|
|
flash("{$show['name']} is queued" . ($scheduledAt ? ' for ' . describeScheduledAt($scheduledAt) : '')
|
|
. '. It will go live as soon as the stream starts.');
|
|
}
|
|
} elseif ($action === 'clear_queue') {
|
|
clearQueuedShow($db);
|
|
flash('The queued show has been cleared.');
|
|
}
|
|
|
|
header('Location: index.php');
|
|
exit;
|
|
}
|
|
|
|
$live = liveBroadcast($db);
|
|
$current = currentShow($db);
|
|
$shows = $db->query('SELECT id, name FROM shows ORDER BY name')->fetchAll();
|
|
$scheduledLocal = !$live && $current && $current['scheduled_at'] ? utcToStationTime($current['scheduled_at']) : null;
|
|
|
|
adminHeader('Dashboard', $admin);
|
|
?>
|
|
<h3>Broadcast status</h3>
|
|
<p>
|
|
<?php if ($live): ?>
|
|
<strong>Live now</strong><?= $current ? ': ' . e($current['name']) : ' (no show set)' ?>, since <?= e($live['started_at']) ?> UTC.
|
|
<?php elseif ($current): ?>
|
|
Offline. <strong><?= e($current['name']) ?></strong> is queued for the next broadcast<?= $current['scheduled_at'] ? ', scheduled for ' . e(describeScheduledAt($current['scheduled_at'])) : '' ?>.
|
|
<?php else: ?>
|
|
Offline. No show is queued.
|
|
<?php endif; ?>
|
|
</p>
|
|
|
|
<h3><?= $live ? 'Change the live show' : 'Queue the next show' ?></h3>
|
|
<p><?= $live
|
|
? 'Switch which show the live page and recently played list belong to.'
|
|
: 'Choose the show before you start streaming. The broadcast goes live on the site automatically when the stream comes online. The show, and its start time if you enter one, appear on the main page until then.' ?></p>
|
|
<form method="post" action="index.php">
|
|
<?= csrfField() ?>
|
|
<input type="hidden" name="action" value="set_show" />
|
|
<div class="row gtr-uniform gtr-50">
|
|
<div class="<?= $live ? 'col-8' : 'col-12' ?> col-12-small">
|
|
<select name="show_id" aria-label="Show" required>
|
|
<option value="">Choose a show…</option>
|
|
<?php foreach ($shows as $show): ?>
|
|
<option value="<?= (int)$show['id'] ?>"<?= $current && $current['id'] == $show['id'] ? ' selected' : '' ?>><?= e($show['name']) ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<?php if (!$live): ?>
|
|
<div class="col-6 col-12-xsmall">
|
|
<label for="date">Date (optional)</label>
|
|
<input type="date" name="date" id="date" value="<?= $scheduledLocal ? $scheduledLocal->format('Y-m-d') : '' ?>" />
|
|
</div>
|
|
<div class="col-6 col-12-xsmall">
|
|
<label for="time">Start time, <?= e(STATION_TIMEZONE_LABEL) ?> (optional)</label>
|
|
<input type="time" name="time" id="time" value="<?= $scheduledLocal ? $scheduledLocal->format('H:i') : '' ?>" />
|
|
</div>
|
|
<?php endif; ?>
|
|
<div class="<?= $live ? 'col-4' : 'col-12' ?> col-12-small">
|
|
<input type="submit" class="primary<?= $live ? ' fit' : '' ?>" value="<?= $live ? 'Switch show' : 'Queue show' ?>" />
|
|
</div>
|
|
</div>
|
|
</form>
|
|
|
|
<?php if (!$live && $current): ?>
|
|
<form method="post" action="index.php">
|
|
<?= csrfField() ?>
|
|
<input type="hidden" name="action" value="clear_queue" />
|
|
<input type="submit" class="small" value="Clear queued show" />
|
|
</form>
|
|
<?php endif; ?>
|
|
<?php
|
|
adminFooter();
|