Files
radio-free-elsewhere/admin/index.php
T
Daniel MesserandClaude Opus 5.5 f659b09a0b 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>
2026-10-30 09:30:20 -05:00

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();