From 7c4f4f10fcd327d6e6abda14ddaf61a0e108fd47 Mon Sep 17 00:00:00 2001 From: xing Date: Fri, 7 Oct 2022 22:27:34 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84post=20feed=E5=8F=8A=E5=8A=A0?= =?UTF-8?q?=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- actions/feed.go | 152 ++++++++++++++++++++++++++++++++++++++---------- cache/map.go | 8 +++ main.go | 3 +- route/route.go | 3 +- rss2/rss2.go | 26 +++++++-- 5 files changed, 153 insertions(+), 39 deletions(-) diff --git a/actions/feed.go b/actions/feed.go index 484d3bb..c8a6a5b 100644 --- a/actions/feed.go +++ b/actions/feed.go @@ -6,24 +6,32 @@ import ( "github/fthvgb1/wp-go/actions/common" "github/fthvgb1/wp-go/cache" "github/fthvgb1/wp-go/helper" + "github/fthvgb1/wp-go/logs" "github/fthvgb1/wp-go/models" "github/fthvgb1/wp-go/plugins" "github/fthvgb1/wp-go/rss2" "net/http" + "strconv" "strings" "time" ) var feedCache = cache.NewSliceCache[string](feed, time.Hour) +var postFeedCache = cache.NewMapCacheByFn[string, string](postFeed, time.Hour) var tmp = "Mon, 02 Jan 2006 15:04:05 GMT" +var templateRss rss2.Rss2 -func FeedCached(c *gin.Context) { - if !isCacheExpired(c, feedCache.SetTime()) { - c.Status(http.StatusNotModified) - c.Abort() - return +func InitFeed() { + templateRss = rss2.Rss2{ + Title: models.Options["blogname"], + AtomLink: fmt.Sprintf("%s/feed", models.Options["home"]), + Link: models.Options["siteurl"], + Description: models.Options["blogdescription"], + Language: "zh-CN", + UpdatePeriod: "hourly", + UpdateFrequency: 1, + Generator: models.Options["home"], } - c.Next() } func isCacheExpired(c *gin.Context, lastTime time.Time) bool { @@ -41,19 +49,11 @@ func isCacheExpired(c *gin.Context, lastTime time.Time) bool { } func Feed(c *gin.Context) { - s, err := feedCache.GetCache(c, time.Second, c) - if err != nil { - c.Status(http.StatusInternalServerError) - c.Abort() - c.Error(err) - return + if !isCacheExpired(c, feedCache.SetTime()) { + c.Status(http.StatusNotModified) + } else { + setFeed(feedCache, c) } - lastTimeGMT := feedCache.SetTime().Format(tmp) - eTag := helper.StringMd5(lastTimeGMT) - c.Header("Content-Type", "application/rss+xml; charset=UTF-8") - c.Header("Last-Modified", lastTimeGMT) - c.Header("ETag", eTag) - c.String(http.StatusOK, s[0]) } func feed(arg ...any) (xml []string, err error) { @@ -66,19 +66,8 @@ func feed(arg ...any) (xml []string, err error) { if err != nil { return } - rs := rss2.Rss2{ - Title: models.Options["blogname"], - AtomLink: fmt.Sprintf("%s/feed", models.Options["home"]), - Link: models.Options["siteurl"], - Description: models.Options["blogdescription"], - LastBuildDate: time.Now().Format(time.RFC1123Z), - Language: "zh-CN", - UpdatePeriod: "hourly", - UpdateFrequency: 1, - Generator: models.Options["home"], - Items: nil, - } - + rs := templateRss + rs.LastBuildDate = time.Now().Format(time.RFC1123Z) rs.Items = helper.SliceMap(posts, func(t models.WpPosts) rss2.Item { desc := "无法提供摘要。这是一篇受保护的文章。" common.PasswordProjectTitle(&t) @@ -112,3 +101,104 @@ func feed(arg ...any) (xml []string, err error) { xml = []string{rs.GetXML()} return } + +func setFeed(sliceCache *cache.SliceCache[string], c *gin.Context) { + s, err := sliceCache.GetCache(c, time.Second, c) + if err != nil { + c.Status(http.StatusInternalServerError) + c.Abort() + c.Error(err) + return + } + lastTimeGMT := sliceCache.SetTime().Format(tmp) + eTag := helper.StringMd5(lastTimeGMT) + c.Header("Content-Type", "application/rss+xml; charset=UTF-8") + c.Header("Last-Modified", lastTimeGMT) + c.Header("ETag", eTag) + c.String(http.StatusOK, s[0]) +} + +func PostFeed(c *gin.Context) { + id := c.Param("id") + if !isCacheExpired(c, postFeedCache.GetSetTime(id)) { + c.Status(http.StatusNotModified) + } else { + s, err := postFeedCache.GetCache(c, id, time.Second, c, id) + if err != nil { + c.Status(http.StatusInternalServerError) + c.Abort() + c.Error(err) + return + } + lastTimeGMT := postFeedCache.GetSetTime(id).Format(tmp) + eTag := helper.StringMd5(lastTimeGMT) + c.Header("Content-Type", "application/rss+xml; charset=UTF-8") + c.Header("Last-Modified", lastTimeGMT) + c.Header("ETag", eTag) + c.String(http.StatusOK, s) + } +} + +func postFeed(arg ...any) (x string, err error) { + c := arg[0].(*gin.Context) + id := arg[1].(string) + Id := 0 + if id != "" { + Id, err = strconv.Atoi(id) + if err != nil { + return + } + } + ID := uint64(Id) + maxId, err := common.GetMaxPostId(c) + logs.ErrPrintln(err, "get max post id") + if ID > maxId || err != nil { + return + } + post, err := common.GetPostAndCache(c, ID) + if post.Id == 0 || err != nil { + return + } + common.PasswordProjectTitle(&post) + comments, err := common.PostComments(c, post.Id) + if err != nil { + return + } + rs := templateRss + + rs.Title = fmt.Sprintf("《%s》的评论", post.PostTitle) + rs.AtomLink = fmt.Sprintf("%s/p/%d/feed", models.Options["siteurl"], post.Id) + rs.Link = fmt.Sprintf("%s/p/%d", models.Options["siteurl"], post.Id) + rs.LastBuildDate = time.Now().Format(time.RFC1123Z) + if post.PostPassword != "" { + if len(comments) > 0 { + common.PasswdProjectContent(&post) + t := comments[len(comments)-1] + rs.Items = []rss2.Item{ + { + Title: fmt.Sprintf("评价者:%s", t.CommentAuthor), + Link: fmt.Sprintf("%s/p/%d#comment-%d", models.Options["siteurl"], post.Id, t.CommentId), + Creator: t.CommentAuthor, + PubDate: t.CommentDateGmt.Format(time.RFC1123Z), + Guid: fmt.Sprintf("%s#comment-%d", post.Guid, t.CommentId), + Description: "评论受保护:要查看请输入密码。", + Content: post.PostContent, + }, + } + } + } else { + rs.Items = helper.SliceMap(comments, func(t models.WpComments) rss2.Item { + return rss2.Item{ + Title: fmt.Sprintf("评价者:%s", t.CommentAuthor), + Link: fmt.Sprintf("%s/p/%d#comment-%d", models.Options["siteurl"], post.Id, t.CommentId), + Creator: t.CommentAuthor, + PubDate: t.CommentDateGmt.Format(time.RFC1123Z), + Guid: fmt.Sprintf("%s#comment-%d", post.Guid, t.CommentId), + Content: t.CommentContent, + } + }) + } + + x = rs.GetXML() + return +} diff --git a/cache/map.go b/cache/map.go index e570dd3..afab49f 100644 --- a/cache/map.go +++ b/cache/map.go @@ -30,6 +30,14 @@ func (m *MapCache[K, V]) SetCacheFunc(fn func(...any) (V, error)) { m.setCacheFunc = fn } +func (m *MapCache[K, V]) GetSetTime(k K) (t time.Time) { + r, ok := m.data[k] + if ok { + t = r.setTime + } + return +} + func (m *MapCache[K, V]) SetCacheBatchFunc(fn func(...any) (map[K]V, error)) { m.setBatchCacheFn = fn } diff --git a/main.go b/main.go index 4d1ea81..5324184 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "github/fthvgb1/wp-go/actions" "github/fthvgb1/wp-go/actions/common" "github/fthvgb1/wp-go/db" "github/fthvgb1/wp-go/models" @@ -30,7 +31,7 @@ func init() { if err != nil { panic(err) } - + actions.InitFeed() common.InitActionsCommonCache() plugins.InitDigestCache() go cronClearCache() diff --git a/route/route.go b/route/route.go index 371b0b4..436f15c 100644 --- a/route/route.go +++ b/route/route.go @@ -52,7 +52,8 @@ func SetupRouter() *gin.Engine { r.GET("/p/date/:year/:month/page/:page", actions.Index) r.POST("/login", actions.Login) r.GET("/p/:id", actions.Detail) - r.GET("/feed", actions.FeedCached, actions.Feed) + r.GET("/p/:id/feed", actions.PostFeed) + r.GET("/feed", actions.Feed) if helper.IsContainInArr(gin.Mode(), []string{gin.DebugMode, gin.TestMode}) { pprof.Register(r, "dev/pprof") } diff --git a/rss2/rss2.go b/rss2/rss2.go index 26ad662..1120427 100644 --- a/rss2/rss2.go +++ b/rss2/rss2.go @@ -42,9 +42,9 @@ var templateItems = ` {$comments} {$pubDate} - + {$category} {$guid} - + {$description} {$commentRss} {$commentNumber} @@ -105,12 +105,12 @@ func (i Item) GetXml() (xml string) { for k, v := range map[string]string{ "{$title}": i.Title, "{$link}": i.Link, - "{$comments}": i.GetComments(), + "{$comments}": i.getComments(), "{$author}": i.Creator, "{$pubDate}": i.PubDate, - "{$category}": i.Category, + "{$category}": i.getCategory(), "{$guid}": i.Guid, - "{$description}": i.Description, + "{$description}": i.getDescription(), "{$content}": i.Content, "{$commentRss}": i.getCommentRss(), "{$commentNumber}": i.getSlashComments(), @@ -120,7 +120,21 @@ func (i Item) GetXml() (xml string) { return } -func (i Item) GetComments() string { +func (i Item) getCategory() string { + r := "" + if i.Category != "" { + r = fmt.Sprintf("", i.CommentLink) + } + return r +} +func (i Item) getDescription() string { + r := "" + if i.Description != "" { + r = fmt.Sprintf("", i.Description) + } + return r +} +func (i Item) getComments() string { r := "" if i.CommentLink != "" { r = fmt.Sprintf("%s", i.CommentLink)