Use cmp.Or

This commit is contained in:
Jan-Lukas Else 2024-04-22 15:49:22 +02:00
parent 00271a9728
commit 6e3fedeb20
23 changed files with 71 additions and 66 deletions

View File

@ -2,6 +2,7 @@ package main
import ( import (
"bytes" "bytes"
"cmp"
"context" "context"
"io" "io"
"net/http" "net/http"
@ -29,7 +30,7 @@ func (a *goBlog) serveBlogroll(w http.ResponseWriter, r *http.Request) {
return return
} }
c := bc.Blogroll c := bc.Blogroll
can := bc.getRelativePath(defaultIfEmpty(c.Path, defaultBlogrollPath)) can := bc.getRelativePath(cmp.Or(c.Path, defaultBlogrollPath))
a.render(w, r, a.renderBlogroll, &renderData{ a.render(w, r, a.renderBlogroll, &renderData{
Canonical: a.getFullAddress(can), Canonical: a.getFullAddress(can),
Data: &blogrollRenderData{ Data: &blogrollRenderData{

View File

@ -2,6 +2,7 @@ package main
import ( import (
"bytes" "bytes"
"cmp"
"database/sql" "database/sql"
"encoding/gob" "encoding/gob"
"net/http" "net/http"
@ -26,7 +27,7 @@ func (a *goBlog) initBlogStats() {
func (a *goBlog) serveBlogStats(w http.ResponseWriter, r *http.Request) { func (a *goBlog) serveBlogStats(w http.ResponseWriter, r *http.Request) {
_, bc := a.getBlog(r) _, bc := a.getBlog(r)
canonical := bc.getRelativePath(defaultIfEmpty(bc.BlogStats.Path, defaultBlogStatsPath)) canonical := bc.getRelativePath(cmp.Or(bc.BlogStats.Path, defaultBlogStatsPath))
a.render(w, r, a.renderBlogStats, &renderData{ a.render(w, r, a.renderBlogStats, &renderData{
Canonical: a.getFullAddress(canonical), Canonical: a.getFullAddress(canonical),
Data: &blogStatsRenderData{ Data: &blogStatsRenderData{

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"cmp"
"database/sql" "database/sql"
"errors" "errors"
"fmt" "fmt"
@ -44,7 +45,7 @@ func (a *goBlog) serveComment(w http.ResponseWriter, r *http.Request) {
_, bc := a.getBlog(r) _, bc := a.getBlog(r)
canonical := a.getFullAddress(bc.getRelativePath(path.Join(commentPath, strconv.Itoa(id)))) canonical := a.getFullAddress(bc.getRelativePath(path.Join(commentPath, strconv.Itoa(id))))
a.render(w, r, a.renderComment, &renderData{ a.render(w, r, a.renderComment, &renderData{
Canonical: defaultIfEmpty(comment.Original, canonical), Canonical: cmp.Or(comment.Original, canonical),
Data: comment, Data: comment,
}) })
} }
@ -77,7 +78,7 @@ func (a *goBlog) createComment(bc *configBlog, target, comment, name, website, o
if comment == "" { if comment == "" {
return "", http.StatusBadRequest, errors.New("comment is empty") return "", http.StatusBadRequest, errors.New("comment is empty")
} }
name = defaultIfEmpty(cleanHTMLText(name), "Anonymous") name = cmp.Or(cleanHTMLText(name), "Anonymous")
website = cleanHTMLText(website) website = cleanHTMLText(website)
original = cleanHTMLText(original) original = cleanHTMLText(original)
if original != "" { if original != "" {

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"cmp"
"errors" "errors"
"net/http" "net/http"
"net/url" "net/url"
@ -653,5 +654,5 @@ func (a *goBlog) getBlog(r *http.Request) (string, *configBlog) {
} }
func (a *goBlog) getBlogFromPost(p *post) *configBlog { func (a *goBlog) getBlogFromPost(p *post) *configBlog {
return a.cfg.Blogs[defaultIfEmpty(p.Blog, a.cfg.DefaultBlog)] return a.cfg.Blogs[cmp.Or(p.Blog, a.cfg.DefaultBlog)]
} }

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"cmp"
"context" "context"
"fmt" "fmt"
"io" "io"
@ -171,7 +172,7 @@ func (a *goBlog) editorMicropubPost(w http.ResponseWriter, r *http.Request, medi
return return
} }
if result.StatusCode >= 200 && result.StatusCode < 400 { if result.StatusCode >= 200 && result.StatusCode < 400 {
redirectPath := defaultIfEmpty(redirectSuccess, editorPath) redirectPath := cmp.Or(redirectSuccess, editorPath)
http.Redirect(w, r, redirectPath, http.StatusFound) http.Redirect(w, r, redirectPath, http.StatusFound)
return return
} }

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"cmp"
"os" "os"
"path/filepath" "path/filepath"
) )
@ -12,7 +13,7 @@ func (a *goBlog) exportMarkdownFiles(dir string) error {
if err != nil { if err != nil {
return err return err
} }
dir = defaultIfEmpty(dir, "export") dir = cmp.Or(dir, "export")
for _, p := range posts { for _, p := range posts {
filename := filepath.Join(dir, p.Path+".md") filename := filepath.Join(dir, p.Path+".md")
filedir := filepath.Dir(filename) filedir := filepath.Dir(filename)

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"cmp"
"io" "io"
"net/http" "net/http"
"time" "time"
@ -25,8 +26,8 @@ const (
func (a *goBlog) generateFeed(blog string, f feedType, w http.ResponseWriter, r *http.Request, posts []*post, title, description, path, query string) { func (a *goBlog) generateFeed(blog string, f feedType, w http.ResponseWriter, r *http.Request, posts []*post, title, description, path, query string) {
now := time.Now() now := time.Now()
title = a.renderMdTitle(defaultIfEmpty(title, a.cfg.Blogs[blog].Title)) title = a.renderMdTitle(cmp.Or(title, a.cfg.Blogs[blog].Title))
description = defaultIfEmpty(description, a.cfg.Blogs[blog].Description) description = cmp.Or(description, a.cfg.Blogs[blog].Description)
feed := &feeds.Feed{ feed := &feeds.Feed{
Title: title, Title: title,
Description: description, Description: description,

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"cmp"
"net/http" "net/http"
) )
@ -9,7 +10,7 @@ const defaultGeoMapPath = "/map"
func (a *goBlog) serveGeoMap(w http.ResponseWriter, r *http.Request) { func (a *goBlog) serveGeoMap(w http.ResponseWriter, r *http.Request) {
blog, bc := a.getBlog(r) blog, bc := a.getBlog(r)
mapPath := bc.getRelativePath(defaultIfEmpty(bc.Map.Path, defaultGeoMapPath)) mapPath := bc.getRelativePath(cmp.Or(bc.Map.Path, defaultGeoMapPath))
canonical := a.getFullAddress(mapPath) canonical := a.getFullAddress(mapPath)
allPostsWithLocationRequestConfig := &postsRequestConfig{ allPostsWithLocationRequestConfig := &postsRequestConfig{

2
go.mod
View File

@ -54,7 +54,7 @@ require (
github.com/stretchr/testify v1.9.0 github.com/stretchr/testify v1.9.0
github.com/tdewolff/minify/v2 v2.20.19 github.com/tdewolff/minify/v2 v2.20.19
github.com/tiptophelmet/cspolicy v0.1.1 github.com/tiptophelmet/cspolicy v0.1.1
github.com/tkrajina/gpxgo v1.3.1 github.com/tkrajina/gpxgo v1.4.0
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80
github.com/traefik/yaegi v0.16.1 github.com/traefik/yaegi v0.16.1
github.com/vcraescu/go-paginator/v2 v2.0.0 github.com/vcraescu/go-paginator/v2 v2.0.0

7
go.sum
View File

@ -143,7 +143,6 @@ github.com/jlaffaye/ftp v0.2.0 h1:lXNvW7cBu7R/68bknOX3MrRIIqZ61zELs1P2RAiA3lg=
github.com/jlaffaye/ftp v0.2.0/go.mod h1:is2Ds5qkhceAPy2xD6RLI6hmp/qysSoymZ+Z2uTnspI= github.com/jlaffaye/ftp v0.2.0/go.mod h1:is2Ds5qkhceAPy2xD6RLI6hmp/qysSoymZ+Z2uTnspI=
github.com/jlelse/feeds v1.3.0 h1:Vdks2qJ3XyxLYPle2UYa2Ucpw6GB48pBvpARJxz9fys= github.com/jlelse/feeds v1.3.0 h1:Vdks2qJ3XyxLYPle2UYa2Ucpw6GB48pBvpARJxz9fys=
github.com/jlelse/feeds v1.3.0/go.mod h1:2cAT6A2cQ4zcIz3FrCZKGXjHuJiGYe62MeM46/R0RxM= github.com/jlelse/feeds v1.3.0/go.mod h1:2cAT6A2cQ4zcIz3FrCZKGXjHuJiGYe62MeM46/R0RxM=
github.com/joeshaw/gengen v0.0.0-20190604015154-c77d87825f5a/go.mod h1:v2qvRL8Xwk4OlARK6gPlf2JreZXzv0dYp/8+kUJ0y7Q=
github.com/jonboulle/clockwork v0.3.0 h1:9BSCMi8C+0qdApAp4auwX0RkLGUjs956h0EkuQymUhg= github.com/jonboulle/clockwork v0.3.0 h1:9BSCMi8C+0qdApAp4auwX0RkLGUjs956h0EkuQymUhg=
github.com/jonboulle/clockwork v0.3.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/jonboulle/clockwork v0.3.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@ -273,8 +272,8 @@ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
github.com/tiptophelmet/cspolicy v0.1.1 h1:TiC1vWOuRcxPlY7GFIdRUpLvfTR3i5PJph66S3qsNpg= github.com/tiptophelmet/cspolicy v0.1.1 h1:TiC1vWOuRcxPlY7GFIdRUpLvfTR3i5PJph66S3qsNpg=
github.com/tiptophelmet/cspolicy v0.1.1/go.mod h1:rUdvHsbJflLSqh5gSWwDuMAxXGlysQpaN5V4vYzmcUM= github.com/tiptophelmet/cspolicy v0.1.1/go.mod h1:rUdvHsbJflLSqh5gSWwDuMAxXGlysQpaN5V4vYzmcUM=
github.com/tkrajina/gpxgo v1.3.1 h1:b9x0OgF0YqEtLKQoWC6SeCKy4OWUWSt9uzCDPKTI2LY= github.com/tkrajina/gpxgo v1.4.0 h1:cSD5uSwy3VZuNFieTEZLyRnuIwhonQEkGPkPGW4XNag=
github.com/tkrajina/gpxgo v1.3.1/go.mod h1:795sjVRFo5wWyN6oOZp0RYienGGBJjpAlgOz2nCngA0= github.com/tkrajina/gpxgo v1.4.0/go.mod h1:BXSMfUAvKiEhMEXAFM2NvNsbjsSvp394mOvdcNjettg=
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 h1:nrZ3ySNYwJbSpD6ce9duiP+QkD3JuLCcWkdaehUS/3Y= github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 h1:nrZ3ySNYwJbSpD6ce9duiP+QkD3JuLCcWkdaehUS/3Y=
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80/go.mod h1:iFyPdL66DjUD96XmzVL3ZntbzcflLnznH0fr99w5VqE= github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80/go.mod h1:iFyPdL66DjUD96XmzVL3ZntbzcflLnznH0fr99w5VqE=
github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208/go.mod h1:BzWtXXrXzZUvMacR0oF/fbDDgUPO8L36tDMmRAf14ns= github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208/go.mod h1:BzWtXXrXzZUvMacR0oF/fbDDgUPO8L36tDMmRAf14ns=
@ -314,7 +313,6 @@ golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8=
golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
@ -365,7 +363,6 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190603231351-8aaa1484dc10/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=

View File

@ -1,6 +1,8 @@
package main package main
import ( import (
"cmp"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware" "github.com/go-chi/chi/v5/middleware"
"go.goblog.app/app/pkgs/bodylimit" "go.goblog.app/app/pkgs/bodylimit"
@ -278,7 +280,7 @@ func (a *goBlog) dateRoutes(conf *configBlog, pathPrefix string) func(r chi.Rout
func (a *goBlog) blogPhotosRouter(conf *configBlog) func(r chi.Router) { func (a *goBlog) blogPhotosRouter(conf *configBlog) func(r chi.Router) {
return func(r chi.Router) { return func(r chi.Router) {
if pc := conf.Photos; pc != nil && pc.Enabled { if pc := conf.Photos; pc != nil && pc.Enabled {
photoPath := conf.getRelativePath(defaultIfEmpty(pc.Path, defaultPhotosPath)) photoPath := conf.getRelativePath(cmp.Or(pc.Path, defaultPhotosPath))
r.Use( r.Use(
a.privateModeHandler, a.privateModeHandler,
a.cacheMiddleware, a.cacheMiddleware,
@ -301,7 +303,7 @@ func (a *goBlog) blogPhotosRouter(conf *configBlog) func(r chi.Router) {
func (a *goBlog) blogSearchRouter(conf *configBlog) func(r chi.Router) { func (a *goBlog) blogSearchRouter(conf *configBlog) func(r chi.Router) {
return func(r chi.Router) { return func(r chi.Router) {
if bsc := conf.Search; bsc != nil && bsc.Enabled { if bsc := conf.Search; bsc != nil && bsc.Enabled {
searchPath := conf.getRelativePath(defaultIfEmpty(bsc.Path, defaultSearchPath)) searchPath := conf.getRelativePath(cmp.Or(bsc.Path, defaultSearchPath))
r.Route(searchPath, func(r chi.Router) { r.Route(searchPath, func(r chi.Router) {
r.Group(func(r chi.Router) { r.Group(func(r chi.Router) {
r.Use( r.Use(
@ -330,7 +332,7 @@ func (a *goBlog) blogSearchRouter(conf *configBlog) func(r chi.Router) {
func (a *goBlog) blogRandomRouter(conf *configBlog) func(r chi.Router) { func (a *goBlog) blogRandomRouter(conf *configBlog) func(r chi.Router) {
return func(r chi.Router) { return func(r chi.Router) {
if rp := conf.RandomPost; rp != nil && rp.Enabled { if rp := conf.RandomPost; rp != nil && rp.Enabled {
r.With(a.privateModeHandler).Get(conf.getRelativePath(defaultIfEmpty(rp.Path, defaultRandomPath)), a.redirectToRandomPost) r.With(a.privateModeHandler).Get(conf.getRelativePath(cmp.Or(rp.Path, defaultRandomPath)), a.redirectToRandomPost)
} }
} }
} }
@ -339,7 +341,7 @@ func (a *goBlog) blogRandomRouter(conf *configBlog) func(r chi.Router) {
func (a *goBlog) blogOnThisDayRouter(conf *configBlog) func(r chi.Router) { func (a *goBlog) blogOnThisDayRouter(conf *configBlog) func(r chi.Router) {
return func(r chi.Router) { return func(r chi.Router) {
if otd := conf.OnThisDay; otd != nil && otd.Enabled { if otd := conf.OnThisDay; otd != nil && otd.Enabled {
r.With(a.privateModeHandler).Get(conf.getRelativePath(defaultIfEmpty(otd.Path, defaultOnThisDayPath)), a.redirectToOnThisDay) r.With(a.privateModeHandler).Get(conf.getRelativePath(cmp.Or(otd.Path, defaultOnThisDayPath)), a.redirectToOnThisDay)
} }
} }
} }
@ -403,7 +405,7 @@ func (a *goBlog) blogCommentsRouter(conf *configBlog) func(r chi.Router) {
func (a *goBlog) blogStatsRouter(conf *configBlog) func(r chi.Router) { func (a *goBlog) blogStatsRouter(conf *configBlog) func(r chi.Router) {
return func(r chi.Router) { return func(r chi.Router) {
if bsc := conf.BlogStats; bsc != nil && bsc.Enabled { if bsc := conf.BlogStats; bsc != nil && bsc.Enabled {
statsPath := conf.getRelativePath(defaultIfEmpty(bsc.Path, defaultBlogStatsPath)) statsPath := conf.getRelativePath(cmp.Or(bsc.Path, defaultBlogStatsPath))
r.Use(a.privateModeHandler) r.Use(a.privateModeHandler)
r.With(a.cacheMiddleware).Get(statsPath, a.serveBlogStats) r.With(a.cacheMiddleware).Get(statsPath, a.serveBlogStats)
r.With(cacheLoggedIn, a.cacheMiddleware).Get(statsPath+blogStatsTablePath, a.serveBlogStatsTable) r.With(cacheLoggedIn, a.cacheMiddleware).Get(statsPath+blogStatsTablePath, a.serveBlogStatsTable)
@ -415,7 +417,7 @@ func (a *goBlog) blogStatsRouter(conf *configBlog) func(r chi.Router) {
func (a *goBlog) blogBlogrollRouter(conf *configBlog) func(r chi.Router) { func (a *goBlog) blogBlogrollRouter(conf *configBlog) func(r chi.Router) {
return func(r chi.Router) { return func(r chi.Router) {
if brConfig := conf.Blogroll; brConfig != nil && brConfig.Enabled { if brConfig := conf.Blogroll; brConfig != nil && brConfig.Enabled {
brPath := conf.getRelativePath(defaultIfEmpty(brConfig.Path, defaultBlogrollPath)) brPath := conf.getRelativePath(cmp.Or(brConfig.Path, defaultBlogrollPath))
r.Use( r.Use(
a.privateModeHandler, a.privateModeHandler,
middleware.WithValue(cacheExpirationKey, a.defaultCacheExpiration()), middleware.WithValue(cacheExpirationKey, a.defaultCacheExpiration()),
@ -432,7 +434,7 @@ func (a *goBlog) blogGeoMapRouter(conf *configBlog) func(r chi.Router) {
return func(r chi.Router) { return func(r chi.Router) {
if mc := conf.Map; mc != nil && mc.Enabled { if mc := conf.Map; mc != nil && mc.Enabled {
r.Use(a.privateModeHandler, a.cacheMiddleware) r.Use(a.privateModeHandler, a.cacheMiddleware)
mapPath := conf.getRelativePath(defaultIfEmpty(mc.Path, defaultGeoMapPath)) mapPath := conf.getRelativePath(cmp.Or(mc.Path, defaultGeoMapPath))
r.Get(mapPath, a.serveGeoMap) r.Get(mapPath, a.serveGeoMap)
r.Get(mapPath+geoMapTracksSubpath, a.serveGeoMapTracks) r.Get(mapPath+geoMapTracksSubpath, a.serveGeoMapTracks)
r.Get(mapPath+geoMapLocationsSubpath, a.serveGeoMapLocations) r.Get(mapPath+geoMapLocationsSubpath, a.serveGeoMapLocations)
@ -444,7 +446,7 @@ func (a *goBlog) blogGeoMapRouter(conf *configBlog) func(r chi.Router) {
func (a *goBlog) blogContactRouter(conf *configBlog) func(r chi.Router) { func (a *goBlog) blogContactRouter(conf *configBlog) func(r chi.Router) {
return func(r chi.Router) { return func(r chi.Router) {
if cc := conf.Contact; cc != nil && cc.Enabled { if cc := conf.Contact; cc != nil && cc.Enabled {
contactPath := conf.getRelativePath(defaultIfEmpty(cc.Path, defaultContactPath)) contactPath := conf.getRelativePath(cmp.Or(cc.Path, defaultContactPath))
r.Route(contactPath, func(r chi.Router) { r.Route(contactPath, func(r chi.Router) {
r.Use(a.privateModeHandler, a.cacheMiddleware) r.Use(a.privateModeHandler, a.cacheMiddleware)
r.Get("/", a.serveContactForm) r.Get("/", a.serveContactForm)

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"cmp"
"context" "context"
"net/http" "net/http"
"strings" "strings"
@ -19,7 +20,7 @@ func (a *goBlog) initIndieAuth() {
func (a *goBlog) checkIndieAuth(next http.Handler) http.Handler { func (a *goBlog) checkIndieAuth(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
bearerToken := defaultIfEmpty(r.Header.Get("Authorization"), r.URL.Query().Get("access_token")) bearerToken := cmp.Or(r.Header.Get("Authorization"), r.URL.Query().Get("access_token"))
data, err := a.db.indieAuthVerifyToken(bearerToken) data, err := a.db.indieAuthVerifyToken(bearerToken)
if err != nil { if err != nil {
a.serveError(w, r, err.Error(), http.StatusUnauthorized) a.serveError(w, r, err.Error(), http.StatusUnauthorized)

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"cmp"
"flag" "flag"
"fmt" "fmt"
"net" "net"
@ -115,7 +116,7 @@ func main() {
pprofHandler.HandleFunc("/debug/pprof/trace", netpprof.Trace) pprofHandler.HandleFunc("/debug/pprof/trace", netpprof.Trace)
// Build server and listener // Build server and listener
pprofServer := &http.Server{ pprofServer := &http.Server{
Addr: defaultIfEmpty(pprofCfg.Address, "localhost:0"), Addr: cmp.Or(pprofCfg.Address, "localhost:0"),
Handler: pprofHandler, Handler: pprofHandler,
ReadHeaderTimeout: 1 * time.Minute, ReadHeaderTimeout: 1 * time.Minute,
} }

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"cmp"
"crypto/sha256" "crypto/sha256"
"errors" "errors"
"fmt" "fmt"
@ -191,7 +192,7 @@ func (s *micropubImplementation) Update(req *micropub.Request) (string, error) {
if err != nil { if err != nil {
return "", fmt.Errorf("%w: %w", micropub.ErrBadRequest, err) return "", fmt.Errorf("%w: %w", micropub.ErrBadRequest, err)
} }
postPath := defaultIfEmpty(url.Path, "/") postPath := cmp.Or(url.Path, "/")
entry, err := s.a.getPost(postPath) entry, err := s.a.getPost(postPath)
if err != nil { if err != nil {
return "", fmt.Errorf("%w: %w", micropub.ErrBadRequest, err) return "", fmt.Errorf("%w: %w", micropub.ErrBadRequest, err)
@ -489,7 +490,7 @@ func (s *micropubImplementation) updatePostPropertiesFromMf(p *post, properties
delete(properties, "mp-slug") delete(properties, "mp-slug")
p.setChannel(getFirstStringFromArray(properties["mp-channel"])) p.setChannel(getFirstStringFromArray(properties["mp-channel"]))
delete(properties, "mp-channel") delete(properties, "mp-channel")
p.Visibility = postVisibility(defaultIfEmpty(getFirstStringFromArray(properties["visibility"]), string(p.Visibility))) p.Visibility = postVisibility(cmp.Or(getFirstStringFromArray(properties["visibility"]), string(p.Visibility)))
delete(properties, "visibility") delete(properties, "visibility")
if newStatusString := getFirstStringFromArray(properties["post-status"]); newStatusString != "" { if newStatusString := getFirstStringFromArray(properties["post-status"]); newStatusString != "" {
if newStatus := postStatus(newStatusString); newStatus == statusPublished || newStatus == statusDraft { if newStatus := postStatus(newStatusString); newStatus == statusPublished || newStatus == statusDraft {

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"cmp"
"encoding/xml" "encoding/xml"
"io" "io"
"net/http" "net/http"
@ -34,7 +35,7 @@ type openSearchDescriptionUrlParam struct {
func (a *goBlog) serveOpenSearch(w http.ResponseWriter, r *http.Request) { func (a *goBlog) serveOpenSearch(w http.ResponseWriter, r *http.Request) {
_, b := a.getBlog(r) _, b := a.getBlog(r)
title := a.renderMdTitle(b.Title) title := a.renderMdTitle(b.Title)
sURL := a.getFullAddress(b.getRelativePath(defaultIfEmpty(b.Search.Path, defaultSearchPath))) sURL := a.getFullAddress(b.getRelativePath(cmp.Or(b.Search.Path, defaultSearchPath)))
openSearch := &openSearchDescription{ openSearch := &openSearchDescription{
ShortName: title, ShortName: title,
Description: title, Description: title,
@ -60,7 +61,7 @@ func (a *goBlog) serveOpenSearch(w http.ResponseWriter, r *http.Request) {
func openSearchUrl(b *configBlog) string { func openSearchUrl(b *configBlog) string {
if b.Search != nil && b.Search.Enabled { if b.Search != nil && b.Search.Enabled {
return b.getRelativePath(defaultIfEmpty(b.Search.Path, defaultSearchPath) + "/opensearch.xml") return b.getRelativePath(cmp.Or(b.Search.Path, defaultSearchPath) + "/opensearch.xml")
} }
return "" return ""
} }

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"cmp"
"database/sql" "database/sql"
"errors" "errors"
"fmt" "fmt"
@ -124,7 +125,7 @@ func (a *goBlog) checkPost(p *post, new bool) (err error) {
if p.Slug == "" { if p.Slug == "" {
p.Slug = fmt.Sprintf("%v-%02d-%02d-%v", published.Year(), int(published.Month()), published.Day(), randomString(5)) p.Slug = fmt.Sprintf("%v-%02d-%02d-%v", published.Year(), int(published.Month()), published.Day(), randomString(5))
} }
pathTmplString := defaultIfEmpty( pathTmplString := cmp.Or(
a.getBlogFromPost(p).Sections[p.Section].PathTemplate, a.getBlogFromPost(p).Sections[p.Section].PathTemplate,
"{{printf \""+a.getRelativePath(p.Blog, "/%v/%02d/%02d/%v")+"\" .Section .Year .Month .Slug}}", "{{printf \""+a.getRelativePath(p.Blog, "/%v/%02d/%02d/%v")+"\" .Section .Year .Month .Slug}}",
) )

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"cmp"
"encoding/xml" "encoding/xml"
"fmt" "fmt"
"io" "io"
@ -70,37 +71,37 @@ func (a *goBlog) serveSitemapBlogFeatures(w http.ResponseWriter, r *http.Request
// Photos // Photos
if pc := bc.Photos; pc != nil && pc.Enabled { if pc := bc.Photos; pc != nil && pc.Enabled {
sm.Add(&sitemap.URL{ sm.Add(&sitemap.URL{
Loc: a.getFullAddress(bc.getRelativePath(defaultIfEmpty(pc.Path, defaultPhotosPath))), Loc: a.getFullAddress(bc.getRelativePath(cmp.Or(pc.Path, defaultPhotosPath))),
}) })
} }
// Search // Search
if bsc := bc.Search; bsc != nil && bsc.Enabled { if bsc := bc.Search; bsc != nil && bsc.Enabled {
sm.Add(&sitemap.URL{ sm.Add(&sitemap.URL{
Loc: a.getFullAddress(bc.getRelativePath(defaultIfEmpty(bsc.Path, defaultSearchPath))), Loc: a.getFullAddress(bc.getRelativePath(cmp.Or(bsc.Path, defaultSearchPath))),
}) })
} }
// Stats // Stats
if bsc := bc.BlogStats; bsc != nil && bsc.Enabled { if bsc := bc.BlogStats; bsc != nil && bsc.Enabled {
sm.Add(&sitemap.URL{ sm.Add(&sitemap.URL{
Loc: a.getFullAddress(bc.getRelativePath(defaultIfEmpty(bsc.Path, defaultBlogStatsPath))), Loc: a.getFullAddress(bc.getRelativePath(cmp.Or(bsc.Path, defaultBlogStatsPath))),
}) })
} }
// Blogroll // Blogroll
if brc := bc.Blogroll; brc != nil && brc.Enabled { if brc := bc.Blogroll; brc != nil && brc.Enabled {
sm.Add(&sitemap.URL{ sm.Add(&sitemap.URL{
Loc: a.getFullAddress(bc.getRelativePath(defaultIfEmpty(brc.Path, defaultBlogrollPath))), Loc: a.getFullAddress(bc.getRelativePath(cmp.Or(brc.Path, defaultBlogrollPath))),
}) })
} }
// Geo map // Geo map
if mc := bc.Map; mc != nil && mc.Enabled { if mc := bc.Map; mc != nil && mc.Enabled {
sm.Add(&sitemap.URL{ sm.Add(&sitemap.URL{
Loc: a.getFullAddress(bc.getRelativePath(defaultIfEmpty(mc.Path, defaultGeoMapPath))), Loc: a.getFullAddress(bc.getRelativePath(cmp.Or(mc.Path, defaultGeoMapPath))),
}) })
} }
// Contact // Contact
if cc := bc.Contact; cc != nil && cc.Enabled { if cc := bc.Contact; cc != nil && cc.Enabled {
sm.Add(&sitemap.URL{ sm.Add(&sitemap.URL{
Loc: a.getFullAddress(bc.getRelativePath(defaultIfEmpty(cc.Path, defaultContactPath))), Loc: a.getFullAddress(bc.getRelativePath(cmp.Or(cc.Path, defaultContactPath))),
}) })
} }
// Write sitemap // Write sitemap
@ -170,7 +171,7 @@ func (a *goBlog) serveSitemapBlogPosts(w http.ResponseWriter, r *http.Request) {
// Add posts to sitemap // Add posts to sitemap
for _, p := range posts { for _, p := range posts {
item := &sitemap.URL{Loc: a.fullPostURL(p)} item := &sitemap.URL{Loc: a.fullPostURL(p)}
lastMod := noError(dateparse.ParseLocal(defaultIfEmpty(p.Updated, p.Published))) lastMod := noError(dateparse.ParseLocal(cmp.Or(p.Updated, p.Published)))
if !lastMod.IsZero() { if !lastMod.IsZero() {
item.LastMod = &lastMod item.LastMod = &lastMod
} }

3
tts.go
View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"cmp"
"context" "context"
"crypto/sha256" "crypto/sha256"
"encoding/base64" "encoding/base64"
@ -59,7 +60,7 @@ func (a *goBlog) ttsEnabled() bool {
func (a *goBlog) createPostTTSAudio(p *post) error { func (a *goBlog) createPostTTSAudio(p *post) error {
// Get required values // Get required values
lang := defaultIfEmpty(a.getBlogFromPost(p).Lang, "en") lang := cmp.Or(a.getBlogFromPost(p).Lang, "en")
// Create TTS text parts // Create TTS text parts
parts := []string{} parts := []string{}

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"cmp"
"fmt" "fmt"
"strings" "strings"
"time" "time"
@ -332,7 +333,7 @@ func (a *goBlog) renderInteractions(hb *htmlbuilder.HtmlBuilder, rd *renderData)
for _, mention := range m { for _, mention := range m {
hb.WriteElementOpen("li") hb.WriteElementOpen("li")
hb.WriteElementOpen("a", "href", mention.Url, "target", "_blank", "rel", "nofollow noopener noreferrer ugc") hb.WriteElementOpen("a", "href", mention.Url, "target", "_blank", "rel", "nofollow noopener noreferrer ugc")
hb.WriteEscaped(defaultIfEmpty(mention.Author, mention.Url)) hb.WriteEscaped(cmp.Or(mention.Author, mention.Url))
hb.WriteElementClose("a") hb.WriteElementClose("a")
if mention.Title != "" { if mention.Title != "" {
hb.WriteUnescaped(" ") hb.WriteUnescaped(" ")
@ -388,7 +389,7 @@ func (a *goBlog) renderAuthor(hb *htmlbuilder.HtmlBuilder) {
hb.WriteElementClose("data") hb.WriteElementClose("data")
} }
if user.Name != "" { if user.Name != "" {
hb.WriteElementOpen("a", "class", "p-name u-url", "rel", "me", "href", defaultIfEmpty(user.Link, "/")) hb.WriteElementOpen("a", "class", "p-name u-url", "rel", "me", "href", cmp.Or(user.Link, "/"))
hb.WriteEscaped(user.Name) hb.WriteEscaped(user.Name)
hb.WriteElementClose("a") hb.WriteElementClose("a")
} }

View File

@ -311,13 +311,6 @@ func cleanHTMLText(s string) string {
return s return s
} }
func defaultIfEmpty(s, d string) string {
if s == "" {
return d
}
return s
}
func containsStrings(s string, subStrings ...string) bool { func containsStrings(s string, subStrings ...string) bool {
for _, ss := range subStrings { for _, ss := range subStrings {
if strings.Contains(s, ss) { if strings.Contains(s, ss) {

View File

@ -126,11 +126,6 @@ func Test_containsStrings(t *testing.T) {
assert.False(t, containsStrings("Test", "xx", "aa")) assert.False(t, containsStrings("Test", "xx", "aa"))
} }
func Test_defaultIfEmpty(t *testing.T) {
assert.Equal(t, "def", defaultIfEmpty("", "def"))
assert.Equal(t, "first", defaultIfEmpty("first", "def"))
}
func Test_matchTimeDiffLocale(t *testing.T) { func Test_matchTimeDiffLocale(t *testing.T) {
assert.Equal(t, "en", string(matchTimeDiffLocale("en-US"))) assert.Equal(t, "en", string(matchTimeDiffLocale("en-US")))
assert.Equal(t, "en", string(matchTimeDiffLocale("en"))) assert.Equal(t, "en", string(matchTimeDiffLocale("en")))

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"cmp"
"database/sql" "database/sql"
"errors" "errors"
"fmt" "fmt"
@ -112,8 +113,8 @@ func (db *database) webmentionExists(m *mention) bool {
and lowerunescaped(target) in (lowerunescaped(@target), lowerunescaped(@newtarget)) and lowerunescaped(target) in (lowerunescaped(@target), lowerunescaped(@newtarget))
) )
`, `,
sql.Named("source", m.Source), sql.Named("newsource", defaultIfEmpty(m.NewSource, m.Source)), sql.Named("source", m.Source), sql.Named("newsource", cmp.Or(m.NewSource, m.Source)),
sql.Named("target", m.Target), sql.Named("newtarget", defaultIfEmpty(m.NewTarget, m.Target)), sql.Named("target", m.Target), sql.Named("newtarget", cmp.Or(m.NewTarget, m.Target)),
) )
if err != nil { if err != nil {
return false return false
@ -165,17 +166,17 @@ func (db *database) updateWebmention(m *mention, newStatus webmentionStatus) err
lowerunescaped(source) in (lowerunescaped(@source), lowerunescaped(@newsource2)) lowerunescaped(source) in (lowerunescaped(@source), lowerunescaped(@newsource2))
and lowerunescaped(target) in (lowerunescaped(@target), lowerunescaped(@newtarget2)) and lowerunescaped(target) in (lowerunescaped(@target), lowerunescaped(@newtarget2))
`, `,
sql.Named("newsource", defaultIfEmpty(m.NewSource, m.Source)), sql.Named("newsource", cmp.Or(m.NewSource, m.Source)),
sql.Named("newtarget", defaultIfEmpty(m.NewTarget, m.Target)), sql.Named("newtarget", cmp.Or(m.NewTarget, m.Target)),
sql.Named("url", m.Url), sql.Named("url", m.Url),
sql.Named("status", newStatus), sql.Named("status", newStatus),
sql.Named("title", m.Title), sql.Named("title", m.Title),
sql.Named("content", m.Content), sql.Named("content", m.Content),
sql.Named("author", m.Author), sql.Named("author", m.Author),
sql.Named("source", m.Source), sql.Named("source", m.Source),
sql.Named("newsource2", defaultIfEmpty(m.NewSource, m.Source)), sql.Named("newsource2", cmp.Or(m.NewSource, m.Source)),
sql.Named("target", m.Target), sql.Named("target", m.Target),
sql.Named("newtarget2", defaultIfEmpty(m.NewTarget, m.Target)), sql.Named("newtarget2", cmp.Or(m.NewTarget, m.Target)),
) )
return err return err
} }
@ -194,9 +195,9 @@ func (db *database) deleteWebmention(m *mention) error {
_, err := db.Exec( _, err := db.Exec(
"delete from webmentions where lowerunescaped(source) in (lowerunescaped(@source), lowerunescaped(@newsource)) and lowerunescaped(target) in (lowerunescaped(@target), lowerunescaped(@newtarget))", "delete from webmentions where lowerunescaped(source) in (lowerunescaped(@source), lowerunescaped(@newsource)) and lowerunescaped(target) in (lowerunescaped(@target), lowerunescaped(@newtarget))",
sql.Named("source", m.Source), sql.Named("source", m.Source),
sql.Named("newsource", defaultIfEmpty(m.NewSource, m.Source)), sql.Named("newsource", cmp.Or(m.NewSource, m.Source)),
sql.Named("target", m.Target), sql.Named("target", m.Target),
sql.Named("newtarget", defaultIfEmpty(m.NewTarget, m.Target)), sql.Named("newtarget", cmp.Or(m.NewTarget, m.Target)),
) )
return err return err
} }

View File

@ -2,6 +2,7 @@ package main
import ( import (
"bytes" "bytes"
"cmp"
"context" "context"
"encoding/gob" "encoding/gob"
"errors" "errors"
@ -126,7 +127,7 @@ func (a *goBlog) verifyMention(m *mention) error {
if err != nil { if err != nil {
return err return err
} }
a.sendNotification(fmt.Sprintf("New webmention from %s to %s", defaultIfEmpty(m.NewSource, m.Source), defaultIfEmpty(m.NewTarget, m.Target))) a.sendNotification(fmt.Sprintf("New webmention from %s to %s", cmp.Or(m.NewSource, m.Source), cmp.Or(m.NewTarget, m.Target)))
} }
return err return err
} }
@ -140,7 +141,7 @@ func (a *goBlog) verifyReader(m *mention, body io.Reader) error {
_ = pw.CloseWithError(err) _ = pw.CloseWithError(err)
}() }()
// Check if source mentions target // Check if source mentions target
links, err := allLinksFromHTML(pr, defaultIfEmpty(m.NewSource, m.Source)) links, err := allLinksFromHTML(pr, cmp.Or(m.NewSource, m.Source))
_ = pr.CloseWithError(err) _ = pr.CloseWithError(err)
if err != nil { if err != nil {
return err return err
@ -164,7 +165,7 @@ func (a *goBlog) verifyReader(m *mention, body io.Reader) error {
return false return false
} }
_ = resp.Body.Close() _ = resp.Body.Close()
if resp.StatusCode == http.StatusOK && lowerUnescapedPath(resp.Request.URL.String()) == lowerUnescapedPath(defaultIfEmpty(m.NewTarget, m.Target)) { if resp.StatusCode == http.StatusOK && lowerUnescapedPath(resp.Request.URL.String()) == lowerUnescapedPath(cmp.Or(m.NewTarget, m.Target)) {
return true return true
} }
return false return false
@ -172,10 +173,10 @@ func (a *goBlog) verifyReader(m *mention, body io.Reader) error {
return errors.New("target not found in source") return errors.New("target not found in source")
} }
// Fill mention attributes // Fill mention attributes
mf, err := parseMicroformatsFromReader(defaultIfEmpty(m.NewSource, m.Source), mfBuffer) mf, err := parseMicroformatsFromReader(cmp.Or(m.NewSource, m.Source), mfBuffer)
if err != nil { if err != nil {
return err return err
} }
m.Title, m.Content, m.Author, m.Url = mf.Title, mf.Content, mf.Author, defaultIfEmpty(mf.Url, m.Source) m.Title, m.Content, m.Author, m.Url = mf.Title, mf.Content, mf.Author, cmp.Or(mf.Url, m.Source)
return nil return nil
} }