Rework and test the geo title feature

This commit is contained in:
Jan-Lukas Else 2022-02-22 19:47:12 +01:00
parent 0f1408fe3e
commit 63a069cec8
3 changed files with 95 additions and 23 deletions

2
app.go
View File

@ -41,6 +41,8 @@ type goBlog struct {
db *database db *database
// Errors // Errors
errorCheckMediaTypes []ct.MediaType errorCheckMediaTypes []ct.MediaType
// Geo
photonMutex sync.Mutex
// Hooks // Hooks
pPostHooks []postHookFunc pPostHooks []postHookFunc
pUpdateHooks []postHookFunc pUpdateHooks []postHookFunc

56
geo.go
View File

@ -1,9 +1,9 @@
package main package main
import ( import (
"bytes"
"context" "context"
"embed" "embed"
"encoding/json"
"fmt" "fmt"
"strings" "strings"
@ -11,47 +11,57 @@ import (
"github.com/carlmjohnson/requests" "github.com/carlmjohnson/requests"
geojson "github.com/paulmach/go.geojson" geojson "github.com/paulmach/go.geojson"
"github.com/thoas/go-funk" "github.com/thoas/go-funk"
"go.goblog.app/app/pkgs/bufferpool"
) )
func (a *goBlog) geoTitle(g *gogeouri.Geo, lang string) string { func (a *goBlog) geoTitle(g *gogeouri.Geo, lang string) string {
if name, ok := g.Parameters["name"]; ok && len(name) > 0 && name[0] != "" { if name, ok := g.Parameters["name"]; ok && len(name) > 0 && name[0] != "" {
return name[0] return name[0]
} }
ba, err := a.photonReverse(g.Latitude, g.Longitude, lang) fc, err := a.photonReverse(g.Latitude, g.Longitude, lang)
if err != nil {
return ""
}
fc, err := geojson.UnmarshalFeatureCollection(ba)
if err != nil || len(fc.Features) < 1 { if err != nil || len(fc.Features) < 1 {
return "" return ""
} }
f := fc.Features[0] f := fc.Features[0]
name := f.PropertyMustString("name", "") return strings.Join(funk.FilterString([]string{
city := f.PropertyMustString("city", "") f.PropertyMustString("name", ""), f.PropertyMustString("city", ""), f.PropertyMustString("state", ""), f.PropertyMustString("country", ""),
state := f.PropertyMustString("state", "") }, func(s string) bool { return s != "" }), ", ")
country := f.PropertyMustString("country", "")
return strings.Join(funk.FilterString([]string{name, city, state, country}, func(s string) bool { return s != "" }), ", ")
} }
func (a *goBlog) photonReverse(lat, lon float64, lang string) ([]byte, error) { func (a *goBlog) photonReverse(lat, lon float64, lang string) (*geojson.FeatureCollection, error) {
// Only allow one concurrent request
a.photonMutex.Lock()
defer a.photonMutex.Unlock()
// Create feature collection
fc := geojson.NewFeatureCollection()
// Check cache
cacheKey := fmt.Sprintf("photon-%v-%v-%v", lat, lon, lang) cacheKey := fmt.Sprintf("photon-%v-%v-%v", lat, lon, lang)
cache, _ := a.db.retrievePersistentCache(cacheKey) if cache, _ := a.db.retrievePersistentCache(cacheKey); cache != nil {
if cache != nil { // Cache hit, unmarshal and return
return cache, nil if err := json.Unmarshal(cache, fc); err != nil {
return nil, err
}
return fc, nil
} }
var buf bytes.Buffer // No cache, fetch from Photon
rb := requests.URL("https://photon.komoot.io/reverse").Client(a.httpClient).UserAgent(appUserAgent).ToBytesBuffer(&buf) buf := bufferpool.Get()
defer bufferpool.Put(buf)
// Create request
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("lat", fmt.Sprintf("%v", lat)).Param("lon", fmt.Sprintf("%v", lon))
if lang == "de" || lang == "fr" || lang == "it" { rb.Param("lang", funk.ShortIf(lang == "de" || lang == "fr" || lang == "it", lang, "en").(string)) // Photon only supports en, de, fr, it
rb.Param("lang", lang) // Do request
} else {
rb.Param("lang", "en")
}
if err := rb.Fetch(context.Background()); err != nil { if err := rb.Fetch(context.Background()); err != nil {
return nil, err return nil, err
} }
// Cache response
_ = a.db.cachePersistently(cacheKey, buf.Bytes()) _ = a.db.cachePersistently(cacheKey, buf.Bytes())
return buf.Bytes(), nil // Unmarshal response
if err := json.NewDecoder(buf).Decode(fc); err != nil {
return nil, err
}
return fc, nil
} }
func geoOSMLink(g *gogeouri.Geo) string { func geoOSMLink(g *gogeouri.Geo) string {

60
geo_test.go Normal file
View File

@ -0,0 +1,60 @@
package main
import (
"net/http"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_geo(t *testing.T) {
fc := newFakeHttpClient()
app := &goBlog{
httpClient: fc.Client,
cfg: createDefaultTestConfig(t),
}
_ = app.initConfig()
_ = app.initDatabase(false)
defer app.db.close()
app.initComponents(false)
p := &post{
Blog: "en",
Parameters: map[string][]string{
"location": {"geo:52.51627,13.37737"},
},
}
gu := app.geoURI(p)
require.NotNil(t, gu)
assert.Equal(t, 52.51627, gu.Latitude)
assert.Equal(t, 13.37737, gu.Longitude)
osmLink := geoOSMLink(gu)
assert.Equal(t, "https://www.openstreetmap.org/?mlat=52.51627&mlon=13.37737", osmLink)
// Test original Photon request
fc.setFakeResponse(http.StatusOK, `{"features":[{"geometry":{"coordinates":[13.3774202,52.5162623],"type":"Point"},"type":"Feature","properties":{"osm_id":38345682,"osm_type":"W","extent":[13.3772052,52.5162623,13.3774202,52.5162476],"country":"Deutschland","osm_key":"highway","city":"Berlin","countrycode":"DE","district":"Mitte","osm_value":"service","postcode":"10117","name":"Platz des 18. März","type":"street"}}],"type":"FeatureCollection"}`)
gt := app.geoTitle(gu, "de")
require.NotNil(t, fc.req)
assert.Equal(t, "https://photon.komoot.io/reverse?lang=de&lat=52.51627&lon=13.37737", fc.req.URL.String())
assert.Equal(t, "Platz des 18. März, Berlin, Deutschland", gt)
// Test cache
fc.setFakeResponse(http.StatusOK, "")
gt = app.geoTitle(gu, "de")
assert.Nil(t, fc.req)
assert.Equal(t, "Platz des 18. März, Berlin, Deutschland", gt)
}