mirror of
https://github.com/juherr/kill-the-news.git
synced 2026-06-21 06:13:48 +00:00
refactor: simplify quick-win code after review
- Make feedId required in generateRssFeed (removes dead /emails/ fallback) - Hoist loop-invariant conditional and remove intermediate variable - Extract normalizeAllowedSenders() so JSON and form paths share same logic - Move escapeHtml to src/utils/html.ts for reuse by admin.ts - Parallelize the two independent KV puts in feed creation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+10
-12
@@ -41,11 +41,12 @@ function waitUntilSafe(c: Context, promise: Promise<unknown>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeAllowedSenders(senders: string[]): string[] {
|
||||||
|
return senders.map((s) => s.trim().toLowerCase()).filter(Boolean);
|
||||||
|
}
|
||||||
|
|
||||||
function parseAllowedSenders(rawAllowedSenders: string): string[] {
|
function parseAllowedSenders(rawAllowedSenders: string): string[] {
|
||||||
return rawAllowedSenders
|
return normalizeAllowedSenders(rawAllowedSenders.split(/[\n,]+/));
|
||||||
.split(/[\n,]+/)
|
|
||||||
.map((value) => value.trim().toLowerCase())
|
|
||||||
.filter(Boolean);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function clampText(value: string, maxLen: number): string {
|
function clampText(value: string, maxLen: number): string {
|
||||||
@@ -1580,7 +1581,7 @@ app.post("/feeds/create", async (c) => {
|
|||||||
language = String(body.language ?? "en");
|
language = String(body.language ?? "en");
|
||||||
view = "list";
|
view = "list";
|
||||||
allowedSenders = Array.isArray(body.allowedSenders)
|
allowedSenders = Array.isArray(body.allowedSenders)
|
||||||
? (body.allowedSenders as unknown[]).map(String).map((s) => s.trim().toLowerCase()).filter(Boolean)
|
? normalizeAllowedSenders((body.allowedSenders as unknown[]).map(String))
|
||||||
: [];
|
: [];
|
||||||
} else {
|
} else {
|
||||||
const formData = await c.req.formData();
|
const formData = await c.req.formData();
|
||||||
@@ -1621,14 +1622,11 @@ app.post("/feeds/create", async (c) => {
|
|||||||
emails: [],
|
emails: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
// Store feed configuration and metadata
|
await Promise.all([
|
||||||
await emailStorage.put(`feed:${feedId}:config`, JSON.stringify(feedConfig));
|
emailStorage.put(`feed:${feedId}:config`, JSON.stringify(feedConfig)),
|
||||||
await emailStorage.put(
|
emailStorage.put(`feed:${feedId}:metadata`, JSON.stringify(feedMetadata)),
|
||||||
`feed:${feedId}:metadata`,
|
]);
|
||||||
JSON.stringify(feedMetadata),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add feed to the list of all feeds
|
|
||||||
await addFeedToList(
|
await addFeedToList(
|
||||||
emailStorage,
|
emailStorage,
|
||||||
feedId,
|
feedId,
|
||||||
|
|||||||
@@ -1,13 +1,6 @@
|
|||||||
import { Context } from "hono";
|
import { Context } from "hono";
|
||||||
import { Env, FeedMetadata, EmailData } from "../types";
|
import { Env, FeedMetadata, EmailData } from "../types";
|
||||||
|
import { escapeHtml } from "../utils/html";
|
||||||
function escapeHtml(str: string): string {
|
|
||||||
return str
|
|
||||||
.replace(/&/g, "&")
|
|
||||||
.replace(/</g, "<")
|
|
||||||
.replace(/>/g, ">")
|
|
||||||
.replace(/"/g, """);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function handle(c: Context): Promise<Response> {
|
export async function handle(c: Context): Promise<Response> {
|
||||||
const env = c.env as unknown as Env;
|
const env = c.env as unknown as Env;
|
||||||
|
|||||||
@@ -13,16 +13,12 @@ function parseFromAddress(from: string): { name: string; email?: string } {
|
|||||||
return { name: from.trim() };
|
return { name: from.trim() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate an RSS feed from a list of emails
|
|
||||||
*/
|
|
||||||
export function generateRssFeed(
|
export function generateRssFeed(
|
||||||
feedConfig: FeedConfig,
|
feedConfig: FeedConfig,
|
||||||
emails: EmailData[],
|
emails: EmailData[],
|
||||||
baseUrl: string,
|
baseUrl: string,
|
||||||
feedId?: string,
|
feedId: string,
|
||||||
): string {
|
): string {
|
||||||
// Create a new feed
|
|
||||||
const feed = new Feed({
|
const feed = new Feed({
|
||||||
title: feedConfig.title,
|
title: feedConfig.title,
|
||||||
description: feedConfig.description || "",
|
description: feedConfig.description || "",
|
||||||
@@ -43,25 +39,18 @@ export function generateRssFeed(
|
|||||||
: undefined,
|
: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add each email as a feed item
|
|
||||||
for (const email of emails) {
|
for (const email of emails) {
|
||||||
const date = new Date(email.receivedAt);
|
|
||||||
const uniqueId = `${email.receivedAt}-${Buffer.from(email.subject).toString("base64").substring(0, 10)}`;
|
const uniqueId = `${email.receivedAt}-${Buffer.from(email.subject).toString("base64").substring(0, 10)}`;
|
||||||
const entryLink = feedId
|
|
||||||
? `${baseUrl}/entries/${feedId}/${email.receivedAt}`
|
|
||||||
: `${baseUrl}/emails/${uniqueId}`;
|
|
||||||
|
|
||||||
feed.addItem({
|
feed.addItem({
|
||||||
title: email.subject,
|
title: email.subject,
|
||||||
id: uniqueId,
|
id: uniqueId,
|
||||||
link: entryLink,
|
link: `${baseUrl}/entries/${feedId}/${email.receivedAt}`,
|
||||||
description: email.content,
|
description: email.content,
|
||||||
content: email.content,
|
content: email.content,
|
||||||
author: [parseFromAddress(email.from)],
|
author: [parseFromAddress(email.from)],
|
||||||
date: date,
|
date: new Date(email.receivedAt),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the RSS feed as XML
|
|
||||||
return feed.rss2();
|
return feed.rss2();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
export function escapeHtml(str: string): string {
|
||||||
|
return str
|
||||||
|
.replace(/&/g, "&")
|
||||||
|
.replace(/</g, "<")
|
||||||
|
.replace(/>/g, ">")
|
||||||
|
.replace(/"/g, """);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user