pull/25/head
Jan-Lukas Else 7 months ago
parent 7e8cb619b5
commit 474155306d
  1. 2
      Dockerfile
  2. 26
      activityPub.go
  3. 2
      activityPubSending.go
  4. 4
      activityStreams.go
  5. 10
      blogroll.go
  6. 2
      blogstats.go
  7. 2
      cache.go
  8. 9
      check.go
  9. 2
      comments.go
  10. 14
      commentsAdmin.go
  11. 5
      config.go
  12. 18
      database.go
  13. 6
      databaseHooks.go
  14. 4
      databaseMigrations.go
  15. 4
      debug.go
  16. 6
      editor.go
  17. 10
      editorFiles.go
  18. 8
      geo.go
  19. 9
      go.mod
  20. 19
      go.sum
  21. 10
      hooks.go
  22. 3
      indexnow.go
  23. 2
      main.go
  24. 2
      markdown.go
  25. 10
      mediaCompression.go
  26. 2
      mediaCompression_test.go
  27. 68
      micropub.go
  28. 14
      nodeinfo.go
  29. 4
      notifications.go
  30. 2
      persistentCache.go
  31. 2
      pkgs/bufferpool/bufferPool.go
  32. 2
      pkgs/highlighting/highlighting.go
  33. 16
      pkgs/httpcompress/httpCompress.go
  34. 2
      posts.go
  35. 22
      postsDb.go
  36. 2
      postsFuncs.go
  37. 4
      render.go
  38. 2
      shortPath.go
  39. 2
      sitemap.go
  40. 2
      tailscale.go
  41. 10
      tts.go
  42. 8
      ui.go
  43. 4
      uiHtmlBuilder.go
  44. 25
      utils.go
  45. 14
      utils_test.go
  46. 2
      webmention.go
  47. 14
      webmentionAdmin.go
  48. 4
      webmentionSending.go
  49. 4
      webmentionVerification.go

@ -1,4 +1,4 @@
FROM golang:1.17-alpine3.15 as buildbase
FROM golang:1.18-alpine3.15 as buildbase
WORKDIR /app
RUN apk add --no-cache git gcc musl-dev

@ -89,7 +89,7 @@ func (a *goBlog) apHandleWebfinger(w http.ResponseWriter, r *http.Request) {
return
}
apIri := a.apIri(blog)
b, _ := json.Marshal(map[string]interface{}{
b, _ := json.Marshal(map[string]any{
"subject": a.webfingerAccts[apIri],
"aliases": []string{
a.webfingerAccts[apIri],
@ -142,7 +142,7 @@ func (a *goBlog) apHandleInbox(w http.ResponseWriter, r *http.Request) {
return
}
// Parse activity
activity := map[string]interface{}{}
activity := map[string]any{}
err = json.NewDecoder(r.Body).Decode(&activity)
_ = r.Body.Close()
if err != nil {
@ -164,7 +164,7 @@ func (a *goBlog) apHandleInbox(w http.ResponseWriter, r *http.Request) {
case "Follow":
a.apAccept(blogName, blog, activity)
case "Undo":
if object, ok := activity["object"].(map[string]interface{}); ok {
if object, ok := activity["object"].(map[string]any); ok {
ot := cast.ToString(object["type"])
actor := cast.ToString(object["actor"])
if ot == "Follow" && actor == activityActor {
@ -172,7 +172,7 @@ func (a *goBlog) apHandleInbox(w http.ResponseWriter, r *http.Request) {
}
}
case "Create":
if object, ok := activity["object"].(map[string]interface{}); ok {
if object, ok := activity["object"].(map[string]any); ok {
baseUrl := cast.ToString(object["id"])
if ou := cast.ToString(object["url"]); ou != "" {
baseUrl = ou
@ -297,7 +297,7 @@ func (db *database) apRemoveInbox(inbox string) error {
func (a *goBlog) apPost(p *post) {
n := a.toASNote(p)
a.apSendToAllFollowers(p.Blog, map[string]interface{}{
a.apSendToAllFollowers(p.Blog, map[string]any{
"@context": []string{asContext},
"actor": a.apIri(a.cfg.Blogs[p.Blog]),
"id": a.fullPostURL(p),
@ -308,7 +308,7 @@ func (a *goBlog) apPost(p *post) {
}
func (a *goBlog) apUpdate(p *post) {
a.apSendToAllFollowers(p.Blog, map[string]interface{}{
a.apSendToAllFollowers(p.Blog, map[string]any{
"@context": []string{asContext},
"actor": a.apIri(a.cfg.Blogs[p.Blog]),
"id": a.fullPostURL(p),
@ -319,7 +319,7 @@ func (a *goBlog) apUpdate(p *post) {
}
func (a *goBlog) apDelete(p *post) {
a.apSendToAllFollowers(p.Blog, map[string]interface{}{
a.apSendToAllFollowers(p.Blog, map[string]any{
"@context": []string{asContext},
"actor": a.apIri(a.cfg.Blogs[p.Blog]),
"type": "Delete",
@ -328,11 +328,11 @@ func (a *goBlog) apDelete(p *post) {
}
func (a *goBlog) apUndelete(p *post) {
a.apSendToAllFollowers(p.Blog, map[string]interface{}{
a.apSendToAllFollowers(p.Blog, map[string]any{
"@context": []string{asContext},
"actor": a.apIri(a.cfg.Blogs[p.Blog]),
"type": "Undo",
"object": map[string]interface{}{
"object": map[string]any{
"@context": []string{asContext},
"actor": a.apIri(a.cfg.Blogs[p.Blog]),
"type": "Delete",
@ -341,7 +341,7 @@ func (a *goBlog) apUndelete(p *post) {
})
}
func (a *goBlog) apAccept(blogName string, blog *configBlog, follow map[string]interface{}) {
func (a *goBlog) apAccept(blogName string, blog *configBlog, follow map[string]any) {
// it's a follow, write it down
newFollower := follow["actor"].(string)
log.Println("New follow request:", newFollower)
@ -365,7 +365,7 @@ func (a *goBlog) apAccept(blogName string, blog *configBlog, follow map[string]i
return
}
// Send accept response to the new follower
accept := map[string]interface{}{
accept := map[string]any{
"@context": []string{asContext},
"type": "Accept",
"to": follow["actor"],
@ -376,7 +376,7 @@ func (a *goBlog) apAccept(blogName string, blog *configBlog, follow map[string]i
_ = a.db.apQueueSendSigned(a.apIri(blog), inbox, accept)
}
func (a *goBlog) apSendToAllFollowers(blog string, activity interface{}) {
func (a *goBlog) apSendToAllFollowers(blog string, activity any) {
inboxes, err := a.db.apGetAllInboxes(blog)
if err != nil {
log.Println("Failed to retrieve inboxes:", err.Error())
@ -385,7 +385,7 @@ func (a *goBlog) apSendToAllFollowers(blog string, activity interface{}) {
a.db.apSendTo(a.apIri(a.cfg.Blogs[blog]), activity, inboxes)
}
func (db *database) apSendTo(blogIri string, activity interface{}, inboxes []string) {
func (db *database) apSendTo(blogIri string, activity any, inboxes []string) {
for _, i := range inboxes {
go func(inbox string) {
_ = db.apQueueSendSigned(blogIri, inbox, activity)

@ -47,7 +47,7 @@ func (a *goBlog) initAPSendQueue() {
})
}
func (db *database) apQueueSendSigned(blogIri, to string, activity interface{}) error {
func (db *database) apQueueSendSigned(blogIri, to string, activity any) error {
body, err := json.Marshal(activity)
if err != nil {
return err

@ -38,7 +38,7 @@ func (a *goBlog) checkActivityStreamsRequest(next http.Handler) http.Handler {
}
type asNote struct {
Context interface{} `json:"@context,omitempty"`
Context any `json:"@context,omitempty"`
To []string `json:"to,omitempty"`
InReplyTo string `json:"inReplyTo,omitempty"`
Name string `json:"name,omitempty"`
@ -55,7 +55,7 @@ type asNote struct {
}
type asPerson struct {
Context interface{} `json:"@context,omitempty"`
Context any `json:"@context,omitempty"`
ID string `json:"id,omitempty"`
URL string `json:"url,omitempty"`
Type string `json:"type,omitempty"`

@ -11,7 +11,7 @@ import (
"github.com/carlmjohnson/requests"
"github.com/kaorimatz/go-opml"
"github.com/thoas/go-funk"
"github.com/samber/lo"
"go.goblog.app/app/pkgs/bufferpool"
"go.goblog.app/app/pkgs/contenttype"
)
@ -20,7 +20,7 @@ const defaultBlogrollPath = "/blogroll"
func (a *goBlog) serveBlogroll(w http.ResponseWriter, r *http.Request) {
blog, bc := a.getBlog(r)
outlines, err, _ := a.blogrollCacheGroup.Do(blog, func() (interface{}, error) {
outlines, err, _ := a.blogrollCacheGroup.Do(blog, func() (any, error) {
return a.getBlogrollOutlines(blog)
})
if err != nil {
@ -43,7 +43,7 @@ func (a *goBlog) serveBlogroll(w http.ResponseWriter, r *http.Request) {
func (a *goBlog) serveBlogrollExport(w http.ResponseWriter, r *http.Request) {
blog, _ := a.getBlog(r)
outlines, err, _ := a.blogrollCacheGroup.Do(blog, func() (interface{}, error) {
outlines, err, _ := a.blogrollCacheGroup.Do(blog, func() (any, error) {
return a.getBlogrollOutlines(blog)
})
if err != nil {
@ -91,9 +91,9 @@ func (a *goBlog) getBlogrollOutlines(blog string) ([]*opml.Outline, error) {
if len(config.Categories) > 0 {
filtered := []*opml.Outline{}
for _, category := range config.Categories {
if outline, ok := funk.Find(outlines, func(outline *opml.Outline) bool {
if outline, ok := lo.Find(outlines, func(outline *opml.Outline) bool {
return outline.Title == category || outline.Text == category
}).(*opml.Outline); ok && outline != nil {
}); ok && outline != nil {
outline.Outlines = sortOutlines(outline.Outlines)
filtered = append(filtered, outline)
}

@ -37,7 +37,7 @@ func (a *goBlog) serveBlogStats(w http.ResponseWriter, r *http.Request) {
func (a *goBlog) serveBlogStatsTable(w http.ResponseWriter, r *http.Request) {
blog, _ := a.getBlog(r)
data, err, _ := a.blogStatsCacheGroup.Do(blog, func() (interface{}, error) {
data, err, _ := a.blogStatsCacheGroup.Do(blog, func() (any, error) {
return a.db.getBlogStats(blog)
})
if err != nil {

@ -76,7 +76,7 @@ func (a *goBlog) cacheMiddleware(next http.Handler) http.Handler {
// Search and serve cache
key := cacheKey(r)
// Get cache or render it
cacheInterface, _, _ := a.cache.g.Do(key, func() (interface{}, error) {
cacheInterface, _, _ := a.cache.g.Do(key, func() (any, error) {
return a.cache.getCache(key, next, r), nil
})
ci := cacheInterface.(*cacheItem)

@ -12,6 +12,7 @@ import (
"time"
"github.com/klauspost/compress/gzhttp"
"github.com/samber/lo"
"go.goblog.app/app/pkgs/bufferpool"
"golang.org/x/sync/singleflight"
)
@ -79,7 +80,7 @@ func (a *goBlog) checkLinks(w io.Writer, posts ...*post) error {
return
}
// Process link
r, err, _ := sg.Do(link.Second, func() (interface{}, error) {
r, err, _ := sg.Do(link.Second, func() (any, error) {
// Check if already cached
if mr, ok := sm.Load(link.Second); ok {
return mr, nil
@ -131,9 +132,9 @@ func (a *goBlog) allLinks(posts ...*post) (allLinks []*stringPair, err error) {
if err != nil {
return nil, err
}
for _, link := range links {
allLinks = append(allLinks, &stringPair{a.fullPostURL(p), link})
}
allLinks = lo.Map(links, func(s string, _ int) *stringPair {
return &stringPair{a.fullPostURL(p), s}
})
}
return allLinks, nil
}

@ -102,7 +102,7 @@ type commentsRequestConfig struct {
offset, limit int
}
func buildCommentsQuery(config *commentsRequestConfig) (query string, args []interface{}) {
func buildCommentsQuery(config *commentsRequestConfig) (query string, args []any) {
queryBuilder := bufferpool.Get()
defer bufferpool.Put(queryBuilder)
queryBuilder.WriteString("select id, target, name, website, comment from comments order by id desc")

@ -5,26 +5,28 @@ import (
"net/http"
"reflect"
"strconv"
"sync"
"github.com/go-chi/chi/v5"
"github.com/vcraescu/go-paginator"
)
type commentsPaginationAdapter struct {
config *commentsRequestConfig
nums int64
db *database
config *commentsRequestConfig
nums int64
getNums sync.Once
db *database
}
func (p *commentsPaginationAdapter) Nums() (int64, error) {
if p.nums == 0 {
p.getNums.Do(func() {
nums, _ := p.db.countComments(p.config)
p.nums = int64(nums)
}
})
return p.nums, nil
}
func (p *commentsPaginationAdapter) Slice(offset, length int, data interface{}) error {
func (p *commentsPaginationAdapter) Slice(offset, length int, data any) error {
modifiedConfig := *p.config
modifiedConfig.offset = offset
modifiedConfig.limit = length

@ -7,6 +7,7 @@ import (
"net/url"
"strings"
"github.com/samber/lo"
"github.com/spf13/viper"
)
@ -370,9 +371,7 @@ func (a *goBlog) initConfig() error {
if a.cfg.DefaultBlog == "" {
if len(a.cfg.Blogs) == 1 {
// Set default blog to the only blog that is configured
for k := range a.cfg.Blogs {
a.cfg.DefaultBlog = k
}
a.cfg.DefaultBlog = lo.Keys(a.cfg.Blogs)[0]
} else {
return errors.New("no default blog configured")
}

@ -66,7 +66,7 @@ func (a *goBlog) openDatabase(file string, logging bool) (*database, error) {
sql.Register(dbDriverName, &sqlite.SQLiteDriver{
ConnectHook: func(c *sqlite.SQLiteConn) error {
// Register functions
for n, f := range map[string]interface{}{
for n, f := range map[string]any{
"mdtext": a.renderText,
"tolocal": toLocalSafe,
"toutc": toUTCSafe,
@ -174,14 +174,14 @@ func (db *database) close() error {
return db.db.Close()
}
func (db *database) prepare(query string, args ...interface{}) (*sql.Stmt, []interface{}, error) {
func (db *database) prepare(query string, args ...any) (*sql.Stmt, []any, error) {
if db == nil || db.db == nil {
return nil, nil, errors.New("database not initialized")
}
if len(args) > 0 && args[0] == dbNoCache {
return nil, args[1:], nil
}
stmt, err, _ := db.sg.Do(query, func() (interface{}, error) {
stmt, err, _ := db.sg.Do(query, func() (any, error) {
// Look if statement already exists
st, ok := db.psc.Get(query)
if ok {
@ -207,11 +207,11 @@ func (db *database) prepare(query string, args ...interface{}) (*sql.Stmt, []int
const dbNoCache = "nocache"
func (db *database) exec(query string, args ...interface{}) (sql.Result, error) {
func (db *database) exec(query string, args ...any) (sql.Result, error) {
return db.execContext(context.Background(), query, args...)
}
func (db *database) execContext(c context.Context, query string, args ...interface{}) (sql.Result, error) {
func (db *database) execContext(c context.Context, query string, args ...any) (sql.Result, error) {
if db == nil || db.db == nil {
return nil, errors.New("database not initialized")
}
@ -230,11 +230,11 @@ func (db *database) execContext(c context.Context, query string, args ...interfa
return db.db.ExecContext(ctx, query, args...)
}
func (db *database) query(query string, args ...interface{}) (*sql.Rows, error) {
func (db *database) query(query string, args ...any) (*sql.Rows, error) {
return db.queryContext(context.Background(), query, args...)
}
func (db *database) queryContext(c context.Context, query string, args ...interface{}) (rows *sql.Rows, err error) {
func (db *database) queryContext(c context.Context, query string, args ...any) (rows *sql.Rows, err error) {
if db == nil || db.db == nil {
return nil, errors.New("database not initialized")
}
@ -253,11 +253,11 @@ func (db *database) queryContext(c context.Context, query string, args ...interf
return
}
func (db *database) queryRow(query string, args ...interface{}) (*sql.Row, error) {
func (db *database) queryRow(query string, args ...any) (*sql.Row, error) {
return db.queryRowContext(context.Background(), query, args...)
}
func (db *database) queryRowContext(c context.Context, query string, args ...interface{}) (row *sql.Row, err error) {
func (db *database) queryRowContext(c context.Context, query string, args ...any) (row *sql.Row, err error) {
if db == nil || db.db == nil {
return nil, errors.New("database not initialized")
}

@ -13,14 +13,14 @@ import (
const dbHooksBegin contextKey = "begin"
func (db *database) dbBefore(ctx context.Context, _ string, _ ...interface{}) context.Context {
func (db *database) dbBefore(ctx context.Context, _ string, _ ...any) context.Context {
if !db.debug {
return ctx
}
return context.WithValue(ctx, dbHooksBegin, time.Now())
}
func (db *database) dbAfter(ctx context.Context, query string, args ...interface{}) {
func (db *database) dbAfter(ctx context.Context, query string, args ...any) {
if !db.debug {
return
}
@ -55,7 +55,7 @@ func (db *database) dbAfter(ctx context.Context, query string, args ...interface
bufferpool.Put(logBuilder)
}
func argToString(arg interface{}) string {
func argToString(arg any) string {
val := cast.ToString(arg)
if val == "" {
val = fmt.Sprintf("%v", arg)

@ -14,7 +14,7 @@ import (
var dbMigrations embed.FS
func migrateDb(db *sql.DB, logging bool) error {
var sqlMigrations []interface{}
var sqlMigrations []any
err := fs.WalkDir(dbMigrations, "dbmigrations", func(path string, d fs.DirEntry, err error) error {
if err != nil || d.Type().IsDir() {
return err
@ -39,7 +39,7 @@ func migrateDb(db *sql.DB, logging bool) error {
return err
}
m, err := migrator.New(
migrator.WithLogger(migrator.LoggerFunc(func(s string, i ...interface{}) {
migrator.WithLogger(migrator.LoggerFunc(func(s string, i ...any) {
if logging {
log.Printf(s, i)
}

@ -2,8 +2,8 @@ package main
import "log"
func (a *goBlog) debug(msg ...interface{}) {
func (a *goBlog) debug(msg ...any) {
if a.cfg.Debug {
log.Println(append([]interface{}{"Debug:"}, msg...)...)
log.Println(append([]any{"Debug:"}, msg...)...)
}
}

@ -94,7 +94,7 @@ func (a *goBlog) serveEditorPost(w http.ResponseWriter, r *http.Request) {
case "updatepost":
buf := bufferpool.Get()
defer bufferpool.Put(buf)
err := json.NewEncoder(buf).Encode(map[string]interface{}{
err := json.NewEncoder(buf).Encode(map[string]any{
"action": actionUpdate,
"url": r.FormValue("url"),
"replace": map[string][]string{
@ -179,8 +179,8 @@ func (a *goBlog) editorMicropubPost(w http.ResponseWriter, r *http.Request, medi
func (*goBlog) editorPostTemplate(blog string, bc *configBlog) string {
builder := bufferpool.Get()
defer bufferpool.Put(builder)
marsh := func(param string, i interface{}) {
_ = yaml.NewEncoder(builder).Encode(map[string]interface{}{
marsh := func(param string, i any) {
_ = yaml.NewEncoder(builder).Encode(map[string]any{
param: i,
})
}

@ -4,7 +4,7 @@ import (
"net/http"
"sort"
"github.com/thoas/go-funk"
"github.com/samber/lo"
)
func (a *goBlog) serveEditorFiles(w http.ResponseWriter, r *http.Request) {
@ -26,13 +26,9 @@ func (a *goBlog) serveEditorFiles(w http.ResponseWriter, r *http.Request) {
return files[i].Time.After(files[j].Time)
})
// Find uses
fileNames, ok := funk.Map(files, func(f *mediaFile) string {
fileNames := lo.Map(files, func(f *mediaFile, _ int) string {
return f.Name
}).([]string)
if !ok {
a.serveError(w, r, "Failed to get file names", http.StatusInternalServerError)
return
}
})
uses, err := a.db.usesOfMediaFile(fileNames...)
if err != nil {
a.serveError(w, r, err.Error(), http.StatusInternalServerError)

@ -10,7 +10,7 @@ import (
gogeouri "git.jlel.se/jlelse/go-geouri"
"github.com/carlmjohnson/requests"
geojson "github.com/paulmach/go.geojson"
"github.com/thoas/go-funk"
"github.com/samber/lo"
"go.goblog.app/app/pkgs/bufferpool"
)
@ -23,9 +23,9 @@ func (a *goBlog) geoTitle(g *gogeouri.Geo, lang string) string {
return ""
}
f := fc.Features[0]
return strings.Join(funk.FilterString([]string{
return strings.Join(lo.Filter([]string{
f.PropertyMustString("name", ""), f.PropertyMustString("city", ""), f.PropertyMustString("state", ""), f.PropertyMustString("country", ""),
}, func(s string) bool { return s != "" }), ", ")
}, func(s string, _ int) bool { return s != "" }), ", ")
}
func (a *goBlog) photonReverse(lat, lon float64, lang string) (*geojson.FeatureCollection, error) {
@ -50,7 +50,7 @@ func (a *goBlog) photonReverse(lat, lon float64, lang string) (*geojson.FeatureC
rb := requests.URL("https://photon.komoot.io/reverse").Client(a.httpClient).UserAgent(appUserAgent).ToBytesBuffer(buf)
// Set parameters
rb.Param("lat", fmt.Sprintf("%v", lat)).Param("lon", fmt.Sprintf("%v", lon))
rb.Param("lang", funk.ShortIf(lang == "de" || lang == "fr" || lang == "it", lang, "en").(string)) // Photon only supports en, de, fr, it
rb.Param("lang", lo.If(lang == "de" || lang == "fr" || lang == "it", lang).Else("en")) // Photon only supports en, de, fr, it
// Do request
if err := rb.Fetch(context.Background()); err != nil {
return nil, err

@ -1,6 +1,6 @@
module go.goblog.app/app
go 1.17
go 1.18
require (
git.jlel.se/jlelse/go-geouri v0.0.0-20210525190615-a9c1d50f42d6
@ -42,20 +42,20 @@ require (
github.com/paulmach/go.geojson v1.4.0
github.com/posener/wstest v1.2.0
github.com/pquerna/otp v1.3.0
github.com/samber/lo v1.10.1
github.com/schollz/sqlite3dump v1.3.1
github.com/snabb/sitemap v1.0.0
github.com/spf13/cast v1.4.1
github.com/spf13/viper v1.10.1
github.com/stretchr/testify v1.7.0
github.com/stretchr/testify v1.7.1
github.com/tdewolff/minify/v2 v2.10.0
github.com/thoas/go-funk v0.9.2
github.com/tkrajina/gpxgo v1.2.1
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80
github.com/vcraescu/go-paginator v1.0.1-0.20201114172518-2cfc59fe05c2
github.com/yuin/goldmark v1.4.10
// master
github.com/yuin/goldmark-emoji v1.0.2-0.20210607094911-0487583eca38
golang.org/x/crypto v0.0.0-20220313003712-b769efc7c000
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd
golang.org/x/net v0.0.0-20220225172249-27dd8689420f
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/text v0.3.7
@ -128,6 +128,7 @@ require (
go4.org/intern v0.0.0-20211027215823-ae77deb06f29 // indirect
go4.org/mem v0.0.0-20210711025021-927187094b94 // indirect
go4.org/unsafe/assume-no-moving-gc v0.0.0-20211027215541-db492cf91b37 // indirect
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 // indirect
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 // indirect

@ -369,6 +369,7 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/paulmach/go.geojson v1.4.0 h1:5x5moCkCtDo5x8af62P9IOAYGQcYHtxz2QJ3x1DoCgY=
github.com/paulmach/go.geojson v1.4.0/go.mod h1:YaKx1hKpWF+T2oj2lFJPsW/t1Q5e1jQI61eoQSTwpIs=
github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
@ -388,6 +389,8 @@ github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.8.1-0.20211023094830-115ce09fd6b4 h1:Ha8xCaq6ln1a+R91Km45Oq6lPXj2Mla6CRJYcuV2h1w=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/samber/lo v1.10.1 h1:0D3h7i0U3hRAbaCeQ82DLe67n0A7Bbl0/cEoWqFGp+U=
github.com/samber/lo v1.10.1/go.mod h1:2I7tgIv8Q1SG2xEIkRq0F2i2zgxVpnyPOP0d3Gj2r+A=
github.com/schollz/sqlite3dump v1.3.1 h1:QXizJ7XEJ7hggjqjZ3YRtF3+javm8zKtzNByYtEkPRA=
github.com/schollz/sqlite3dump v1.3.1/go.mod h1:mzSTjZpJH4zAb1FN3iNlhWPbbdyeBpOaTW0hukyMHyI=
github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg=
@ -413,8 +416,9 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tailscale/certstore v0.0.0-20210528134328-066c94b793d3 h1:fEubocuQkrlcuYeXelhYq/YcKvVVe1Ah7saQEtj98Mo=
@ -431,8 +435,7 @@ github.com/tdewolff/parse/v2 v2.5.27 h1:PL3LzzXaOpmdrknnOlIeO2muIBHAwiKp6TxN1RbU
github.com/tdewolff/parse/v2 v2.5.27/go.mod h1:WzaJpRSbwq++EIQHYIRTpbYKNA3gn9it1Ik++q4zyho=
github.com/tdewolff/test v1.0.6 h1:76mzYJQ83Op284kMT+63iCNCI7NEERsIN8dLM+RiKr4=
github.com/tdewolff/test v1.0.6/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
github.com/thoas/go-funk v0.9.2 h1:oKlNYv0AY5nyf9g+/GhMgS/UO2ces0QRdPKwkhY3VCk=
github.com/thoas/go-funk v0.9.2/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q=
github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M=
github.com/tkrajina/gpxgo v1.2.1 h1:MJJtT4Re5btDGg89brFDrUP3EWz+cBmyo8pQwV0ZOak=
github.com/tkrajina/gpxgo v1.2.1/go.mod h1:795sjVRFo5wWyN6oOZp0RYienGGBJjpAlgOz2nCngA0=
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 h1:nrZ3ySNYwJbSpD6ce9duiP+QkD3JuLCcWkdaehUS/3Y=
@ -483,8 +486,8 @@ golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWP
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220313003712-b769efc7c000 h1:SL+8VVnkqyshUSz5iNnXtrBQzvFF2SkROm6t5RczFAE=
golang.org/x/crypto v0.0.0-20220313003712-b769efc7c000/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38=
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -495,6 +498,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM=
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@ -516,8 +521,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57 h1:LQmS1nU0twXLA96Kt7U9qtHJEbBk3z6Q0V4UXjZkpr4=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -801,8 +806,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI=
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=

@ -25,7 +25,7 @@ func (a *goBlog) postPostHooks(p *post) {
if hc := a.cfg.Hooks; hc != nil {
for _, cmdTmplString := range hc.PostPost {
go func(p *post, cmdTmplString string) {
a.cfg.Hooks.executeTemplateCommand("post-post", cmdTmplString, map[string]interface{}{
a.cfg.Hooks.executeTemplateCommand("post-post", cmdTmplString, map[string]any{
"URL": a.fullPostURL(p),
"Post": p,
})
@ -42,7 +42,7 @@ func (a *goBlog) postUpdateHooks(p *post) {
if hc := a.cfg.Hooks; hc != nil {
for _, cmdTmplString := range hc.PostUpdate {
go func(p *post, cmdTmplString string) {
a.cfg.Hooks.executeTemplateCommand("post-update", cmdTmplString, map[string]interface{}{
a.cfg.Hooks.executeTemplateCommand("post-update", cmdTmplString, map[string]any{
"URL": a.fullPostURL(p),
"Post": p,
})
@ -58,7 +58,7 @@ func (a *goBlog) postDeleteHooks(p *post) {
if hc := a.cfg.Hooks; hc != nil {
for _, cmdTmplString := range hc.PostDelete {
go func(p *post, cmdTmplString string) {
a.cfg.Hooks.executeTemplateCommand("post-delete", cmdTmplString, map[string]interface{}{
a.cfg.Hooks.executeTemplateCommand("post-delete", cmdTmplString, map[string]any{
"URL": a.fullPostURL(p),
"Post": p,
})
@ -74,7 +74,7 @@ func (a *goBlog) postUndeleteHooks(p *post) {
if hc := a.cfg.Hooks; hc != nil {
for _, cmdTmplString := range hc.PostUndelete {
go func(p *post, cmdTmplString string) {
a.cfg.Hooks.executeTemplateCommand("post-undelete", cmdTmplString, map[string]interface{}{
a.cfg.Hooks.executeTemplateCommand("post-undelete", cmdTmplString, map[string]any{
"URL": a.fullPostURL(p),
"Post": p,
})
@ -86,7 +86,7 @@ func (a *goBlog) postUndeleteHooks(p *post) {
}
}
func (cfg *configHooks) executeTemplateCommand(hookType string, tmpl string, data map[string]interface{}) {
func (cfg *configHooks) executeTemplateCommand(hookType string, tmpl string, data map[string]any) {
cmdTmpl, err := template.New("cmd").Parse(tmpl)
if err != nil {
log.Println("Failed to parse cmd template:", err.Error())

@ -6,7 +6,6 @@ import (
"net/http"
"github.com/carlmjohnson/requests"
"github.com/thoas/go-funk"
)
// Implement support for the IndexNow protocol
@ -78,7 +77,7 @@ func (a *goBlog) indexNowKey() []byte {
}
if keyBytes == nil {
// Generate 128 character key with hexadecimal characters
keyBytes = []byte(funk.RandomString(128, []rune("0123456789abcdef")))
keyBytes = []byte(randomString(128, []rune("0123456789abcdef")))
// Store key in database
err = a.db.cachePersistently("indexnowkey", keyBytes)
if err != nil {

@ -221,7 +221,7 @@ func (app *goBlog) initComponents(logging bool) {
}
}
func (a *goBlog) logErrAndQuit(v ...interface{}) {
func (a *goBlog) logErrAndQuit(v ...any) {
log.Println(v...)
a.shutdown.ShutdownAndWait()
os.Exit(1)

@ -185,7 +185,7 @@ func (c *customRenderer) renderImage(w util.BufWriter, source []byte, node ast.N
}
hb := newHtmlBuilder(w)
hb.writeElementOpen("a", "href", dest)
imgEls := []interface{}{"src", dest, "alt", string(n.Text(source)), "loading", "lazy"}
imgEls := []any{"src", dest, "alt", string(n.Text(source)), "loading", "lazy"}
if len(n.Title) > 0 {
imgEls = append(imgEls, "title", string(n.Title))
}

@ -67,7 +67,7 @@ func (sp *shortpixel) compress(url string, upload mediaStorageSaveFunc, hc *http
URL("https://api.shortpixel.com/v2/reducer-sync.php").
Client(hc).
Method(http.MethodPost).
BodyJSON(map[string]interface{}{
BodyJSON(map[string]any{
"key": sp.key,
"plugin_version": "GB001",
"lossy": 1,
@ -106,8 +106,8 @@ func (tf *tinify) compress(url string, upload mediaStorageSaveFunc, hc *http.Cli
Client(hc).
Method(http.MethodPost).
BasicAuth("api", tf.key).
BodyJSON(map[string]interface{}{
"source": map[string]interface{}{
BodyJSON(map[string]any{
"source": map[string]any{
"url": url,
},
}).
@ -130,8 +130,8 @@ func (tf *tinify) compress(url string, upload mediaStorageSaveFunc, hc *http.Cli
Client(hc).
Method(http.MethodPost).
BasicAuth("api", tf.key).
BodyJSON(map[string]interface{}{
"resize": map[string]interface{}{
BodyJSON(map[string]any{
"resize": map[string]any{
"method": "fit",
"width": defaultCompressionWidth,
"height": defaultCompressionHeight,

@ -46,7 +46,7 @@ func Test_compress(t *testing.T) {
requestBody, _ := io.ReadAll(r.Body)
defer r.Body.Close()
var requestJson map[string]interface{}
var requestJson map[string]any
err := json.Unmarshal(requestBody, &requestJson)
require.Nil(t, err)
require.NotNil(t, requestJson)

@ -11,8 +11,8 @@ import (
"strings"
"time"
"github.com/samber/lo"
"github.com/spf13/cast"
"github.com/thoas/go-funk"
"go.goblog.app/app/pkgs/bufferpool"
"go.goblog.app/app/pkgs/contenttype"
"gopkg.in/yaml.v3"
@ -21,7 +21,7 @@ import (
const micropubPath = "/micropub"
func (a *goBlog) serveMicropubQuery(w http.ResponseWriter, r *http.Request) {
var result interface{}
var result any
switch query := r.URL.Query(); query.Get("q") {
case "config":
type micropubConfig struct {
@ -66,7 +66,7 @@ func (a *goBlog) serveMicropubQuery(w http.ResponseWriter, r *http.Request) {
}
allCategories = append(allCategories, values...)
}
result = map[string]interface{}{"categories": allCategories}
result = map[string]any{"categories": allCategories}
default:
a.serve404(w, r)
return
@ -231,30 +231,30 @@ const (
)
type microformatItem struct {
Type []string `json:"type,omitempty"`
URL string `json:"url,omitempty"`
Action micropubAction `json:"action,omitempty"`
Properties *microformatProperties `json:"properties,omitempty"`
Replace map[string][]interface{} `json:"replace,omitempty"`
Add map[string][]interface{} `json:"add,omitempty"`
Delete interface{} `json:"delete,omitempty"`
Type []string `json:"type,omitempty"`
URL string `json:"url,omitempty"`
Action micropubAction `json:"action,omitempty"`
Properties *microformatProperties `json:"properties,omitempty"`
Replace map[string][]any `json:"replace,omitempty"`
Add map[string][]any `json:"add,omitempty"`
Delete any `json:"delete,omitempty"`
}
type microformatProperties struct {
Name []string `json:"name,omitempty"`
Published []string `json:"published,omitempty"`
Updated []string `json:"updated,omitempty"`
PostStatus []string `json:"post-status,omitempty"`
Visibility []string `json:"visibility,omitempty"`
Category []string `json:"category,omitempty"`
Content []string `json:"content,omitempty"`
URL []string `json:"url,omitempty"`
InReplyTo []string `json:"in-reply-to,omitempty"`
LikeOf []string `json:"like-of,omitempty"`
BookmarkOf []string `json:"bookmark-of,omitempty"`
MpSlug []string `json:"mp-slug,omitempty"`
Photo []interface{} `json:"photo,omitempty"`
Audio []string `json:"audio,omitempty"`
Name []string `json:"name,omitempty"`
Published []string `json:"published,omitempty"`
Updated []string `json:"updated,omitempty"`
PostStatus []string `json:"post-status,omitempty"`
Visibility []string `json:"visibility,omitempty"`
Category []string `json:"category,omitempty"`
Content []string `json:"content,omitempty"`
URL []string `json:"url,omitempty"`
InReplyTo []string `json:"in-reply-to,omitempty"`
LikeOf []string `json:"like-of,omitempty"`
BookmarkOf []string `json:"bookmark-of,omitempty"`
MpSlug []string `json:"mp-slug,omitempty"`
Photo []any `json:"photo,omitempty"`
Audio []string `json:"audio,omitempty"`
}
func (a *goBlog) micropubParsePostParamsMfItem(entry *post, mf *microformatItem) error {
@ -314,7 +314,7 @@ func (a *goBlog) micropubParsePostParamsMfItem(entry *post, mf *microformatItem)
if theString, justString := photo.(string); justString {
entry.Parameters[a.cfg.Micropub.PhotoParam] = append(entry.Parameters[a.cfg.Micropub.PhotoParam], theString)
entry.Parameters[a.cfg.Micropub.PhotoDescriptionParam] = append(entry.Parameters[a.cfg.Micropub.PhotoDescriptionParam], "")
} else if thePhoto, isPhoto := photo.(map[string]interface{}); isPhoto {
} else if thePhoto, isPhoto := photo.(map[string]any); isPhoto {
entry.Parameters[a.cfg.Micropub.PhotoParam] = append(entry.Parameters[a.cfg.Micropub.PhotoParam], cast.ToString(thePhoto["value"]))
entry.Parameters[a.cfg.Micropub.PhotoDescriptionParam] = append(entry.Parameters[a.cfg.Micropub.PhotoDescriptionParam], cast.ToString(thePhoto["alt"]))
}
@ -331,7 +331,7 @@ func (a *goBlog) computeExtraPostParameters(p *post) error {
if split := strings.Split(p.Content, "---\n"); len(split) >= 3 && strings.TrimSpace(split[0]) == "" {
// Contains frontmatter
fm := split[1]
meta := map[string]interface{}{}
meta := map[string]any{}
err := yaml.Unmarshal([]byte(fm), &meta)
if err != nil {
return err
@ -340,7 +340,7 @@ func (a *goBlog) computeExtraPostParameters(p *post) error {
for key, value := range meta {
// Delete existing content - replace
p.Parameters[key] = []string{}
if a, ok := value.([]interface{}); ok {
if a, ok := value.([]any); ok {
for _, ae := range a {
p.Parameters[key] = append(p.Parameters[key], cast.ToString(ae))
}
@ -534,7 +534,7 @@ func (a *goBlog) micropubUpdate(w http.ResponseWriter, r *http.Request, u string
http.Redirect(w, r, a.fullPostURL(p), http.StatusNoContent)
}
func (a *goBlog) micropubUpdateReplace(p *post, replace map[string][]interface{}) {
func (a *goBlog) micropubUpdateReplace(p *post, replace map[string][]any) {
if content, ok := replace["content"]; ok && len(content) > 0 {
p.Content = cast.ToStringSlice(content)[0]
}
@ -578,7 +578,7 @@ func (a *goBlog) micropubUpdateReplace(p *post, replace map[string][]interface{}
// TODO: photos
}
func (a *goBlog) micropubUpdateAdd(p *post, add map[string][]interface{}) {
func (a *goBlog) micropubUpdateAdd(p *post, add map[string][]any) {
for key, value := range add {
switch key {
case "content":
@ -602,11 +602,11 @@ func (a *goBlog) micropubUpdateAdd(p *post, add map[string][]interface{}) {
}
}
func (a *goBlog) micropubUpdateDelete(p *post, del interface{}) {
func (a *goBlog) micropubUpdateDelete(p *post, del any) {
if del == nil {
return
}
deleteProperties, ok := del.([]interface{})
deleteProperties, ok := del.([]any)
if ok {
// Completely remove properties
for _, prop := range deleteProperties {
@ -637,7 +637,7 @@ func (a *goBlog) micropubUpdateDelete(p *post, del interface{}) {
// Return
return
}
toDelete, ok := del.(map[string]interface{})
toDelete, ok := del.(map[string]any)
if ok {
// Only delete parts of properties
for key, values := range toDelete {
@ -661,8 +661,8 @@ func (a *goBlog) micropubUpdateDelete(p *post, del interface{}) {
// TODO: Support partial deletes of more properties
case "category":
delValues := cast.ToStringSlice(values)
p.Parameters[a.cfg.Micropub.CategoryParam] = funk.FilterString(p.Parameters[a.cfg.Micropub.CategoryParam], func(s string) bool {
return !funk.ContainsString(delValues, s)
p.Parameters[a.cfg.Micropub.CategoryParam] = lo.Filter(p.Parameters[a.cfg.Micropub.CategoryParam], func(s string, _ int) bool {
return !lo.Contains(delValues, s)
})
}
}

@ -11,8 +11,8 @@ import (
func (a *goBlog) serveNodeInfoDiscover(w http.ResponseWriter, r *http.Request) {
buf := bufferpool.Get()
defer bufferpool.Put(buf)
err := json.NewEncoder(buf).Encode(map[string]interface{}{
"links": []map[string]interface{}{
err := json.NewEncoder(buf).Encode(map[string]any{
"links": []map[string]any{
{
"href": a.getFullAddress("/nodeinfo"),
"rel": "http://nodeinfo.diaspora.software/ns/schema/2.1",
@ -35,14 +35,14 @@ func (a *goBlog) serveNodeInfo(w http.ResponseWriter, r *http.Request) {
})
buf := bufferpool.Get()
defer bufferpool.Put(buf)
err := json.NewEncoder(buf).Encode(map[string]interface{}{
err := json.NewEncoder(buf).Encode(map[string]any{
"version": "2.1",
"software": map[string]interface{}{
"software": map[string]any{
"name": "goblog",
"repository": "https://go.goblog.app/app",
},
"usage": map[string]interface{}{
"users": map[string]interface{}{
"usage": map[string]any{
"users": map[string]any{
"total": len(a.cfg.Blogs),
},
"localPosts": localPosts,
@ -52,7 +52,7 @@ func (a *goBlog) serveNodeInfo(w http.ResponseWriter, r *http.Request) {
"micropub",
"webmention",
},
"metadata": map[string]interface{}{},
"metadata": map[string]any{},
})
if err != nil {
a.serveError(w, r, "", http.StatusInternalServerError)

@ -56,7 +56,7 @@ type notificationsRequestConfig struct {
offset, limit int
}
func buildNotificationsQuery(config *notificationsRequestConfig) (query string, args []interface{}) {
func buildNotificationsQuery(config *notificationsRequestConfig) (query string, args []any) {
queryBuilder := bufferpool.Get()
defer bufferpool.Put(queryBuilder)
queryBuilder.WriteString("select id, time, text from notifications order by id desc")
@ -110,7 +110,7 @@ func (p *notificationsPaginationAdapter) Nums() (int64, error) {
return p.nums, nil
}
func (p *notificationsPaginationAdapter) Slice(offset, length int, data interface{}) error {
func (p *notificationsPaginationAdapter) Slice(offset, length int, data any) error {
modifiedConfig := *p.config
modifiedConfig.offset = offset
modifiedConfig.limit = length

@ -26,7 +26,7 @@ func (db *database) retrievePersistentCacheContext(c context.Context, key string
if db == nil {
return nil, errors.New("database is nil")
}
d, err, _ := db.pc.Do(key, func() (interface{}, error) {
d, err, _ := db.pc.Do(key, func() (any, error) {
if row, err := db.queryRowContext(c, "select data from persistent_cache where key = @key", sql.Named("key", key)); err != nil {
return nil, err
} else {

@ -6,7 +6,7 @@ import (
)
var bufferPool = sync.Pool{
New: func() interface{} {
New: func() any {
return new(bytes.Buffer)
},
}

@ -32,7 +32,7 @@ func newConfig() *config {
}
// SetOption implements renderer.SetOptioner.
func (c *config) SetOption(name renderer.OptionName, value interface{}) {
func (c *config) SetOption(name renderer.OptionName, value any) {
c.Config.SetOption(name, value)
}

@ -11,7 +11,7 @@ import (
"github.com/klauspost/compress/flate"
"github.com/klauspost/compress/gzip"
"github.com/thoas/go-funk"
"github.com/samber/lo"
"go.goblog.app/app/pkgs/contenttype"
)
@ -48,7 +48,7 @@ type Compressor struct {
// The mapping of pooled encoders to pools.
pooledEncoders map[string]*sync.Pool
// The set of content types allowed to be compressed.
allowedTypes map[string]interface{}
allowedTypes map[string]any
// The list of encoders in order of decreasing precedence.
encodingPrecedence []string
// The compression level.
@ -62,8 +62,8 @@ type Compressor struct {
func NewCompressor(level int, types ...string) *Compressor {