← Back to docs

RSS Watch

Language: EN | EN | SV

RSS Watch

RSS Watch provides feed browsing, category grouping, and optional AI summaries.

Public Feed Page

  • URL: /feed
  • Browse feeds grouped by category
  • Default Feeds per page is now configurable from /feed-admin (query per_page still overrides per request)
  • Open feed source or category RSS
  • See first and last discovery timestamps
  • View cached AI summaries per category
  • Feeds marked as hidden are intentionally omitted from /feed and use a hash-based direct URL instead, for example /feed/key/{public-hash} and /api/rss/feed/{public-hash}
  • Analytics feeds are now available as dedicated selectors under /api/rss/feed/{selector}:
    • analytics-daily (alias daily-analytics)
    • analytics-weekly (alias weekly-analytics)
    • analytics-monthly (alias monthly-analytics)
    • analytics-yearly (alias yearly-analytics)
    • analytics-bulk (alias bulk-analytics, combines daily/weekly/monthly/yearly)
  • Analytics feed items now link back to related category/site targets when available (/api/rss/feed/{category-slug} for category analytics and /feed/{site-urlid} for site analytics)
  • /feed now includes a mini Ask about all open feeds card where visitors can submit free-form questions against the current open RSS dataset

Feed Q&A and history

  • Submit endpoint: POST /feed/user-questions
  • History page: GET /feed/user-questions
  • Guests must pass Cloudflare Turnstile before submit and are limited by configurable daily/weekly quotas
  • Logged-in users are also quota-limited (higher defaults), with separate configurable daily/weekly limits
  • Admin users are unlimited and bypass Turnstile for this feature
  • Guest intake also has a configurable concurrent protection (distinct active guest IPs in a short processing window)
  • Every question stores timestamp, actor (user_id or guest), IP, user-agent, status, answer/error, and response metadata for audit/history
  • /feed question submit is AJAX-first and renders answer/error inline; standard form post/redirect remains as fallback if JavaScript is unavailable
  • /feed/user-questions now supports pagination with configurable rows-per-page to keep history manageable when question volume grows
  • Admins can now delete question rows from /feed/user-questions via AJAX inline actions (server redirect fallback still works without JavaScript)
  • Admin settings on /feed/user-questions and /feed-admin now also include answer model and answer tone controls for OpenAI question responses
  • Admin history view now includes filters for status, user_id (or guest), ip, and deleted scope (active/deleted/all)
  • Admin moderation now supports both single-row and bulk deletion with explicit delete mode:
    • hard delete removes rows permanently
    • soft delete keeps rows with deletion metadata (deleted_at, deleted_by_user_id, deleted_reason)
  • Soft-deleted rows can now be restored via admin action (POST /feed/user-questions/{question}/restore) for undo workflow.

Entry-level noisy post controls (/feed/entry/{contentId})

  • For admin users, each entry page now includes per-post controls for persistent noisy/cycling links:
    • Mark/unmark cautious mode (auto-purge noisy duplicates on future imports)
    • Ignore this post at import (feed-scoped or global), so incoming scraper reports for the link are dropped
    • Purge noisy duplicates (keeps newest representative per distinct meaningful hash)
    • Purge all except one latest row (hard reset mode)

Analytics Cards on /feed

  • Weekly/monthly/yearly cards are shown per category only when cached analytics exist
  • Cards are color-coded by period
  • Click Read more to expand long analyses
  • Markdown is rendered as HTML for readability

Editor Page

  • URL: /rss
  • Requires permission:rss
  • Manage feed URLs and metadata
  • View cached category analytics
  • Site Type now supports explicit xpath and json flows in addition to rss and wp
  • When sitetype=xpath, elements JSON rules are required and validated server-side before save
  • elements accepts both supported extraction shapes:
    • object format (begin + table) for JSON payload traversal
    • legacy pipeline-array format for HTML/XPath extraction pipelines
  • In the /rss list UI, elements editing is now shown only for xpath rows and uses a collapsible panel with AJAX save on blur
  • New visual helper: /rss/xpath-lab lets editors paste HTML snippets, inspect a DOM outline, run/test XPath queries, and review a SimpleXML-style XML preview before saving rules

