✨ Add post RSS feed
This commit is contained in:
		| @@ -23,6 +23,7 @@ | ||||
|     "axios": "^1.7.9", | ||||
|     "axios-case-converter": "^1.1.1", | ||||
|     "cookies-next": "^5.0.2", | ||||
|     "feed": "^4.2.2", | ||||
|     "next": "15.1.3", | ||||
|     "next-nprogress-bar": "^2.4.3", | ||||
|     "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 { getAttachmentUrl, sni } from '@/services/network' | ||||
| 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 Link from 'next/link' | ||||
| import NextLink from 'next/link' | ||||
| import { useRouter } from 'next/router' | ||||
| import rehypeSanitize from 'rehype-sanitize' | ||||
| import rehypeStringify from 'rehype-stringify' | ||||
| @@ -86,7 +97,7 @@ export default function PostList({ posts, page, pages }: InferGetServerSideProps | ||||
|             </Box> | ||||
|           </Box> | ||||
|  | ||||
|           <Link href={`/posts/${p.id}`} passHref> | ||||
|           <NextLink href={`/posts/${p.id}`} passHref> | ||||
|             <Box> | ||||
|               <Box sx={{ mt: 1.5, mb: 1 }} display="flex" flexDirection="column" gap={0.5}> | ||||
|                 {(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 }} />} | ||||
|               </Box> | ||||
|             </Box> | ||||
|           </Link> | ||||
|           </NextLink> | ||||
|  | ||||
|           {p.attachments && ( | ||||
|             <Grid | ||||
| @@ -131,12 +142,24 @@ export default function PostList({ posts, page, pages }: InferGetServerSideProps | ||||
|         </Paper> | ||||
|       ))} | ||||
|  | ||||
|       <Pagination | ||||
|         count={pages} | ||||
|         page={page} | ||||
|         sx={{ mx: 'auto', mb: 5, mt: 3 }} | ||||
|         onChange={(_, page) => router.push('/posts?page=' + page)} | ||||
|       /> | ||||
|       <Box | ||||
|         sx={{ | ||||
|           mx: 'auto', | ||||
|           mb: 5, | ||||
|           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> | ||||
|   ) | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user