diff --git a/src/routes/admin.ts b/src/routes/admin.ts index 62427e0..909b80d 100644 --- a/src/routes/admin.ts +++ b/src/routes/admin.ts @@ -41,11 +41,12 @@ function waitUntilSafe(c: Context, promise: Promise) { } } +function normalizeAllowedSenders(senders: string[]): string[] { + return senders.map((s) => s.trim().toLowerCase()).filter(Boolean); +} + function parseAllowedSenders(rawAllowedSenders: string): string[] { - return rawAllowedSenders - .split(/[\n,]+/) - .map((value) => value.trim().toLowerCase()) - .filter(Boolean); + return normalizeAllowedSenders(rawAllowedSenders.split(/[\n,]+/)); } function clampText(value: string, maxLen: number): string { @@ -1580,7 +1581,7 @@ app.post("/feeds/create", async (c) => { language = String(body.language ?? "en"); view = "list"; 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 { const formData = await c.req.formData(); @@ -1621,14 +1622,11 @@ app.post("/feeds/create", async (c) => { emails: [], }; - // Store feed configuration and metadata - await emailStorage.put(`feed:${feedId}:config`, JSON.stringify(feedConfig)); - await emailStorage.put( - `feed:${feedId}:metadata`, - JSON.stringify(feedMetadata), - ); + await Promise.all([ + emailStorage.put(`feed:${feedId}:config`, JSON.stringify(feedConfig)), + emailStorage.put(`feed:${feedId}:metadata`, JSON.stringify(feedMetadata)), + ]); - // Add feed to the list of all feeds await addFeedToList( emailStorage, feedId, diff --git a/src/routes/entries.ts b/src/routes/entries.ts index 2c221ed..8cefaf1 100644 --- a/src/routes/entries.ts +++ b/src/routes/entries.ts @@ -1,13 +1,6 @@ import { Context } from "hono"; import { Env, FeedMetadata, EmailData } from "../types"; - -function escapeHtml(str: string): string { - return str - .replace(/&/g, "&") - .replace(//g, ">") - .replace(/"/g, """); -} +import { escapeHtml } from "../utils/html"; export async function handle(c: Context): Promise { const env = c.env as unknown as Env; diff --git a/src/utils/feed-generator.ts b/src/utils/feed-generator.ts index aa5f22c..50bda90 100644 --- a/src/utils/feed-generator.ts +++ b/src/utils/feed-generator.ts @@ -13,16 +13,12 @@ function parseFromAddress(from: string): { name: string; email?: string } { return { name: from.trim() }; } -/** - * Generate an RSS feed from a list of emails - */ export function generateRssFeed( feedConfig: FeedConfig, emails: EmailData[], baseUrl: string, - feedId?: string, + feedId: string, ): string { - // Create a new feed const feed = new Feed({ title: feedConfig.title, description: feedConfig.description || "", @@ -43,25 +39,18 @@ export function generateRssFeed( : undefined, }); - // Add each email as a feed item 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 entryLink = feedId - ? `${baseUrl}/entries/${feedId}/${email.receivedAt}` - : `${baseUrl}/emails/${uniqueId}`; - feed.addItem({ title: email.subject, id: uniqueId, - link: entryLink, + link: `${baseUrl}/entries/${feedId}/${email.receivedAt}`, description: email.content, content: email.content, author: [parseFromAddress(email.from)], - date: date, + date: new Date(email.receivedAt), }); } - // Return the RSS feed as XML return feed.rss2(); } diff --git a/src/utils/html.ts b/src/utils/html.ts new file mode 100644 index 0000000..62b0389 --- /dev/null +++ b/src/utils/html.ts @@ -0,0 +1,7 @@ +export function escapeHtml(str: string): string { + return str + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """); +}