mirror of https://github.com/jlelse/GoBlog
Rework and test the geo title feature
This commit is contained in:
parent
0f1408fe3e
commit
63a069cec8
2
app.go
2
app.go
|
@ -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
56
geo.go
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue