add atom, rss and json feed support

This commit is contained in:
ngn 2024-04-11 16:07:01 +03:00
parent 2a95341a99
commit 736bc7c4aa
8 changed files with 1201 additions and 83 deletions

View File

@ -5,6 +5,7 @@ import (
"log"
"net/http"
"net/url"
"fmt"
"os"
"strings"
"time"
@ -133,75 +134,7 @@ func GetPost(c *fiber.Ctx) error{
})
}
func GetFeed(c *fiber.Ctx) error{
var posts []Post = []Post{}
rows, err := DB.Query("SELECT * FROM posts")
if util.ErrorCheck(err, c) {
return util.ErrServer(c)
}
for rows.Next() {
var post Post
err := PostFromRow(&post, rows)
if util.ErrorCheck(err, c) {
return util.ErrServer(c)
}
if post.Public == 0 {
continue
}
posts = append(posts, post)
}
rows.Close()
blogurl, err := url.JoinPath(os.Getenv("URL"), "/blog")
if err != nil {
log.Printf("Failed to create the blog URL: %s\n", err.Error())
return c.JSON(fiber.Map{"error": "Server error"})
}
feed := &feeds.Feed{
Title: "[ngn] | blog",
Link: &feeds.Link{Href: blogurl},
Description: "ngn's personal blog",
Author: &feeds.Author{Name: "ngn", Email: "ngn@ngn.tf"},
Created: time.Now(),
}
feed.Items = []*feeds.Item{}
for _, p := range posts {
purl, err := url.JoinPath(blogurl, p.ID)
if err != nil {
log.Printf("Failed to create URL for '%s': %s\n", p.ID, err.Error())
continue
}
parsed, err := time.Parse("02/01/06", p.Date)
if err != nil {
log.Printf("Failed to parse time for '%s': %s\n", p.ID, err.Error())
continue
}
feed.Items = append(feed.Items, &feeds.Item{
Title: p.Title,
Link: &feeds.Link{Href: purl},
Author: &feeds.Author{Name: p.Author},
Created: parsed,
})
}
atom, err := feed.ToAtom()
if err != nil {
log.Printf("Failed to create atom feed: %s", err.Error())
return c.JSON(fiber.Map{"error": "Server error"})
}
c.Set("Content-Type", "application/atom+xml")
return c.Send([]byte(atom))
}
func SumPost(c *fiber.Ctx) error{
var posts []Post = []Post{}
@ -235,3 +168,108 @@ func SumPost(c *fiber.Ctx) error{
"result": posts,
})
}
func GetFeed() (*feeds.Feed, error){
var posts []Post = []Post{}
rows, err := DB.Query("SELECT * FROM posts")
if err != nil {
return nil, err
}
for rows.Next() {
var post Post
err := PostFromRow(&post, rows)
if err != nil {
return nil, err
}
if post.Public == 0 {
continue
}
posts = append(posts, post)
}
rows.Close()
blogurl, err := url.JoinPath(os.Getenv("URL"), "/blog")
if err != nil {
return nil, fmt.Errorf("failed to create the blog URL: %s", err.Error())
}
feed := &feeds.Feed{
Title: "[ngn.tf] | blog",
Link: &feeds.Link{Href: blogurl},
Description: "ngn's personal blog",
Author: &feeds.Author{Name: "ngn", Email: "ngn@ngn.tf"},
Created: time.Now(),
}
feed.Items = []*feeds.Item{}
for _, p := range posts {
purl, err := url.JoinPath(blogurl, p.ID)
if err != nil {
return nil, fmt.Errorf("failed to create URL for '%s': %s\n", p.ID, err.Error())
}
parsed, err := time.Parse("02/01/06", p.Date)
if err != nil {
return nil, fmt.Errorf("failed to parse time for '%s': %s\n", p.ID, err.Error())
}
feed.Items = append(feed.Items, &feeds.Item{
Id: p.ID,
Title: p.Title,
Link: &feeds.Link{Href: purl},
Author: &feeds.Author{Name: p.Author},
Created: parsed,
})
}
return feed, nil
}
func GetAtomFeed(c *fiber.Ctx) error {
feed, err := GetFeed()
if util.ErrorCheck(err, c){
return util.ErrServer(c)
}
atom, err := feed.ToAtom()
if util.ErrorCheck(err, c){
return util.ErrServer(c)
}
c.Set("Content-Type", "application/atom+xml")
return c.Send([]byte(atom))
}
func GetRSSFeed(c *fiber.Ctx) error {
feed, err := GetFeed()
if util.ErrorCheck(err, c){
return util.ErrServer(c)
}
rss, err := feed.ToRss()
if util.ErrorCheck(err, c){
return util.ErrServer(c)
}
c.Set("Content-Type", "application/rss+xml")
return c.Send([]byte(rss))
}
func GetJSONFeed(c *fiber.Ctx) error {
feed, err := GetFeed()
if util.ErrorCheck(err, c){
return util.ErrServer(c)
}
json, err := feed.ToJSON()
if util.ErrorCheck(err, c){
return util.ErrServer(c)
}
c.Set("Content-Type", "application/feed+json")
return c.Send([]byte(json))
}

