✨ Add post RSS feed
This commit is contained in:
parent
2be8508914
commit
fff10245ea
@ -23,6 +23,7 @@
|
|||||||
"axios": "^1.7.9",
|
"axios": "^1.7.9",
|
||||||
"axios-case-converter": "^1.1.1",
|
"axios-case-converter": "^1.1.1",
|
||||||
"cookies-next": "^5.0.2",
|
"cookies-next": "^5.0.2",
|
||||||
|
"feed": "^4.2.2",
|
||||||
"next": "15.1.3",
|
"next": "15.1.3",
|
||||||
"next-nprogress-bar": "^2.4.3",
|
"next-nprogress-bar": "^2.4.3",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
|
72
src/pages/posts/feed.ts
Normal file
72
src/pages/posts/feed.ts
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import { sni } from '@/services/network'
|
||||||
|
import { SnPost } from '@/services/post'
|
||||||
|
import { GetServerSideProps } from 'next'
|
||||||
|
import { Feed } from 'feed'
|
||||||
|
|
||||||
|
function generateFeed(posts: SnPost[]): string {
|
||||||
|
const feed = new Feed({
|
||||||
|
title: 'Solar Network Posts',
|
||||||
|
description: 'All posts on the Solar Network platform, and now you can view them via the RSS feed!',
|
||||||
|
id: 'https://solsynth.dev/posts',
|
||||||
|
link: 'https://solsynth.dev/posts',
|
||||||
|
favicon: 'https://solsynth.dev/favicon.png',
|
||||||
|
copyright: `All rights reserved ${new Date().getFullYear()} © Solsynth LLC & Post Publishers`,
|
||||||
|
updated: new Date(posts[0].createdAt),
|
||||||
|
generator: 'Capital',
|
||||||
|
feedLinks: {
|
||||||
|
json: 'https://example.com/json',
|
||||||
|
atom: 'https://example.com/atom',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
for (const p of posts) {
|
||||||
|
feed.addItem({
|
||||||
|
id: p.id.toString(),
|
||||||
|
title: p.body.title ?? `Post #${p.id}`,
|
||||||
|
description: p.body.description,
|
||||||
|
link:
|
||||||
|
p.alias && p.aliasPrefix
|
||||||
|
? `https://solsynth.dev/posts/${p.aliasPrefix}/${p.alias}`
|
||||||
|
: `https://solsynth.dev/posts/${p.id}`,
|
||||||
|
content: p.body.content,
|
||||||
|
date: new Date(p.publishedAt ?? p.createdAt),
|
||||||
|
published: new Date(p.publishedAt ?? p.createdAt),
|
||||||
|
copyright: `All right reserved ${new Date().getFullYear()} © @${p.publisher.name}`,
|
||||||
|
author: [
|
||||||
|
{
|
||||||
|
name: `@${p.publisher.name}`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return feed.rss2()
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getServerSideProps: GetServerSideProps = async ({ res, query }) => {
|
||||||
|
let page: number = parseInt(query.page as string)
|
||||||
|
if (isNaN(page)) page = 1
|
||||||
|
|
||||||
|
const countPerPage = 20
|
||||||
|
|
||||||
|
const { data: resp } = await sni.get<{ data: SnPost[] }>('/cgi/co/posts', {
|
||||||
|
params: {
|
||||||
|
take: countPerPage,
|
||||||
|
offset: (page - 1) * countPerPage,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const sitemap = generateFeed(resp.data)
|
||||||
|
|
||||||
|
res.setHeader('Content-Type', 'text/xml')
|
||||||
|
res.write(sitemap)
|
||||||
|
res.end()
|
||||||
|
|
||||||
|
return {
|
||||||
|
props: {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function PostSiteMap() {
|
||||||
|
// getServerSideProps will do the heavy lifting
|
||||||
|
}
|
@ -2,9 +2,20 @@ import { AttachmentItem } from '@/components/attachments/AttachmentItem'
|
|||||||
import { SnAttachment, listAttachment } from '@/services/attachment'
|
import { SnAttachment, listAttachment } from '@/services/attachment'
|
||||||
import { getAttachmentUrl, sni } from '@/services/network'
|
import { getAttachmentUrl, sni } from '@/services/network'
|
||||||
import { SnPost } from '@/services/post'
|
import { SnPost } from '@/services/post'
|
||||||
import { Avatar, Box, Container, Divider, Grid2 as Grid, Pagination, Paper, Typography } from '@mui/material'
|
import {
|
||||||
|
Avatar,
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Container,
|
||||||
|
Divider,
|
||||||
|
Grid2 as Grid,
|
||||||
|
Link,
|
||||||
|
Pagination,
|
||||||
|
Paper,
|
||||||
|
Typography,
|
||||||
|
} from '@mui/material'
|
||||||
import { GetServerSideProps, InferGetServerSidePropsType } from 'next'
|
import { GetServerSideProps, InferGetServerSidePropsType } from 'next'
|
||||||
import Link from 'next/link'
|
import NextLink from 'next/link'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import rehypeSanitize from 'rehype-sanitize'
|
import rehypeSanitize from 'rehype-sanitize'
|
||||||
import rehypeStringify from 'rehype-stringify'
|
import rehypeStringify from 'rehype-stringify'
|
||||||
@ -86,7 +97,7 @@ export default function PostList({ posts, page, pages }: InferGetServerSideProps
|
|||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Link href={`/posts/${p.id}`} passHref>
|
<NextLink href={`/posts/${p.id}`} passHref>
|
||||||
<Box>
|
<Box>
|
||||||
<Box sx={{ mt: 1.5, mb: 1 }} display="flex" flexDirection="column" gap={0.5}>
|
<Box sx={{ mt: 1.5, mb: 1 }} display="flex" flexDirection="column" gap={0.5}>
|
||||||
{(p.body.title || p.body.content) && (
|
{(p.body.title || p.body.content) && (
|
||||||
@ -108,7 +119,7 @@ export default function PostList({ posts, page, pages }: InferGetServerSideProps
|
|||||||
{p.body.content && <div dangerouslySetInnerHTML={{ __html: p.body.content }} />}
|
{p.body.content && <div dangerouslySetInnerHTML={{ __html: p.body.content }} />}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Link>
|
</NextLink>
|
||||||
|
|
||||||
{p.attachments && (
|
{p.attachments && (
|
||||||
<Grid
|
<Grid
|
||||||
@ -131,12 +142,24 @@ export default function PostList({ posts, page, pages }: InferGetServerSideProps
|
|||||||
</Paper>
|
</Paper>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
<Pagination
|
<Box
|
||||||
count={pages}
|
sx={{
|
||||||
page={page}
|
mx: 'auto',
|
||||||
sx={{ mx: 'auto', mb: 5, mt: 3 }}
|
mb: 5,
|
||||||
onChange={(_, page) => router.push('/posts?page=' + page)}
|
mt: 3,
|
||||||
/>
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
justifyContent: 'center',
|
||||||
|
placeItems: 'center',
|
||||||
|
gap: 1.5,
|
||||||
|
textAlign: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Pagination count={pages} page={page} onChange={(_, page) => router.push('/posts?page=' + page)} />
|
||||||
|
<NextLink passHref href="/posts/feed" target="_blank" prefetch={false}>
|
||||||
|
<Link fontSize={13}>RSS Feed</Link>
|
||||||
|
</NextLink>
|
||||||
|
</Box>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user