mirror of https://github.com/jlelse/GoBlog
More strings.Builder and io.Pipe
This commit is contained in:
parent
ffe7065621
commit
e8a5e9eb0e
13
micropub.go
13
micropub.go
|
@ -13,7 +13,6 @@ import (
|
||||||
|
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
"github.com/spf13/cast"
|
"github.com/spf13/cast"
|
||||||
"go.goblog.app/app/pkgs/bufferpool"
|
|
||||||
"go.goblog.app/app/pkgs/contenttype"
|
"go.goblog.app/app/pkgs/contenttype"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
@ -76,14 +75,12 @@ func (a *goBlog) serveMicropubQuery(w http.ResponseWriter, r *http.Request) {
|
||||||
a.serve404(w, r)
|
a.serve404(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
buf := bufferpool.Get()
|
pr, pw := io.Pipe()
|
||||||
defer bufferpool.Put(buf)
|
go func() {
|
||||||
if err := json.NewEncoder(buf).Encode(result); err != nil {
|
_ = pw.CloseWithError(json.NewEncoder(pw).Encode(result))
|
||||||
a.serveError(w, r, "Failed to encode json", http.StatusInternalServerError)
|
}()
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Header().Set(contentType, contenttype.JSONUTF8)
|
w.Header().Set(contentType, contenttype.JSONUTF8)
|
||||||
_ = a.min.Get().Minify(contenttype.JSON, w, buf)
|
_ = pr.CloseWithError(a.min.Get().Minify(contenttype.JSON, w, pr))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *goBlog) getMicropubChannelsMap() []map[string]any {
|
func (a *goBlog) getMicropubChannelsMap() []map[string]any {
|
||||||
|
|
30
nodeinfo.go
30
nodeinfo.go
|
@ -5,29 +5,24 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"go.goblog.app/app/pkgs/bufferpool"
|
|
||||||
"go.goblog.app/app/pkgs/contenttype"
|
"go.goblog.app/app/pkgs/contenttype"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *goBlog) serveNodeInfoDiscover(w http.ResponseWriter, r *http.Request) {
|
func (a *goBlog) serveNodeInfoDiscover(w http.ResponseWriter, r *http.Request) {
|
||||||
buf := bufferpool.Get()
|
result := map[string]any{
|
||||||
defer bufferpool.Put(buf)
|
|
||||||
err := json.NewEncoder(buf).Encode(map[string]any{
|
|
||||||
"links": []map[string]any{
|
"links": []map[string]any{
|
||||||
{
|
{
|
||||||
"href": a.getFullAddress("/nodeinfo"),
|
"href": a.getFullAddress("/nodeinfo"),
|
||||||
"rel": "http://nodeinfo.diaspora.software/ns/schema/2.1",
|
"rel": "http://nodeinfo.diaspora.software/ns/schema/2.1",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
a.serveError(w, r, "", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
pr, pw := io.Pipe()
|
||||||
|
go func() {
|
||||||
|
_ = pw.CloseWithError(json.NewEncoder(pw).Encode(result))
|
||||||
|
}()
|
||||||
w.Header().Set(contentType, contenttype.JSONUTF8)
|
w.Header().Set(contentType, contenttype.JSONUTF8)
|
||||||
mw := a.min.Get().Writer(contenttype.JSON, w)
|
_ = pr.CloseWithError(a.min.Get().Minify(contenttype.JSON, w, pr))
|
||||||
_, _ = io.Copy(mw, buf)
|
|
||||||
_ = mw.Close()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *goBlog) serveNodeInfo(w http.ResponseWriter, r *http.Request) {
|
func (a *goBlog) serveNodeInfo(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -35,9 +30,7 @@ func (a *goBlog) serveNodeInfo(w http.ResponseWriter, r *http.Request) {
|
||||||
status: []postStatus{statusPublished},
|
status: []postStatus{statusPublished},
|
||||||
visibility: []postVisibility{visibilityPublic},
|
visibility: []postVisibility{visibilityPublic},
|
||||||
})
|
})
|
||||||
buf := bufferpool.Get()
|
result := map[string]any{
|
||||||
defer bufferpool.Put(buf)
|
|
||||||
if err := json.NewEncoder(buf).Encode(map[string]any{
|
|
||||||
"version": "2.1",
|
"version": "2.1",
|
||||||
"software": map[string]any{
|
"software": map[string]any{
|
||||||
"name": "goblog",
|
"name": "goblog",
|
||||||
|
@ -55,10 +48,11 @@ func (a *goBlog) serveNodeInfo(w http.ResponseWriter, r *http.Request) {
|
||||||
"webmention",
|
"webmention",
|
||||||
},
|
},
|
||||||
"metadata": map[string]any{},
|
"metadata": map[string]any{},
|
||||||
}); err != nil {
|
|
||||||
a.serveError(w, r, "", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
pr, pw := io.Pipe()
|
||||||
|
go func() {
|
||||||
|
_ = pw.CloseWithError(json.NewEncoder(pw).Encode(result))
|
||||||
|
}()
|
||||||
w.Header().Set(contentType, contenttype.JSONUTF8)
|
w.Header().Set(contentType, contenttype.JSONUTF8)
|
||||||
_ = a.min.Get().Minify(contenttype.JSON, w, buf)
|
_ = pr.CloseWithError(a.min.Get().Minify(contenttype.JSON, w, pr))
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,9 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"go.goblog.app/app/pkgs/bufferpool"
|
|
||||||
"go.goblog.app/app/pkgs/contenttype"
|
"go.goblog.app/app/pkgs/contenttype"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -49,15 +49,13 @@ func (a *goBlog) serveOpenSearch(w http.ResponseWriter, r *http.Request) {
|
||||||
},
|
},
|
||||||
SearchForm: sURL,
|
SearchForm: sURL,
|
||||||
}
|
}
|
||||||
buf := bufferpool.Get()
|
pr, pw := io.Pipe()
|
||||||
defer bufferpool.Put(buf)
|
go func() {
|
||||||
_, _ = buf.WriteString(xml.Header)
|
_, _ = io.WriteString(pw, xml.Header)
|
||||||
if err := xml.NewEncoder(buf).Encode(openSearch); err != nil {
|
_ = pw.CloseWithError(xml.NewEncoder(pw).Encode(openSearch))
|
||||||
a.serveError(w, r, "", http.StatusInternalServerError)
|
}()
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Header().Set(contentType, "application/opensearchdescription+xml"+contenttype.CharsetUtf8Suffix)
|
w.Header().Set(contentType, "application/opensearchdescription+xml"+contenttype.CharsetUtf8Suffix)
|
||||||
_ = a.min.Get().Minify(contenttype.XML, w, buf)
|
_ = pr.CloseWithError(a.min.Get().Minify(contenttype.XML, w, pr))
|
||||||
}
|
}
|
||||||
|
|
||||||
func openSearchUrl(b *configBlog) string {
|
func openSearchUrl(b *configBlog) string {
|
||||||
|
|
|
@ -2,13 +2,13 @@ package highlighting
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/yuin/goldmark"
|
"github.com/yuin/goldmark"
|
||||||
"github.com/yuin/goldmark/ast"
|
"github.com/yuin/goldmark/ast"
|
||||||
"github.com/yuin/goldmark/renderer"
|
"github.com/yuin/goldmark/renderer"
|
||||||
"github.com/yuin/goldmark/renderer/html"
|
"github.com/yuin/goldmark/renderer/html"
|
||||||
"github.com/yuin/goldmark/util"
|
"github.com/yuin/goldmark/util"
|
||||||
"go.goblog.app/app/pkgs/bufferpool"
|
|
||||||
|
|
||||||
"github.com/alecthomas/chroma/v2"
|
"github.com/alecthomas/chroma/v2"
|
||||||
chromahtml "github.com/alecthomas/chroma/v2/formatters/html"
|
chromahtml "github.com/alecthomas/chroma/v2/formatters/html"
|
||||||
|
@ -60,8 +60,7 @@ func (r *htmlRenderer) renderFencedCodeBlock(w util.BufWriter, source []byte, no
|
||||||
n := node.(*ast.FencedCodeBlock)
|
n := node.(*ast.FencedCodeBlock)
|
||||||
|
|
||||||
// Read code block content.
|
// Read code block content.
|
||||||
buf := bufferpool.Get()
|
var buf strings.Builder
|
||||||
defer bufferpool.Put(buf)
|
|
||||||
for _, line := range n.Lines().Sliced(0, n.Lines().Len()) {
|
for _, line := range n.Lines().Sliced(0, n.Lines().Len()) {
|
||||||
buf.Write(line.Value(source))
|
buf.Write(line.Value(source))
|
||||||
}
|
}
|
||||||
|
@ -70,7 +69,7 @@ func (r *htmlRenderer) renderFencedCodeBlock(w util.BufWriter, source []byte, no
|
||||||
if highlight(w, buf.String(), string(n.Language(source)), r.formatter) != nil {
|
if highlight(w, buf.String(), string(n.Language(source)), r.formatter) != nil {
|
||||||
// Highlight failed, fallback to plain text.
|
// Highlight failed, fallback to plain text.
|
||||||
_, _ = w.WriteString("<pre><code>")
|
_, _ = w.WriteString("<pre><code>")
|
||||||
r.Writer.RawWrite(w, buf.Bytes())
|
r.Writer.RawWrite(w, []byte(buf.String()))
|
||||||
_, _ = w.WriteString("</code></pre>\n")
|
_, _ = w.WriteString("</code></pre>\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
39
postsDb.go
39
postsDb.go
|
@ -206,8 +206,7 @@ func (db *database) savePost(p *post, o *postCreationOptions) error {
|
||||||
db.pcm.Lock()
|
db.pcm.Lock()
|
||||||
defer db.pcm.Unlock()
|
defer db.pcm.Unlock()
|
||||||
// Build SQL
|
// Build SQL
|
||||||
sqlBuilder := bufferpool.Get()
|
var sqlBuilder strings.Builder
|
||||||
defer bufferpool.Put(sqlBuilder)
|
|
||||||
var sqlArgs = []any{dbNoCache}
|
var sqlArgs = []any{dbNoCache}
|
||||||
// Start transaction
|
// Start transaction
|
||||||
sqlBuilder.WriteString("begin;")
|
sqlBuilder.WriteString("begin;")
|
||||||
|
@ -336,7 +335,7 @@ func (db *database) replacePostParam(path, param string, values []string) error
|
||||||
db.pcm.Lock()
|
db.pcm.Lock()
|
||||||
defer db.pcm.Unlock()
|
defer db.pcm.Unlock()
|
||||||
// Build SQL
|
// Build SQL
|
||||||
sqlBuilder := bufferpool.Get()
|
var sqlBuilder strings.Builder
|
||||||
var sqlArgs = []any{dbNoCache}
|
var sqlArgs = []any{dbNoCache}
|
||||||
// Start transaction
|
// Start transaction
|
||||||
sqlBuilder.WriteString("begin;")
|
sqlBuilder.WriteString("begin;")
|
||||||
|
@ -352,7 +351,6 @@ func (db *database) replacePostParam(path, param string, values []string) error
|
||||||
sqlBuilder.WriteString("commit;")
|
sqlBuilder.WriteString("commit;")
|
||||||
// Execute
|
// Execute
|
||||||
_, err := db.Exec(sqlBuilder.String(), sqlArgs...)
|
_, err := db.Exec(sqlBuilder.String(), sqlArgs...)
|
||||||
bufferpool.Put(sqlBuilder)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -387,8 +385,7 @@ type postsRequestConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildPostsQuery(c *postsRequestConfig, selection string) (query string, args []any) {
|
func buildPostsQuery(c *postsRequestConfig, selection string) (query string, args []any) {
|
||||||
queryBuilder := bufferpool.Get()
|
var queryBuilder strings.Builder
|
||||||
defer bufferpool.Put(queryBuilder)
|
|
||||||
// Selection
|
// Selection
|
||||||
queryBuilder.WriteString("select ")
|
queryBuilder.WriteString("select ")
|
||||||
queryBuilder.WriteString(selection)
|
queryBuilder.WriteString(selection)
|
||||||
|
@ -413,11 +410,11 @@ func buildPostsQuery(c *postsRequestConfig, selection string) (query string, arg
|
||||||
queryBuilder.WriteString(", ")
|
queryBuilder.WriteString(", ")
|
||||||
}
|
}
|
||||||
named := "status" + strconv.Itoa(i)
|
named := "status" + strconv.Itoa(i)
|
||||||
queryBuilder.WriteByte('@')
|
queryBuilder.WriteString("@")
|
||||||
queryBuilder.WriteString(named)
|
queryBuilder.WriteString(named)
|
||||||
args = append(args, sql.Named(named, status))
|
args = append(args, sql.Named(named, status))
|
||||||
}
|
}
|
||||||
queryBuilder.WriteByte(')')
|
queryBuilder.WriteString(")")
|
||||||
}
|
}
|
||||||
if c.visibility != nil && len(c.visibility) > 0 {
|
if c.visibility != nil && len(c.visibility) > 0 {
|
||||||
queryBuilder.WriteString(" and visibility in (")
|
queryBuilder.WriteString(" and visibility in (")
|
||||||
|
@ -426,11 +423,11 @@ func buildPostsQuery(c *postsRequestConfig, selection string) (query string, arg
|
||||||
queryBuilder.WriteString(", ")
|
queryBuilder.WriteString(", ")
|
||||||
}
|
}
|
||||||
named := "visibility" + strconv.Itoa(i)
|
named := "visibility" + strconv.Itoa(i)
|
||||||
queryBuilder.WriteByte('@')
|
queryBuilder.WriteString("@")
|
||||||
queryBuilder.WriteString(named)
|
queryBuilder.WriteString(named)
|
||||||
args = append(args, sql.Named(named, visibility))
|
args = append(args, sql.Named(named, visibility))
|
||||||
}
|
}
|
||||||
queryBuilder.WriteByte(')')
|
queryBuilder.WriteString(")")
|
||||||
}
|
}
|
||||||
if c.blog != "" {
|
if c.blog != "" {
|
||||||
queryBuilder.WriteString(" and blog = @blog")
|
queryBuilder.WriteString(" and blog = @blog")
|
||||||
|
@ -451,7 +448,7 @@ func buildPostsQuery(c *postsRequestConfig, selection string) (query string, arg
|
||||||
queryBuilder.WriteString(", ")
|
queryBuilder.WriteString(", ")
|
||||||
}
|
}
|
||||||
named := "param" + strconv.Itoa(i)
|
named := "param" + strconv.Itoa(i)
|
||||||
queryBuilder.WriteByte('@')
|
queryBuilder.WriteString("@")
|
||||||
queryBuilder.WriteString(named)
|
queryBuilder.WriteString(named)
|
||||||
args = append(args, param)
|
args = append(args, param)
|
||||||
}
|
}
|
||||||
|
@ -477,11 +474,11 @@ func buildPostsQuery(c *postsRequestConfig, selection string) (query string, arg
|
||||||
queryBuilder.WriteString(", ")
|
queryBuilder.WriteString(", ")
|
||||||
}
|
}
|
||||||
named := "section" + strconv.Itoa(i)
|
named := "section" + strconv.Itoa(i)
|
||||||
queryBuilder.WriteByte('@')
|
queryBuilder.WriteString("@")
|
||||||
queryBuilder.WriteString(named)
|
queryBuilder.WriteString(named)
|
||||||
args = append(args, sql.Named(named, section))
|
args = append(args, sql.Named(named, section))
|
||||||
}
|
}
|
||||||
queryBuilder.WriteByte(')')
|
queryBuilder.WriteString(")")
|
||||||
}
|
}
|
||||||
if c.publishedYear != 0 {
|
if c.publishedYear != 0 {
|
||||||
queryBuilder.WriteString(" and substr(tolocal(published), 1, 4) = @publishedyear")
|
queryBuilder.WriteString(" and substr(tolocal(published), 1, 4) = @publishedyear")
|
||||||
|
@ -522,8 +519,7 @@ func (d *database) loadPostParameters(posts []*post, parameters ...string) (err
|
||||||
}
|
}
|
||||||
// Build query
|
// Build query
|
||||||
sqlArgs := make([]any, 0)
|
sqlArgs := make([]any, 0)
|
||||||
queryBuilder := bufferpool.Get()
|
var queryBuilder strings.Builder
|
||||||
defer bufferpool.Put(queryBuilder)
|
|
||||||
queryBuilder.WriteString("select path, parameter, value from post_parameters where")
|
queryBuilder.WriteString("select path, parameter, value from post_parameters where")
|
||||||
// Paths
|
// Paths
|
||||||
queryBuilder.WriteString(" path in (")
|
queryBuilder.WriteString(" path in (")
|
||||||
|
@ -532,11 +528,11 @@ func (d *database) loadPostParameters(posts []*post, parameters ...string) (err
|
||||||
queryBuilder.WriteString(", ")
|
queryBuilder.WriteString(", ")
|
||||||
}
|
}
|
||||||
named := "path" + strconv.Itoa(i)
|
named := "path" + strconv.Itoa(i)
|
||||||
queryBuilder.WriteByte('@')
|
queryBuilder.WriteString("@")
|
||||||
queryBuilder.WriteString(named)
|
queryBuilder.WriteString(named)
|
||||||
sqlArgs = append(sqlArgs, sql.Named(named, p.Path))
|
sqlArgs = append(sqlArgs, sql.Named(named, p.Path))
|
||||||
}
|
}
|
||||||
queryBuilder.WriteByte(')')
|
queryBuilder.WriteString(")")
|
||||||
// Parameters
|
// Parameters
|
||||||
if len(parameters) > 0 {
|
if len(parameters) > 0 {
|
||||||
queryBuilder.WriteString(" and parameter in (")
|
queryBuilder.WriteString(" and parameter in (")
|
||||||
|
@ -545,11 +541,11 @@ func (d *database) loadPostParameters(posts []*post, parameters ...string) (err
|
||||||
queryBuilder.WriteString(", ")
|
queryBuilder.WriteString(", ")
|
||||||
}
|
}
|
||||||
named := "param" + strconv.Itoa(i)
|
named := "param" + strconv.Itoa(i)
|
||||||
queryBuilder.WriteByte('@')
|
queryBuilder.WriteString("@")
|
||||||
queryBuilder.WriteString(named)
|
queryBuilder.WriteString(named)
|
||||||
sqlArgs = append(sqlArgs, sql.Named(named, p))
|
sqlArgs = append(sqlArgs, sql.Named(named, p))
|
||||||
}
|
}
|
||||||
queryBuilder.WriteByte(')')
|
queryBuilder.WriteString(")")
|
||||||
}
|
}
|
||||||
// Order
|
// Order
|
||||||
queryBuilder.WriteString(" order by id")
|
queryBuilder.WriteString(" order by id")
|
||||||
|
@ -695,7 +691,7 @@ group by name;
|
||||||
|
|
||||||
func (db *database) usesOfMediaFile(names ...string) (counts []int, err error) {
|
func (db *database) usesOfMediaFile(names ...string) (counts []int, err error) {
|
||||||
sqlArgs := []any{dbNoCache}
|
sqlArgs := []any{dbNoCache}
|
||||||
nameValues := bufferpool.Get()
|
var nameValues strings.Builder
|
||||||
for i, n := range names {
|
for i, n := range names {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
nameValues.WriteString(", ")
|
nameValues.WriteString(", ")
|
||||||
|
@ -703,11 +699,10 @@ func (db *database) usesOfMediaFile(names ...string) (counts []int, err error) {
|
||||||
named := "name" + strconv.Itoa(i)
|
named := "name" + strconv.Itoa(i)
|
||||||
nameValues.WriteString("(@")
|
nameValues.WriteString("(@")
|
||||||
nameValues.WriteString(named)
|
nameValues.WriteString(named)
|
||||||
nameValues.WriteByte(')')
|
nameValues.WriteString(")")
|
||||||
sqlArgs = append(sqlArgs, sql.Named(named, n))
|
sqlArgs = append(sqlArgs, sql.Named(named, n))
|
||||||
}
|
}
|
||||||
rows, err := db.Query(fmt.Sprintf(mediaUseSql, nameValues.String()), sqlArgs...)
|
rows, err := db.Query(fmt.Sprintf(mediaUseSql, nameValues.String()), sqlArgs...)
|
||||||
bufferpool.Put(nameValues)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
18
reactions.go
18
reactions.go
|
@ -5,10 +5,10 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/dgraph-io/ristretto"
|
"github.com/dgraph-io/ristretto"
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
"go.goblog.app/app/pkgs/bufferpool"
|
|
||||||
"go.goblog.app/app/pkgs/contenttype"
|
"go.goblog.app/app/pkgs/contenttype"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -88,15 +88,12 @@ func (a *goBlog) getReactions(w http.ResponseWriter, r *http.Request) {
|
||||||
a.serveError(w, r, "", http.StatusInternalServerError)
|
a.serveError(w, r, "", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
buf := bufferpool.Get()
|
pr, pw := io.Pipe()
|
||||||
defer bufferpool.Put(buf)
|
go func() {
|
||||||
err = json.NewEncoder(buf).Encode(reactions)
|
_ = pw.CloseWithError(json.NewEncoder(pw).Encode(reactions))
|
||||||
if err != nil {
|
}()
|
||||||
a.serveError(w, r, "", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Header().Set(contentType, contenttype.JSONUTF8)
|
w.Header().Set(contentType, contenttype.JSONUTF8)
|
||||||
_, _ = io.Copy(w, buf)
|
_ = pr.CloseWithError(a.min.Get().Minify(contenttype.JSON, w, pr))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *goBlog) getReactionsFromDatabase(path string) (map[string]int, error) {
|
func (a *goBlog) getReactionsFromDatabase(path string) (map[string]int, error) {
|
||||||
|
@ -110,8 +107,7 @@ func (a *goBlog) getReactionsFromDatabase(path string) (map[string]int, error) {
|
||||||
// Get reactions
|
// Get reactions
|
||||||
res, err, _ := a.reactionsSfg.Do(path, func() (any, error) {
|
res, err, _ := a.reactionsSfg.Do(path, func() (any, error) {
|
||||||
// Build query
|
// Build query
|
||||||
sqlBuf := bufferpool.Get()
|
var sqlBuf strings.Builder
|
||||||
defer bufferpool.Put(sqlBuf)
|
|
||||||
sqlArgs := []any{}
|
sqlArgs := []any{}
|
||||||
sqlBuf.WriteString("select reaction, count from reactions where path=? and reaction in (")
|
sqlBuf.WriteString("select reaction, count from reactions where path=? and reaction in (")
|
||||||
sqlArgs = append(sqlArgs, path)
|
sqlArgs = append(sqlArgs, path)
|
||||||
|
|
|
@ -136,13 +136,13 @@ func Test_reactionsHighLevel(t *testing.T) {
|
||||||
rec = httptest.NewRecorder()
|
rec = httptest.NewRecorder()
|
||||||
app.getReactions(rec, req)
|
app.getReactions(rec, req)
|
||||||
assert.Equal(t, http.StatusOK, rec.Code)
|
assert.Equal(t, http.StatusOK, rec.Code)
|
||||||
assert.Equal(t, "{\"❤️\":1}\n", rec.Body.String())
|
assert.Equal(t, "{\"❤️\":1}", rec.Body.String())
|
||||||
|
|
||||||
// Get reactions for a non-existing post
|
// Get reactions for a non-existing post
|
||||||
req = httptest.NewRequest(http.MethodGet, "/?path=/non-existing-post", nil)
|
req = httptest.NewRequest(http.MethodGet, "/?path=/non-existing-post", nil)
|
||||||
rec = httptest.NewRecorder()
|
rec = httptest.NewRecorder()
|
||||||
app.getReactions(rec, req)
|
app.getReactions(rec, req)
|
||||||
assert.Equal(t, http.StatusOK, rec.Code)
|
assert.Equal(t, http.StatusOK, rec.Code)
|
||||||
assert.Equal(t, "{}\n", rec.Body.String())
|
assert.Equal(t, "{}", rec.Body.String())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
22
sitemap.go
22
sitemap.go
|
@ -3,12 +3,12 @@ package main
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/araddon/dateparse"
|
"github.com/araddon/dateparse"
|
||||||
"github.com/snabb/sitemap"
|
"github.com/snabb/sitemap"
|
||||||
"go.goblog.app/app/pkgs/bufferpool"
|
|
||||||
"go.goblog.app/app/pkgs/contenttype"
|
"go.goblog.app/app/pkgs/contenttype"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -174,18 +174,16 @@ func (a *goBlog) serveSitemapBlogPosts(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *goBlog) writeSitemapXML(w http.ResponseWriter, r *http.Request, sm any) {
|
func (a *goBlog) writeSitemapXML(w http.ResponseWriter, r *http.Request, sm any) {
|
||||||
buf := bufferpool.Get()
|
pr, pw := io.Pipe()
|
||||||
defer bufferpool.Put(buf)
|
go func() {
|
||||||
_, _ = buf.WriteString(xml.Header)
|
_, _ = io.WriteString(pw, xml.Header)
|
||||||
_, _ = buf.WriteString(`<?xml-stylesheet type="text/xsl" href="`)
|
_, _ = io.WriteString(pw, `<?xml-stylesheet type="text/xsl" href="`)
|
||||||
_, _ = buf.WriteString(a.assetFileName("sitemap.xsl"))
|
_, _ = io.WriteString(pw, a.assetFileName("sitemap.xsl"))
|
||||||
_, _ = buf.WriteString(`" ?>`)
|
_, _ = io.WriteString(pw, `" ?>`)
|
||||||
if err := xml.NewEncoder(buf).Encode(sm); err != nil {
|
_ = pw.CloseWithError(xml.NewEncoder(pw).Encode(sm))
|
||||||
a.serveError(w, r, "Failed to encode sitemap", http.StatusInternalServerError)
|
}()
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Header().Set(contentType, contenttype.XMLUTF8)
|
w.Header().Set(contentType, contenttype.XMLUTF8)
|
||||||
_ = a.min.Get().Minify(contenttype.XML, w, buf)
|
_ = pr.CloseWithError(a.min.Get().Minify(contenttype.XML, w, pr))
|
||||||
}
|
}
|
||||||
|
|
||||||
const sitemapDatePathsSql = `
|
const sitemapDatePathsSql = `
|
||||||
|
|
|
@ -5,9 +5,9 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||||
"go.goblog.app/app/pkgs/bufferpool"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *goBlog) initTelegram() {
|
func (a *goBlog) initTelegram() {
|
||||||
|
@ -135,8 +135,7 @@ func (tg *configTelegram) generateHTML(title, fullURL, shortURL string) (html st
|
||||||
if !tg.enabled() {
|
if !tg.enabled() {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
message := bufferpool.Get()
|
var message strings.Builder
|
||||||
defer bufferpool.Put(message)
|
|
||||||
if title != "" {
|
if title != "" {
|
||||||
message.WriteString(tgbotapi.EscapeText(tgbotapi.ModeHTML, title))
|
message.WriteString(tgbotapi.EscapeText(tgbotapi.ModeHTML, title))
|
||||||
message.WriteString("\n\n")
|
message.WriteString("\n\n")
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
"go.goblog.app/app/pkgs/bufferpool"
|
|
||||||
"go.goblog.app/app/pkgs/htmlbuilder"
|
"go.goblog.app/app/pkgs/htmlbuilder"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -65,7 +64,7 @@ func (a *goBlog) renderSummary(hb *htmlbuilder.HtmlBuilder, bc *configBlog, p *p
|
||||||
}
|
}
|
||||||
// Show link to full post
|
// Show link to full post
|
||||||
hb.WriteElementOpen("p")
|
hb.WriteElementOpen("p")
|
||||||
prefix := bufferpool.Get()
|
var prefix strings.Builder
|
||||||
if len(photos) > 0 {
|
if len(photos) > 0 {
|
||||||
// Contains photos
|
// Contains photos
|
||||||
prefix.WriteString("🖼️")
|
prefix.WriteString("🖼️")
|
||||||
|
@ -75,10 +74,9 @@ func (a *goBlog) renderSummary(hb *htmlbuilder.HtmlBuilder, bc *configBlog, p *p
|
||||||
prefix.WriteString("🗺️")
|
prefix.WriteString("🗺️")
|
||||||
}
|
}
|
||||||
if prefix.Len() > 0 {
|
if prefix.Len() > 0 {
|
||||||
prefix.WriteRune(' ')
|
prefix.WriteString(" ")
|
||||||
hb.WriteEscaped(prefix.String())
|
hb.WriteEscaped(prefix.String())
|
||||||
}
|
}
|
||||||
bufferpool.Put(prefix)
|
|
||||||
hb.WriteElementOpen("a", "class", "u-url", "href", p.Path)
|
hb.WriteElementOpen("a", "class", "u-url", "href", p.Path)
|
||||||
hb.WriteEscaped(a.ts.GetTemplateStringVariant(bc.Lang, "view"))
|
hb.WriteEscaped(a.ts.GetTemplateStringVariant(bc.Lang, "view"))
|
||||||
hb.WriteElementClose("a")
|
hb.WriteElementClose("a")
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.goblog.app/app/pkgs/bufferpool"
|
|
||||||
"go.goblog.app/app/pkgs/contenttype"
|
"go.goblog.app/app/pkgs/contenttype"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -231,8 +230,7 @@ type webmentionsRequestConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildWebmentionsQuery(config *webmentionsRequestConfig) (query string, args []any) {
|
func buildWebmentionsQuery(config *webmentionsRequestConfig) (query string, args []any) {
|
||||||
queryBuilder := bufferpool.Get()
|
var queryBuilder strings.Builder
|
||||||
defer bufferpool.Put(queryBuilder)
|
|
||||||
queryBuilder.WriteString("select id, source, target, url, created, title, content, author, status from webmentions ")
|
queryBuilder.WriteString("select id, source, target, url, created, title, content, author, status from webmentions ")
|
||||||
if config != nil {
|
if config != nil {
|
||||||
queryBuilder.WriteString("where 1")
|
queryBuilder.WriteString("where 1")
|
||||||
|
|
Loading…
Reference in New Issue