Files
RSS-Feed/manage.php
T
Harwinder Sekhon 41f07b6ad8 Add manual subreddit/YouTube channel configuration (manage.php)
Browser-based feed selection layered on top of config/feeds.php:

- manage.php (password + CSRF gated, session based): add subreddits
  (name / r/name / URL) and YouTube channels (@handle / UC id / URL,
  handle resolved to channel_id once, youtube.com only); enable/disable
  toggles; remove manual feeds; config feeds are hidden, not deleted.
- New feeds are validated with one immediate fetch (bypassing the
  per-refresh host cap): HTTP 404 rejects the entry, 429 keeps it for
  a later refresh. YouTube labels adopt the real channel title.
- feeds table gains origin (config|manual) and enabled columns, with
  a guarded ALTER migration for existing databases.
- Only enabled feeds are refreshed and served: getItems/countItems
  filter by feed_url in enabled feeds, so deselected feeds' cached
  stories are hidden, not deleted; re-adding a URL re-enables it.
- Dashboard header gets a Manage link; manage page styled with the
  existing design tokens; README documents the feature.
2026-10-05 18:58:38 -04:00

72 lines
2.0 KiB
PHP

<?php
declare(strict_types=1);
/**
* Manual feed configuration: sign in, then add/remove/toggle subreddits and
* YouTube channels. POST actions redirect (PRG); results surface as flash.
*/
/** @var array<string, mixed> $app */
$app = require __DIR__ . '/src/bootstrap.php';
$config = $app['config'];
$manager = $app['manager'];
$service = $app['service'];
$auth = new App\ManageAuth($config);
$redirect = static function (): never {
header('Location: manage.php', true, 303);
exit;
};
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$token = is_string($_POST['csrf'] ?? null) ? $_POST['csrf'] : '';
$action = is_string($_POST['action'] ?? null) ? $_POST['action'] : '';
$input = is_string($_POST['input'] ?? null) ? trim($_POST['input']) : '';
$url = is_string($_POST['url'] ?? null) ? trim($_POST['url']) : '';
$enabled = is_string($_POST['enabled'] ?? null) && $_POST['enabled'] === '1';
if (!$auth->enabled() || !$auth->checkCsrf($token)) {
$auth->flash('err', 'Session expired — please try again.');
$redirect();
}
if ($action === 'logout') {
$auth->logout();
$auth->flash('ok', 'Signed out.');
$redirect();
}
if ($action === 'login') {
if (!$auth->login($input)) {
$auth->flash('err', 'Wrong password.');
}
$redirect();
}
$result = $auth->authed() ? match ($action) {
'add_reddit' => $manager->addReddit($input),
'add_youtube' => $manager->addYouTube($input),
'toggle' => $manager->setEnabled($url, $enabled),
'remove' => $manager->remove($url),
default => null,
} : null;
if ($result === null) {
$auth->flash('err', 'Please sign in first.');
} else {
$auth->flash($result['ok'] ? 'ok' : 'err', $result['message']);
}
$redirect();
}
echo App\View::render('manage', [
'config' => $config,
'auth' => $auth,
'feeds' => $auth->authed() ? $service->feedsStatus() : [],
'flash' => $auth->takeFlash(),
]);