Feed Admin

  • URL: /feed-admin
  • Generate daily, weekly, monthly, or yearly category analysis
  • Generate daily, weekly, monthly, or yearly site-level analysis per feed/news source
  • Use the Anchor date calendar to generate for historical periods (for example last week/month/year/day when a cron run was missed)
  • Category cards and site cards now also have optional per-segment Anchor date inputs; precedence is segment anchor -> global anchor -> current date
  • Current period semantics are rolling windows anchored to the selected date (weekly = last 7 days, monthly = last 30 days), while yearly remains year-to-date from the anchor year start
  • Choose model per run
  • Optionally provide "watch for" analyst guidance before generation
  • Existing cached variants now include per-variant actions for Retranslate and Regenerate (replace) (for both category and site analytics)
  • When Regenerate (replace) is used, the currently selected variant/period is overwritten instead of creating an extra duplicate variant
  • Site-level generation now has a dedicated per-site optional title field (separate from the global title input)

Scheduler note

  • Analytics scheduling is now admin-configurable in /feed-admin with per-period enable/disable and time fields for daily, weekly, monthly, and yearly.
  • Cron should run the scheduler check every minute (either via Laravel schedule:run or directly via php artisan rss:run-scheduled-analytics).
  • The scheduler executes each period once per relevant cycle after its configured server time; missed runs are caught up as soon as possible.
  • If a period has no previous scheduler timestamp, it is treated as never-run and is executed immediately once.
  • Automatic scheduler runs use a dedicated auto variant title ([AUTO] Scheduled analytics) and always run with overwrite-current semantics so automatic variants update in place.
  • Manual CLI/API generations are still available when needed.
  • Manual CLI runs now skip unchanged bucket+variant signatures by default to avoid unnecessary repeat AI calls.
  • Use php artisan rss:generate-analytics --period=yearly --force (or --overwrite-current) to explicitly re-run and overwrite the current bucket row even when the underlying snapshot is unchanged.

RSS Maintenance Admin

  • URL: /rss-maintenance-admin
  • Lists suspicious links with unusually many revisions over short windows
  • Compares raw hash churn vs meaningful hash churn to identify noisy pseudo-updates
  • Supports dry-run and live purge per link, keeping the latest representative per meaningful change

Scraper API (/api/rss/urls)

  • Endpoint: GET /api/rss/urls
  • Required query parameter: scraper=1 (otherwise request is rejected)
  • always=0 returns a limited due-set for the calling scraper agent (agent_id, fallback agent_name):
    • Due checks use each URL's readinterval
    • Due checks are evaluated against that agent's own seen-state (last seen + next allowed)
    • One scraper's recent claims no longer block other scraper agents
  • always=1 bypasses interval gating and returns all scrapeable URLs (deleted=0, noscrape=0)
  • Recommended: always send a stable agent_id (for example hostname or worker id)

Subscriptions

Authenticated users can subscribe per:

  • Feed
  • Category

Available channels depend on your account settings.

On /feed/subscriptions, channel settings are now AJAX-first with autosave:

  • Channel checkbox on/off saves immediately via AJAX
  • Text/webhook fields save on blur (when leaving the field)
  • Pause/Resume and Remove also use AJAX inline updates
  • Explicitly unchecking all channels is now supported (all delivery channels disabled)

If JavaScript is unavailable, the same forms still fall back to normal server post/redirect behavior.

Discord setup notes on /feed/subscriptions:

  • You can either paste a Discord webhook URL manually or use Connect Discord app (get webhook).
  • OAuth flow uses webhook.incoming and returns to the app callback (/oauth/discord/callback).
  • Callback URL is shown on the page so admins know what to register in Discord developer settings.
  • After callback, the latest Discord webhook payload is kept in session and can be reused per subscription with one click.

Delivery behavior:

  • New RSS imports now attempt an immediate subscription notification pass right after /api/rss/update converts inbound rows
  • Subscription digests now include a direct Tools entry permalink first (/feed/entry/{contentId}), with the original source URL included as secondary fallback
  • The scheduled rss:notify-subscribers task still runs every 15 minutes as fallback/retry protection if an immediate delivery is missed or a channel fails temporarily