1
mirror of https://github.com/jlelse/GoBlog synced 2024-07-15 11:02:58 +00:00

Show feed descriptions on blogroll, add option to manually refresh blogroll

This commit is contained in:
Jan-Lukas Else 2024-05-31 10:08:19 +02:00
parent 4009ef3aad
commit 1f472243e9
4 changed files with 60 additions and 26 deletions

View File

@ -17,7 +17,19 @@ import (
"go.goblog.app/app/pkgs/contenttype"
)
const defaultBlogrollPath = "/blogroll"
const (
defaultBlogrollPath = "/blogroll"
blogrollRefreshSubpath = "/refresh"
blogrollDownloadFile = ".opml"
)
func (bc *configBlog) getBlogrollPath() (bool, string) {
if blogroll := bc.Blogroll; blogroll != nil && blogroll.Enabled {
path := bc.getRelativePath(cmp.Or(blogroll.Path, defaultBlogrollPath))
return true, path
}
return false, ""
}
func (a *goBlog) serveBlogroll(w http.ResponseWriter, r *http.Request) {
blog, bc := a.getBlog(r)
@ -30,14 +42,15 @@ func (a *goBlog) serveBlogroll(w http.ResponseWriter, r *http.Request) {
return
}
c := bc.Blogroll
can := bc.getRelativePath(cmp.Or(c.Path, defaultBlogrollPath))
_, can := bc.getBlogrollPath()
a.render(w, r, a.renderBlogroll, &renderData{
Canonical: a.getFullAddress(can),
Data: &blogrollRenderData{
title: c.Title,
description: c.Description,
outlines: outlines.([]*opml.Outline),
download: can + ".opml",
download: can + blogrollDownloadFile,
refresh: can + blogrollRefreshSubpath,
},
})
}
@ -64,6 +77,14 @@ func (a *goBlog) serveBlogrollExport(w http.ResponseWriter, r *http.Request) {
_ = pr.CloseWithError(a.min.Get().Minify(contenttype.XML, w, pr))
}
func (a *goBlog) refreshBlogroll(w http.ResponseWriter, r *http.Request) {
blog, bc := a.getBlog(r)
a.db.clearPersistentCache("blogroll_" + blog)
a.cache.purge()
_, brPath := bc.getBlogrollPath()
http.Redirect(w, r, brPath, http.StatusFound)
}
func (a *goBlog) getBlogrollOutlines(blog string) ([]*opml.Outline, error) {
// Get config
config := a.cfg.Blogs[blog].Blogroll

View File

@ -416,15 +416,14 @@ func (a *goBlog) blogStatsRouter(conf *configBlog) func(r chi.Router) {
// Blog - Blogroll
func (a *goBlog) blogBlogrollRouter(conf *configBlog) func(r chi.Router) {
return func(r chi.Router) {
if brConfig := conf.Blogroll; brConfig != nil && brConfig.Enabled {
brPath := conf.getRelativePath(cmp.Or(brConfig.Path, defaultBlogrollPath))
if brEnabled, brPath := conf.getBlogrollPath(); brEnabled {
r.Use(
a.privateModeHandler,
middleware.WithValue(cacheExpirationKey, a.defaultCacheExpiration()),
a.cacheMiddleware,
)
r.Get(brPath, a.serveBlogroll)
r.Get(brPath+".opml", a.serveBlogrollExport)
r.With(a.cacheMiddleware).Get(brPath, a.serveBlogroll)
r.With(a.cacheMiddleware).Get(brPath+blogrollDownloadFile, a.serveBlogrollExport)
r.With(a.authMiddleware).Post(brPath+blogrollRefreshSubpath, a.refreshBlogroll)
}
}
}

View File

@ -87,9 +87,9 @@ func (a *goBlog) serveSitemapBlogFeatures(w http.ResponseWriter, r *http.Request
})
}
// Blogroll
if brc := bc.Blogroll; brc != nil && brc.Enabled {
if blogrollEnabled, blogrollPath := bc.getBlogrollPath(); blogrollEnabled {
sm.Add(&sitemap.URL{
Loc: a.getFullAddress(bc.getRelativePath(cmp.Or(brc.Path, defaultBlogrollPath))),
Loc: a.getFullAddress(blogrollPath),
})
}
// Geo map

46
ui.go
View File

@ -1,7 +1,6 @@
package main
import (
"cmp"
"fmt"
"time"
@ -47,8 +46,8 @@ func (a *goBlog) renderBase(hb *htmlbuilder.HtmlBuilder, rd *renderData, title,
hb.WriteElementOpen("link", "rel", "alternate", "type", "application/atom+xml", "title", fmt.Sprintf("ATOM (%s)", renderedBlogTitle), "href", a.getFullAddress(rd.Blog.Path+".atom"))
hb.WriteElementOpen("link", "rel", "alternate", "type", "application/feed+json", "title", fmt.Sprintf("JSON Feed (%s)", renderedBlogTitle), "href", a.getFullAddress(rd.Blog.Path+".json"))
// Blogroll
if brConf := rd.Blog.Blogroll; brConf != nil && brConf.Enabled {
hb.WriteElementOpen("link", "rel", "blogroll", "type", "text/xml", "href", rd.Blog.getRelativePath(cmp.Or(brConf.Path, defaultBlogrollPath)+".opml"))
if brEnabled, brPath := rd.Blog.getBlogrollPath(); brEnabled {
hb.WriteElementOpen("link", "rel", "blogroll", "type", "text/xml", "href", brPath+blogrollDownloadFile)
}
// Webmentions
hb.WriteElementOpen("link", "rel", "webmention", "href", a.getFullAddress("/webmention"))
@ -613,6 +612,7 @@ type blogrollRenderData struct {
description string
outlines []*opml.Outline
download string
refresh string
}
func (a *goBlog) renderBlogroll(hb *htmlbuilder.HtmlBuilder, rd *renderData) {
@ -647,34 +647,48 @@ func (a *goBlog) renderBlogroll(hb *htmlbuilder.HtmlBuilder, rd *renderData) {
hb.WriteElementClose("a")
hb.WriteElementClose("p")
// Outlines
for _, outline := range bd.outlines {
title := outline.Title
if title == "" {
title = outline.Text
for _, category := range bd.outlines {
categoryTitle := category.Title
if categoryTitle == "" {
categoryTitle = category.Text
}
hb.WriteElementOpen("h2", "id", urlize(title))
hb.WriteEscaped(fmt.Sprintf("%s (%d)", title, len(outline.Outlines)))
hb.WriteElementOpen("h2", "id", urlize(categoryTitle))
hb.WriteEscaped(fmt.Sprintf("%s (%d)", categoryTitle, len(category.Outlines)))
hb.WriteElementClose("h2")
hb.WriteElementOpen("ul")
for _, subOutline := range outline.Outlines {
subTitle := subOutline.Title
if subTitle == "" {
subTitle = subOutline.Text
for _, blog := range category.Outlines {
blogTitle := blog.Title
if blogTitle == "" {
blogTitle = blog.Text
}
hb.WriteElementOpen("li")
hb.WriteElementOpen("a", "href", subOutline.HTMLURL, "target", "_blank")
hb.WriteEscaped(subTitle)
hb.WriteElementOpen("a", "href", blog.HTMLURL, "target", "_blank")
hb.WriteEscaped(blogTitle)
hb.WriteElementClose("a")
hb.WriteUnescaped(" (")
hb.WriteElementOpen("a", "href", subOutline.XMLURL, "target", "_blank")
hb.WriteElementOpen("a", "href", blog.XMLURL, "target", "_blank")
hb.WriteEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "feed"))
hb.WriteElementClose("a")
hb.WriteUnescaped(")")
if blog.Description != "" {
hb.WriteEscaped(" — ")
hb.WriteElementOpen("i")
hb.WriteEscaped(blog.Description)
hb.WriteElementClose("i")
}
hb.WriteElementClose("li")
}
hb.WriteElementClose("ul")
}
hb.WriteElementClose("main")
// Actions
if rd.LoggedIn() {
hb.WriteElementOpen("div", "class", "actions")
hb.WriteElementOpen("form", "method", "post", "action", bd.refresh)
hb.WriteElementOpen("input", "type", "submit", "value", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "update"))
hb.WriteElementClose("form")
hb.WriteElementClose("div")
}
// Interactions
if rd.Blog.commentsEnabled() {
a.renderInteractions(hb, rd)