Refine feed formatting

This commit is contained in:
Sam Becker 2025-06-12 19:04:42 -05:00
parent 4dc9149931
commit 099fcdec8b
2 changed files with 46 additions and 56 deletions

View File

@ -1,4 +1,3 @@
import { INFINITE_SCROLL_FEED_INITIAL } from '@/photo';
import { getPhotosCached } from '@/photo/cache';
import {
BASE_URL,
@ -6,40 +5,39 @@ import {
META_TITLE,
SITE_FEEDS_ENABLED,
} from '@/app/config';
import { feedPhotoToXml, formatPhotoForFeedRss } from '@/app/feed';
import { ABSOLUTE_PATH_FOR_FEED_JSON } from '@/app/paths';
import { createRssItems, FEED_PHOTO_REQUEST_LIMIT } from '@/app/feed';
import { ABSOLUTE_PATH_FOR_RSS_XML } from '@/app/paths';
export const dynamic = 'force-static';
export async function GET() {
if (SITE_FEEDS_ENABLED) {
const photos = await getPhotosCached({
limit: INFINITE_SCROLL_FEED_INITIAL,
limit: FEED_PHOTO_REQUEST_LIMIT,
sortBy: 'createdAt',
});
const items = photos.map(formatPhotoForFeedRss).map(feedPhotoToXml);
return new Response(
`<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:media="http://search.yahoo.com/mrss/">
const items = createRssItems(photos);
<channel>
<title>${META_TITLE}</title>
<atom:link href="${ABSOLUTE_PATH_FOR_FEED_JSON}"
rel="self" type="application/rss+xml" />
<link>${BASE_URL}</link>
<description>${META_DESCRIPTION}</description>
${items.join('\n')}
</channel>
</rss>`,
{
headers: {
'Content-Type': 'text/xml',
},
},
return new Response(`
<?xml version="1.0" encoding="UTF-8"?>
<rss
version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:media="http://search.yahoo.com/mrss/"
>
<channel>
<title>${META_TITLE}</title>
<atom:link href="${ABSOLUTE_PATH_FOR_RSS_XML}"
rel="self" type="application/rss+xml" />
<link>${BASE_URL}</link>
<description>${META_DESCRIPTION}</description>
${items.join('\n')}
</channel>
</rss>
`,
{ headers: { 'Content-Type': 'text/xml' } },
);
} else {
return new Response('RSS feed access disabled', { status: 404 });

View File

@ -12,22 +12,6 @@ export const FEED_PHOTO_WIDTH_SMALL = 200;
export const FEED_PHOTO_WIDTH_MEDIUM = 640;
export const FEED_PHOTO_WIDTH_LARGE = 1200;
export interface PublicFeedJson {
meta: {
title: string
url: string
}
photos: PublicFeedPhotoJson[]
}
export interface PublicFeedRss {
meta: {
title: string
url: string
}
photos: PublicFeedPhotoRss[]
}
interface PublicFeedMedia {
url: string
width: number
@ -42,10 +26,7 @@ interface PublicFeedPhotoJson {
model?: string
tags?: string[]
takenAtNaive: string
src: Record<
'small' | 'medium' | 'large',
PublicFeedMedia
>
src: Record<'small' | 'medium' | 'large', PublicFeedMedia>
}
interface PublicFeedPhotoRss {
@ -54,10 +35,15 @@ interface PublicFeedPhotoRss {
description?: string
link: string
publicationDate: Date
media: Record<
'content' | 'thumb',
PublicFeedMedia
>
media: Record<'content' | 'thumb', PublicFeedMedia>
}
export interface PublicFeedJson {
meta: {
title: string
url: string
}
photos: PublicFeedPhotoJson[]
}
const generateFeedMedia = (
@ -89,7 +75,7 @@ export const formatPhotoForFeedJson = (photo: Photo): PublicFeedPhotoJson => ({
},
});
export const formatPhotoForFeedRss = (photo: Photo): PublicFeedPhotoRss => ({
const formatPhotoForFeedRss = (photo: Photo): PublicFeedPhotoRss => ({
...getCoreFeedFields(photo),
link: absolutePathForPhoto({ photo }),
publicationDate: photo.createdAt,
@ -99,7 +85,7 @@ export const formatPhotoForFeedRss = (photo: Photo): PublicFeedPhotoRss => ({
},
});
export const feedPhotoToXml = (photo: PublicFeedPhotoRss): string => {
const feedPhotoToXml = (photo: PublicFeedPhotoRss): string => {
const formattedDate = formatDate({
date: photo.publicationDate,
length: 'rss',
@ -112,14 +98,20 @@ export const feedPhotoToXml = (photo: PublicFeedPhotoRss): string => {
<description>
<![CDATA[${photo.description}]]>
</description>
<media:content url="${photo.media.content.url.replace(/&/g, '&amp;')}"
<media:content url="<![CDATA[${photo.media.content.url}]]>"
type="image/jpeg"
medium="image"
width="${photo.media.content.width}"
height="${photo.media.content.height}">
<media:thumbnail url="${photo.media.thumb.url.replace(/&/g, '&amp;')}"
width="${photo.media.thumb.width}"
height="${photo.media.thumb.height}" />
height="${photo.media.content.height}"
>
<media:thumbnail
url="<![CDATA[${photo.media.thumb.url}]]>"
width="${photo.media.thumb.width}"
height="${photo.media.thumb.height}"
/>
</media:content>
</item>`;
};
export const createRssItems = (photos: Photo[]) =>
photos.map(formatPhotoForFeedRss).map(feedPhotoToXml);