102 lines
2.2 KiB
Go
102 lines
2.2 KiB
Go
package web
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/xml"
|
|
"net/url"
|
|
"owl-blogs/app"
|
|
"owl-blogs/app/repository"
|
|
"owl-blogs/domain/model"
|
|
"sort"
|
|
"time"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
)
|
|
|
|
type RSS struct {
|
|
XMLName xml.Name `xml:"rss"`
|
|
Version string `xml:"version,attr"`
|
|
Channel RSSChannel `xml:"channel"`
|
|
}
|
|
|
|
type RSSChannel struct {
|
|
Title string `xml:"title"`
|
|
Link string `xml:"link"`
|
|
Description string `xml:"description"`
|
|
Items []RSSItem `xml:"item"`
|
|
}
|
|
|
|
type RSSItem struct {
|
|
Guid string `xml:"guid"`
|
|
Title string `xml:"title"`
|
|
Link string `xml:"link"`
|
|
PubDate string `xml:"pubDate"`
|
|
Description string `xml:"description"`
|
|
}
|
|
|
|
func RenderRSSFeed(config model.SiteConfig, entries []model.Entry) (string, error) {
|
|
|
|
rss := RSS{
|
|
Version: "2.0",
|
|
Channel: RSSChannel{
|
|
Title: config.Title,
|
|
Link: config.FullUrl,
|
|
Description: config.SubTitle,
|
|
Items: make([]RSSItem, 0),
|
|
},
|
|
}
|
|
|
|
for _, entry := range entries {
|
|
content := entry.Content()
|
|
url, _ := url.JoinPath(config.FullUrl, "/posts/", entry.ID(), "/")
|
|
rss.Channel.Items = append(rss.Channel.Items, RSSItem{
|
|
Guid: url,
|
|
Title: entry.Title(),
|
|
Link: url,
|
|
PubDate: entry.PublishedAt().Format(time.RFC1123Z),
|
|
Description: string(content),
|
|
})
|
|
}
|
|
|
|
buf := new(bytes.Buffer)
|
|
err := xml.NewEncoder(buf).Encode(rss)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return xml.Header + buf.String(), nil
|
|
|
|
}
|
|
|
|
type RSSHandler struct {
|
|
configRepo repository.ConfigRepository
|
|
entrySvc *app.EntryService
|
|
}
|
|
|
|
func NewRSSHandler(entryService *app.EntryService, configRepo repository.ConfigRepository) *RSSHandler {
|
|
return &RSSHandler{entrySvc: entryService, configRepo: configRepo}
|
|
}
|
|
|
|
func (h *RSSHandler) Handle(c *fiber.Ctx) error {
|
|
c.Set(fiber.HeaderContentType, fiber.MIMEApplicationXML)
|
|
|
|
siteConfig := getSiteConfig(h.configRepo)
|
|
|
|
entries, err := h.entrySvc.FindAllByType(&siteConfig.PrimaryListInclude, true, false)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// sort entries by date descending
|
|
sort.Slice(entries, func(i, j int) bool {
|
|
return entries[i].PublishedAt().After(*entries[j].PublishedAt())
|
|
})
|
|
|
|
rss, err := RenderRSSFeed(siteConfig, entries)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return c.SendString(rss)
|
|
}
|