0250355dcd
- GET /rss.xml 输出 RSS 2.0(已发布文章,SUNDYNIX_SITE_URL 可配) - vite 代理补 /rss.xml,页脚 RSS 链接生效 - README:结构、开发流程、环境变量、后端规范、API 速览 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
89 lines
2.1 KiB
Go
89 lines
2.1 KiB
Go
package handler
|
|
|
|
import (
|
|
"encoding/xml"
|
|
"net/http"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"gorm.io/gorm"
|
|
|
|
"git.sundynix.cn/Blizzard/sundynix-site/server/internal/model"
|
|
)
|
|
|
|
// RSSHandler 输出博客的 RSS 2.0 订阅源。
|
|
type RSSHandler struct {
|
|
db *gorm.DB
|
|
siteURL string
|
|
}
|
|
|
|
func NewRSSHandler(db *gorm.DB) *RSSHandler {
|
|
siteURL := os.Getenv("SUNDYNIX_SITE_URL")
|
|
if siteURL == "" {
|
|
siteURL = "https://sundynix.com"
|
|
}
|
|
return &RSSHandler{db: db, siteURL: siteURL}
|
|
}
|
|
|
|
type rssItem struct {
|
|
Title string `xml:"title"`
|
|
Link string `xml:"link"`
|
|
GUID string `xml:"guid"`
|
|
Description string `xml:"description"`
|
|
Category string `xml:"category,omitempty"`
|
|
PubDate string `xml:"pubDate"`
|
|
}
|
|
|
|
type rssFeed struct {
|
|
XMLName xml.Name `xml:"rss"`
|
|
Version string `xml:"version,attr"`
|
|
Channel struct {
|
|
Title string `xml:"title"`
|
|
Link string `xml:"link"`
|
|
Description string `xml:"description"`
|
|
Language string `xml:"language"`
|
|
Items []rssItem `xml:"item"`
|
|
} `xml:"channel"`
|
|
}
|
|
|
|
// Feed GET /rss.xml
|
|
func (h *RSSHandler) Feed(c *gin.Context) {
|
|
var posts []model.PostListItem
|
|
err := h.db.Model(&model.Post{}).
|
|
Where("published_at IS NOT NULL").
|
|
Order("published_at DESC").
|
|
Limit(50).
|
|
Find(&posts).Error
|
|
if err != nil {
|
|
c.String(http.StatusInternalServerError, "feed unavailable")
|
|
return
|
|
}
|
|
|
|
feed := rssFeed{Version: "2.0"}
|
|
feed.Channel.Title = "sundynix agentix 博客"
|
|
feed.Channel.Link = h.siteURL + "/blog"
|
|
feed.Channel.Description = "事件驱动的 AI Agent 工作台 — 发布日志与工程笔记"
|
|
feed.Channel.Language = "zh-cn"
|
|
for _, p := range posts {
|
|
link := h.siteURL + "/blog/" + p.Slug
|
|
item := rssItem{
|
|
Title: p.Title,
|
|
Link: link,
|
|
GUID: link,
|
|
Description: p.Summary,
|
|
Category: p.Category,
|
|
}
|
|
if p.PublishedAt != nil {
|
|
item.PubDate = p.PublishedAt.Format(time.RFC1123Z)
|
|
}
|
|
feed.Channel.Items = append(feed.Channel.Items, item)
|
|
}
|
|
|
|
c.Header("Content-Type", "application/rss+xml; charset=utf-8")
|
|
c.String(http.StatusOK, xml.Header)
|
|
if out, err := xml.MarshalIndent(feed, "", " "); err == nil {
|
|
c.Writer.Write(out)
|
|
}
|
|
}
|