mirror of
https://github.com/juherr/kill-the-news.git
synced 2026-06-20 22:03:48 +00:00
refactor(app): derive native-feed base from EmailAddress.siteBaseUrl
Delete the `iconBase` local helper (which mishandled display-name form like `Name <a@b.com>`) and replace it with `EmailAddress.parse(input.from) ?.siteBaseUrl()` — the domain-layer VO that already handles bare and display-name addresses correctly. Adds TEST C to lock the display-name + relative-href absolutization fix. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1047,4 +1047,28 @@ describe("native feed detection on ingest", () => {
|
|||||||
)) as { nativeFeeds?: Record<string, unknown> };
|
)) as { nativeFeeds?: Record<string, unknown> };
|
||||||
expect(metadata.nativeFeeds).toBeUndefined();
|
expect(metadata.nativeFeeds).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("absolutizes a relative feed href using the display-name sender's domain (TEST C)", async () => {
|
||||||
|
const result = await processEmail(
|
||||||
|
makeInput({
|
||||||
|
from: "Blog Name <news@blog.example.com>",
|
||||||
|
senders: ["news@blog.example.com"],
|
||||||
|
content:
|
||||||
|
'<html><head><link rel="alternate" type="application/atom+xml" href="/atom.xml"></head><body>hi</body></html>',
|
||||||
|
}),
|
||||||
|
env as any,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result.ok).toBe(true);
|
||||||
|
|
||||||
|
const metadata = (await env.EMAIL_STORAGE.get(
|
||||||
|
`feed:${VALID_FEED_ID}:metadata`,
|
||||||
|
"json",
|
||||||
|
)) as {
|
||||||
|
nativeFeeds?: Record<string, Array<{ url: string; type: string }>>;
|
||||||
|
};
|
||||||
|
expect(Object.values(metadata.nativeFeeds!).flat()).toEqual([
|
||||||
|
{ url: "https://blog.example.com/atom.xml", type: "atom" },
|
||||||
|
]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { MailboxId } from "../domain/value-objects/mailbox-id";
|
import { MailboxId } from "../domain/value-objects/mailbox-id";
|
||||||
|
import { EmailAddress } from "../domain/value-objects/email-address";
|
||||||
import { AttachmentData, EmailMetadata, Env } from "../types";
|
import { AttachmentData, EmailMetadata, Env } from "../types";
|
||||||
import { bumpCounters } from "../application/stats";
|
import { bumpCounters } from "../application/stats";
|
||||||
import { dispatchFeedEvents } from "../application/feed-events";
|
import { dispatchFeedEvents } from "../application/feed-events";
|
||||||
@@ -20,13 +21,6 @@ import { Feed } from "../domain/feed.aggregate";
|
|||||||
import { logger } from "../infrastructure/logger";
|
import { logger } from "../infrastructure/logger";
|
||||||
import { FEED_MAX_BYTES } from "../config/constants";
|
import { FEED_MAX_BYTES } from "../config/constants";
|
||||||
|
|
||||||
// Best-effort site base for absolutizing a sender's relative feed link.
|
|
||||||
function iconBase(from: string): string {
|
|
||||||
const at = from.lastIndexOf("@");
|
|
||||||
const domain = at >= 0 ? from.slice(at + 1).trim() : "";
|
|
||||||
return domain ? `https://${domain}` : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RawAttachment {
|
export interface RawAttachment {
|
||||||
filename: string;
|
filename: string;
|
||||||
contentType: string;
|
contentType: string;
|
||||||
@@ -203,7 +197,10 @@ async function storeEmail(
|
|||||||
});
|
});
|
||||||
|
|
||||||
const nativeFeedList = detectNativeFeeds(
|
const nativeFeedList = detectNativeFeeds(
|
||||||
extractFeedLinks(input.content, iconBase(input.from)),
|
extractFeedLinks(
|
||||||
|
input.content,
|
||||||
|
EmailAddress.parse(input.from)?.siteBaseUrl() ?? "",
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
const attachmentBucket = getAttachmentBucket(env);
|
const attachmentBucket = getAttachmentBucket(env);
|
||||||
|
|||||||
Reference in New Issue
Block a user