mirror of
https://github.com/juherr/kill-the-news.git
synced 2026-06-20 22:03:48 +00:00
fix(feed): advertise WebSub hub in RSS/Atom body
Readers like FreshRSS discover the hub from <atom:link rel="hub"> in the feed XML, not the HTTP Link header. Without it they never subscribe and only refresh on cache expiry (~30 min) instead of receiving an instant push when a new email arrives. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,11 @@ verbatim as the GitHub Release notes — so what you write here is what ships.
|
||||
|
||||
### Fixed
|
||||
|
||||
- RSS and Atom feeds now advertise the WebSub hub inside the feed body
|
||||
(`<atom:link rel="hub">`), not just in the HTTP `Link` header. Readers like
|
||||
FreshRSS discover the hub from the XML, so they can now subscribe and receive
|
||||
an instant push when a new email arrives instead of waiting up to the cache
|
||||
`max-age` (30 min) to refresh.
|
||||
- Subscription-confirmation detection now recognises a confirm email whose CTA
|
||||
button carries the subscribe/subscription hint only in its visible text (e.g.
|
||||
"Yes, subscribe me to this mailing list.") over an opaque tracking-redirect
|
||||
|
||||
@@ -130,6 +130,17 @@ describe("generateRssFeed", () => {
|
||||
expect(result).toContain(`${BASE_URL}/rss/${FEED_ID}`);
|
||||
});
|
||||
|
||||
it("advertises the WebSub hub in the RSS body", () => {
|
||||
const result = generateRssFeed(
|
||||
mockFeedConfig,
|
||||
mockEmails,
|
||||
BASE_URL,
|
||||
FEED_ID,
|
||||
);
|
||||
expect(result).toContain('rel="hub"');
|
||||
expect(result).toContain(`${BASE_URL}/hub`);
|
||||
});
|
||||
|
||||
it("includes email entries as <item> elements", () => {
|
||||
const result = generateRssFeed(
|
||||
mockFeedConfig,
|
||||
@@ -280,6 +291,17 @@ describe("generateAtomFeed", () => {
|
||||
expect(result).toContain(`${BASE_URL}/atom/${FEED_ID}`);
|
||||
});
|
||||
|
||||
it("advertises the WebSub hub in the Atom body", () => {
|
||||
const result = generateAtomFeed(
|
||||
mockFeedConfig,
|
||||
mockEmails,
|
||||
BASE_URL,
|
||||
FEED_ID,
|
||||
);
|
||||
expect(result).toContain('rel="hub"');
|
||||
expect(result).toContain(`${BASE_URL}/hub`);
|
||||
});
|
||||
|
||||
it("includes rss alternate link", () => {
|
||||
const result = generateAtomFeed(
|
||||
mockFeedConfig,
|
||||
|
||||
@@ -35,6 +35,10 @@ function buildFeed(
|
||||
// Public "website" for this feed: its own read URL (never the inbound address
|
||||
// or an auth-gated admin path, so the feed output leaks neither).
|
||||
link: `${baseUrl}/rss/${feedId}`,
|
||||
// WebSub hub advertised in the feed body (<atom:link rel="hub">). Readers like
|
||||
// FreshRSS discover the hub here, not from the HTTP Link header, so without it
|
||||
// they never subscribe and only refresh on cache expiry.
|
||||
hub: `${baseUrl}/hub`,
|
||||
language: feedConfig.language,
|
||||
updated: new Date(),
|
||||
generator: "kill-the-news",
|
||||
|
||||
Reference in New Issue
Block a user