View File

@ -19,7 +19,9 @@ func Setup(app *fiber.App, db *sql.DB){
})
// blog routes
app.Get("/blog/feed", GetFeed)
app.Get("/blog/feed.atom", GetAtomFeed)
app.Get("/blog/feed.rss", GetRSSFeed)
app.Get("/blog/feed.json", GetJSONFeed)
app.Get("/blog/sum", SumPost)
app.Get("/blog/get", GetPost)
app.Get("/blog/vote/set", VoteSet)

4
app/package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "website",
"version": "4.5.0",
"version": "4.6.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "website",
"version": "4.5.0",
"version": "4.6.0",
"dependencies": {
"@types/dompurify": "^3.0.2",
"dompurify": "^3.1.0",

View File

@ -1,6 +1,6 @@
{
"name": "website",
"version": "4.6.0",
"version": "4.8.0",
"private": true,
"scripts": {
"dev": "vite dev",

View File

@ -78,7 +78,7 @@
</main>
<div class="version">
<p>v4.6</p>
<p>v4.8</p>
</div>
<style>

View File

@ -19,28 +19,81 @@
</Header>
<main>
{#each posts as post}
<CardLink url="/blog/{post.id}" title="{post.title}">
<p>{post.author} | {post.date}</p>
<br>
{post.content}...
</CardLink>
{/each}
<div class="feed-list">
<a href="{import.meta.env.VITE_API_URL_DEV+'/blog/feed.rss'}">
<c><i class="nf nf-fa-rss_square"></i></c> <p>RSS</p>
</a>
<a href="{import.meta.env.VITE_API_URL_DEV+'/blog/feed.atom'}">
<c><i class="nf nf-fae-atom"></i></c> <p>Atom</p>
</a>
<a href="{import.meta.env.VITE_API_URL_DEV+'/blog/feed.json'}">
<c><i class="nf nf-seti-json"></i></c> <p>JSON</p>
</a>
</div>
<div class="post-list">
{#each posts as post}
<CardLink url="/blog/{post.id}" title="{post.title}">
<p>{post.author} | {post.date}</p>
<br>
{post.content}...
</CardLink>
{/each}
</div>
</main>
<style>
main{
.post-list{
display: flex;
flex-direction: column;
gap: 35px;
}
main {
padding: 15%;
padding-top: 50px;
display: flex;
flex-direction: column;
gap: 20px;
}
p {
font-size: 20px;
}
.feed-list{
text-align: right;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
gap: 15px;
}
.feed-list a {
text-decoration: none;
padding: 10px 18px 10px 18px;
background: var(--dark-three);
border-radius: var(--radius);
color: var(--white);
font-size: 20px;
font-weight: 900;
display: flex;
flex-direction: row;
align-items: center;
gap: 7px;
transition: .2s;
}
.feed-list a:hover {
box-shadow: var(--box-shadow);
}
.feed-list a i{
font-size: 21px;
}
@media only screen and (max-width: 1316px) {
main {
padding: 50px;

View File

@ -96,7 +96,7 @@
<meta content="{data.content.substring(0, 100)}..." property="og:description" />
<meta content="https://ngn.tf" property="og:url" />
<meta content="#000000" data-react-helmet="true" name="theme-color" />
<link href="https://files.ngn.tf/markdown.css" rel="stylesheet">
<link href="/markdown.css" rel="stylesheet">
</svelte:head>
<Header>
@ -122,7 +122,9 @@
<div class="content markdown-body">
{@html sanitized}
</div>
</main>
</main>
<style>
p {
font-size: 30px;

1023
app/static/markdown.css Normal file

File diff suppressed because it is too large Load Diff