mirror of https://github.com/jlelse/GoBlog
Some improvements
This commit is contained in:
parent
d6518c3a5d
commit
d953b331c4
27
blogroll.go
27
blogroll.go
|
@ -2,13 +2,14 @@ package main
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"context"
|
||||
"log"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/carlmjohnson/requests"
|
||||
"github.com/kaorimatz/go-opml"
|
||||
"github.com/thoas/go-funk"
|
||||
"go.goblog.app/app/pkgs/contenttype"
|
||||
|
@ -64,22 +65,16 @@ func (a *goBlog) getBlogrollOutlines(blog string) ([]*opml.Outline, error) {
|
|||
if cache := a.db.loadOutlineCache(blog); cache != nil {
|
||||
return cache, nil
|
||||
}
|
||||
req, err := http.NewRequest(http.MethodGet, config.Opml, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rb := requests.URL(config.Opml).Client(a.httpClient).UserAgent(appUserAgent)
|
||||
if config.AuthHeader != "" && config.AuthValue != "" {
|
||||
req.Header.Set(config.AuthHeader, config.AuthValue)
|
||||
rb.Header(config.AuthHeader, config.AuthValue)
|
||||
}
|
||||
res, err := a.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if code := res.StatusCode; code < 200 || 300 <= code {
|
||||
return nil, fmt.Errorf("opml request not successful, status code: %d", code)
|
||||
}
|
||||
o, err := opml.Parse(res.Body)
|
||||
var o *opml.OPML
|
||||
err := rb.Handle(func(r *http.Response) (err error) {
|
||||
defer r.Body.Close()
|
||||
o, err = opml.Parse(r.Body)
|
||||
return
|
||||
}).Fetch(context.Background())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -117,7 +112,7 @@ func (db *database) loadOutlineCache(blog string) []*opml.Outline {
|
|||
if err != nil || data == nil {
|
||||
return nil
|
||||
}
|
||||
o, err := opml.NewParser(bytes.NewReader(data)).Parse()
|
||||
o, err := opml.Parse(bytes.NewReader(data))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/carlmjohnson/requests"
|
||||
"github.com/mmcdole/gofeed"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -17,6 +19,7 @@ func Test_feeds(t *testing.T) {
|
|||
_ = app.initDatabase(false)
|
||||
app.initComponents(false)
|
||||
app.d, _ = app.buildRouter()
|
||||
handlerClient := newHandlerClient(app.d)
|
||||
|
||||
err := app.createPost(&post{
|
||||
Path: "/testpost",
|
||||
|
@ -26,21 +29,18 @@ func Test_feeds(t *testing.T) {
|
|||
Parameters: map[string][]string{"title": {"Test Post"}},
|
||||
Content: "Test Content",
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, typ := range []feedType{rssFeed, atomFeed, jsonFeed} {
|
||||
req, _ := http.NewRequest(http.MethodGet, "http://localhost:8080/posts."+string(typ), nil)
|
||||
res, err := doHandlerRequest(req, app.d)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, http.StatusOK, res.StatusCode)
|
||||
|
||||
var feed *gofeed.Feed
|
||||
err := requests.URL("http://localhost:8080/posts." + string(typ)).Client(handlerClient).
|
||||
Handle(func(r *http.Response) (err error) {
|
||||
fp := gofeed.NewParser()
|
||||
feed, err := fp.Parse(res.Body)
|
||||
_ = res.Body.Close()
|
||||
|
||||
defer r.Body.Close()
|
||||
feed, err = fp.Parse(r.Body)
|
||||
return
|
||||
}).
|
||||
Fetch(context.Background())
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, feed)
|
||||
|
||||
|
|
36
geo.go
36
geo.go
|
@ -1,14 +1,14 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"embed"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
gogeouri "git.jlel.se/jlelse/go-geouri"
|
||||
"github.com/carlmjohnson/requests"
|
||||
geojson "github.com/paulmach/go.geojson"
|
||||
"github.com/thoas/go-funk"
|
||||
)
|
||||
|
@ -39,33 +39,19 @@ func (a *goBlog) photonReverse(lat, lon float64, lang string) ([]byte, error) {
|
|||
if cache != nil {
|
||||
return cache, nil
|
||||
}
|
||||
uv := url.Values{}
|
||||
uv.Set("lat", fmt.Sprintf("%v", lat))
|
||||
uv.Set("lon", fmt.Sprintf("%v", lon))
|
||||
var buf bytes.Buffer
|
||||
rb := requests.URL("https://photon.komoot.io/reverse").Client(a.httpClient).UserAgent(appUserAgent).ToBytesBuffer(&buf)
|
||||
rb.Param("lat", fmt.Sprintf("%v", lat)).Param("lon", fmt.Sprintf("%v", lon))
|
||||
if lang == "de" || lang == "fr" || lang == "it" {
|
||||
uv.Set("lang", lang)
|
||||
rb.Param("lang", lang)
|
||||
} else {
|
||||
uv.Set("lang", "en")
|
||||
rb.Param("lang", "en")
|
||||
}
|
||||
req, err := http.NewRequest(http.MethodGet, "https://photon.komoot.io/reverse?"+uv.Encode(), nil)
|
||||
if err != nil {
|
||||
if err := rb.Fetch(context.Background()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set(userAgent, appUserAgent)
|
||||
resp, err := a.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("response status code: %v", resp.StatusCode)
|
||||
}
|
||||
ba, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_ = a.db.cachePersistently(cacheKey, ba)
|
||||
return ba, nil
|
||||
_ = a.db.cachePersistently(cacheKey, buf.Bytes())
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func geoOSMLink(g *gogeouri.Geo) string {
|
||||
|
|
|
@ -15,9 +15,7 @@ type fakeHttpClient struct {
|
|||
|
||||
func newFakeHttpClient() *fakeHttpClient {
|
||||
fc := &fakeHttpClient{}
|
||||
fc.Client = &http.Client{
|
||||
Transport: &handlerRoundTripper{
|
||||
handler: http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
fc.Client = newHandlerClient(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
fc.req = r
|
||||
if fc.handler != nil {
|
||||
rec := httptest.NewRecorder()
|
||||
|
@ -31,9 +29,7 @@ func newFakeHttpClient() *fakeHttpClient {
|
|||
rw.WriteHeader(fc.res.StatusCode)
|
||||
_, _ = io.Copy(rw, rec.Body)
|
||||
}
|
||||
}),
|
||||
},
|
||||
}
|
||||
}))
|
||||
return fc
|
||||
}
|
||||
|
||||
|
|
|
@ -51,24 +51,14 @@ func Test_indieAuthServer(t *testing.T) {
|
|||
_ = app.initDatabase(false)
|
||||
app.initComponents(false)
|
||||
|
||||
app.ias.Client = &http.Client{
|
||||
Transport: &handlerRoundTripper{
|
||||
handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
app.ias.Client = newHandlerClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}),
|
||||
},
|
||||
}
|
||||
}))
|
||||
|
||||
iac := indieauth.NewClient(
|
||||
"https://example.com/",
|
||||
"https://example.com/redirect",
|
||||
&http.Client{
|
||||
Transport: &handlerRoundTripper{
|
||||
handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
app.d.ServeHTTP(w, r)
|
||||
}),
|
||||
},
|
||||
},
|
||||
newHandlerClient(app.d),
|
||||
)
|
||||
require.NotNil(t, iac)
|
||||
|
||||
|
|
|
@ -90,13 +90,14 @@ type tinify struct {
|
|||
}
|
||||
|
||||
func (tf *tinify) compress(url string, upload mediaStorageSaveFunc, hc *http.Client) (string, error) {
|
||||
tinifyErr := errors.New("failed to compress image using tinify")
|
||||
// Check url
|
||||
fileExtension, allowed := urlHasExt(url, "jpg", "jpeg", "png")
|
||||
if !allowed {
|
||||
return "", nil
|
||||
}
|
||||
// Compress
|
||||
compressedLocation := ""
|
||||
headers := http.Header{}
|
||||
err := requests.
|
||||
URL("https://api.tinify.com/shrink").
|
||||
Client(hc).
|
||||
|
@ -107,17 +108,16 @@ func (tf *tinify) compress(url string, upload mediaStorageSaveFunc, hc *http.Cli
|
|||
"url": url,
|
||||
},
|
||||
}).
|
||||
Handle(func(r *http.Response) error {
|
||||
compressedLocation = r.Header.Get("Location")
|
||||
if compressedLocation == "" {
|
||||
return errors.New("location header missing")
|
||||
}
|
||||
return nil
|
||||
}).
|
||||
ToHeaders(headers).
|
||||
Fetch(context.Background())
|
||||
if err != nil {
|
||||
log.Println("Tinify error:", err.Error())
|
||||
return "", errors.New("failed to compress image using tinify")
|
||||
return "", tinifyErr
|
||||
}
|
||||
compressedLocation := headers.Get("Location")
|
||||
if compressedLocation == "" {
|
||||
log.Println("Tinify error: location header missing")
|
||||
return "", tinifyErr
|
||||
}
|
||||
// Resize and download image
|
||||
var imgBuffer bytes.Buffer
|
||||
|
@ -137,7 +137,7 @@ func (tf *tinify) compress(url string, upload mediaStorageSaveFunc, hc *http.Cli
|
|||
Fetch(context.Background())
|
||||
if err != nil {
|
||||
log.Println("Tinify error:", err.Error())
|
||||
return "", errors.New("failed to compress image using tinify")
|
||||
return "", tinifyErr
|
||||
}
|
||||
// Upload compressed file
|
||||
return uploadCompressedFile(fileExtension, &imgBuffer, upload)
|
||||
|
|
|
@ -26,7 +26,9 @@ func (a *goBlog) checkDeletedPosts() {
|
|||
for _, post := range postsToDelete {
|
||||
// Check if post is deleted for more than 7 days
|
||||
if deleted, err := dateparse.ParseLocal(post.firstParameter("deleted")); err == nil && deleted.Add(time.Hour*24*7).Before(time.Now()) {
|
||||
a.deletePost(post.Path)
|
||||
if err := a.deletePost(post.Path); err != nil {
|
||||
log.Println("Error deleting post:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,12 +16,13 @@ func Test_checkDeletedPosts(t *testing.T) {
|
|||
app.initComponents(false)
|
||||
|
||||
// Create a post
|
||||
app.createPost(&post{
|
||||
err := app.createPost(&post{
|
||||
Content: "Test",
|
||||
Status: statusPublished,
|
||||
Path: "/testpost",
|
||||
Section: "posts",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Check if post count is 1
|
||||
count, err := app.db.countPosts(&postsRequestConfig{})
|
||||
|
@ -49,7 +50,8 @@ func Test_checkDeletedPosts(t *testing.T) {
|
|||
require.Equal(t, 1, count)
|
||||
|
||||
// Set deleted time to more than 7 days ago
|
||||
app.db.replacePostParam("/testpost", "deleted", []string{time.Now().Add(-time.Hour * 24 * 8).Format(time.RFC3339)})
|
||||
err = app.db.replacePostParam("/testpost", "deleted", []string{time.Now().Add(-time.Hour * 24 * 8).Format(time.RFC3339)})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Run deleter
|
||||
app.checkDeletedPosts()
|
||||
|
|
|
@ -34,11 +34,7 @@ func Test_serveDate(t *testing.T) {
|
|||
|
||||
require.NoError(t, err)
|
||||
|
||||
client := &http.Client{
|
||||
Transport: &handlerRoundTripper{
|
||||
handler: app.d,
|
||||
},
|
||||
}
|
||||
client := newHandlerClient(app.d)
|
||||
|
||||
var resString string
|
||||
|
||||
|
@ -128,11 +124,7 @@ func Test_servePost(t *testing.T) {
|
|||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
client := &http.Client{
|
||||
Transport: &handlerRoundTripper{
|
||||
handler: app.d,
|
||||
},
|
||||
}
|
||||
client := newHandlerClient(app.d)
|
||||
|
||||
var resString string
|
||||
|
||||
|
|
|
@ -36,11 +36,7 @@ func Test_sitemap(t *testing.T) {
|
|||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
client := &http.Client{
|
||||
Transport: &handlerRoundTripper{
|
||||
handler: app.d,
|
||||
},
|
||||
}
|
||||
client := newHandlerClient(app.d)
|
||||
|
||||
var resString string
|
||||
|
||||
|
|
9
utils.go
9
utils.go
|
@ -302,14 +302,15 @@ func (rt *handlerRoundTripper) RoundTrip(req *http.Request) (*http.Response, err
|
|||
return nil, errors.New("no handler")
|
||||
}
|
||||
|
||||
func newHandlerClient(handler http.Handler) *http.Client {
|
||||
return &http.Client{Transport: &handlerRoundTripper{handler: handler}}
|
||||
}
|
||||
|
||||
func doHandlerRequest(req *http.Request, handler http.Handler) (*http.Response, error) {
|
||||
client := &http.Client{
|
||||
Transport: &handlerRoundTripper{handler: handler},
|
||||
}
|
||||
if req.URL.Path == "" {
|
||||
req.URL.Path = "/"
|
||||
}
|
||||
return client.Do(req)
|
||||
return newHandlerClient(handler).Do(req)
|
||||
}
|
||||
|
||||
func saveToFile(reader io.Reader, fileName string) error {
|
||||
|
|
Loading…
Reference in New Issue