155 lines
4.4 KiB
Go
155 lines
4.4 KiB
Go
|
package geocode
|
||
|
|
||
|
import (
|
||
|
_ "fmt"
|
||
|
"github.com/codingsince1985/geo-golang"
|
||
|
"github.com/pocketbase/dbx"
|
||
|
"github.com/pocketbase/pocketbase"
|
||
|
"github.com/pocketbase/pocketbase/models"
|
||
|
"jubilee-server/structs"
|
||
|
"log"
|
||
|
|
||
|
"github.com/codingsince1985/geo-golang/openstreetmap"
|
||
|
)
|
||
|
|
||
|
// const opencageApiKey = "893ab539eca84b5ca7a54cb03ef23443"
|
||
|
|
||
|
func Geocode(app *pocketbase.PocketBase, latlong structs.LatLong) *structs.FormattedLocation {
|
||
|
|
||
|
log.Println("$$:Geocode", latlong)
|
||
|
log.Println("-- lat", latlong.Lat)
|
||
|
log.Println("-- long", latlong.Long)
|
||
|
|
||
|
formattedLocation := &structs.FormattedLocation{}
|
||
|
|
||
|
latlow := latlong.Lat - 0.001
|
||
|
lathigh := latlong.Lat + 0.001
|
||
|
|
||
|
longlow := latlong.Long - 0.001
|
||
|
longhigh := latlong.Long + 0.001
|
||
|
|
||
|
log.Printf("-- Between %+v,%+v to %+v,%+v\n", latlow, longlow, lathigh, longhigh)
|
||
|
|
||
|
dberr := app.Dao().DB().
|
||
|
Select("*").From("geocode").
|
||
|
Where(dbx.NewExp("lat >= {:latlow} and lat <= {:lathigh}", dbx.Params{"latlow": latlow, "lathigh": lathigh})).
|
||
|
AndWhere(dbx.NewExp("long >= {:longlow} and long <= {:longhigh}", dbx.Params{"longlow": longlow, "longhigh": longhigh})).One(&formattedLocation)
|
||
|
|
||
|
if dberr == nil {
|
||
|
// handle error
|
||
|
log.Printf("-- Cache hit geocode %+v,%+v\n", formattedLocation.Lat, formattedLocation.Long)
|
||
|
return formattedLocation
|
||
|
}
|
||
|
|
||
|
formattedLocation = tryGeocoder(openstreetmap.Geocoder(), latlong)
|
||
|
|
||
|
go func() {
|
||
|
err := saveLocationRec(app, *formattedLocation)
|
||
|
if err != nil {
|
||
|
log.Println(err)
|
||
|
|
||
|
}
|
||
|
}()
|
||
|
|
||
|
return formattedLocation
|
||
|
// tryGeocoder(opencage.Geocoder(opencageApiKey), latlong)
|
||
|
|
||
|
}
|
||
|
|
||
|
func tryGeocoder(geocoder geo.Geocoder, latlong structs.LatLong) *structs.FormattedLocation {
|
||
|
|
||
|
address, _ := geocoder.ReverseGeocode(latlong.Lat, latlong.Long)
|
||
|
|
||
|
if address != nil {
|
||
|
log.Printf("%+v\n", address)
|
||
|
|
||
|
return reformatGeocode(*address, latlong)
|
||
|
} else {
|
||
|
return new(structs.FormattedLocation)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func reformatGeocode(address geo.Address, latlong structs.LatLong) *structs.FormattedLocation {
|
||
|
|
||
|
return &structs.FormattedLocation{
|
||
|
Lat: latlong.Lat,
|
||
|
Long: latlong.Long,
|
||
|
Country: address.Country,
|
||
|
City: address.City,
|
||
|
State: address.State,
|
||
|
Zipcode: address.Postcode,
|
||
|
StreetName: address.Street,
|
||
|
CountryCode: address.CountryCode,
|
||
|
County: address.County,
|
||
|
Neighbourhood: address.Suburb,
|
||
|
Village: "",
|
||
|
Formatted: address.FormattedAddress,
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
func saveLocationRec(app *pocketbase.PocketBase, newLocation structs.FormattedLocation) error {
|
||
|
log.Println("$$:saveLocationRec", newLocation.Lat, newLocation.Long)
|
||
|
|
||
|
collection, err := app.Dao().FindCollectionByNameOrId("geocode")
|
||
|
if err != nil {
|
||
|
log.Println(err)
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
record, recErr := app.Dao().FindRecordsByExpr("geocode", dbx.NewExp("lat = {:lat} and long = {:long}", dbx.Params{"lat": newLocation.Lat, "long": newLocation.Long}))
|
||
|
|
||
|
if recErr != nil {
|
||
|
log.Println(recErr)
|
||
|
return recErr
|
||
|
}
|
||
|
|
||
|
if len(record) == 0 {
|
||
|
log.Println("-- Insert new geocode")
|
||
|
record := models.NewRecord(collection)
|
||
|
|
||
|
record.Set("lat", newLocation.Lat)
|
||
|
record.Set("long", newLocation.Long)
|
||
|
record.Set("country", newLocation.Country)
|
||
|
record.Set("city", newLocation.City)
|
||
|
record.Set("state", newLocation.State)
|
||
|
record.Set("zipcode", newLocation.Zipcode)
|
||
|
record.Set("streetname", newLocation.StreetName)
|
||
|
record.Set("countrycode", newLocation.CountryCode)
|
||
|
record.Set("county", newLocation.County)
|
||
|
record.Set("neighbourhood", newLocation.Neighbourhood)
|
||
|
record.Set("village", newLocation.Village)
|
||
|
record.Set("formatted", newLocation.Formatted)
|
||
|
|
||
|
if err := app.Dao().SaveRecord(record); err != nil {
|
||
|
log.Println("ERROR!! saveLocationRec NewRecord")
|
||
|
log.Println(err)
|
||
|
|
||
|
return err
|
||
|
}
|
||
|
} else {
|
||
|
log.Println("-- Update geocode")
|
||
|
|
||
|
rec := record[0]
|
||
|
rec.Set("lat", newLocation.Lat)
|
||
|
rec.Set("long", newLocation.Long)
|
||
|
rec.Set("country", newLocation.Country)
|
||
|
rec.Set("city", newLocation.City)
|
||
|
rec.Set("state", newLocation.State)
|
||
|
rec.Set("zipcode", newLocation.Zipcode)
|
||
|
rec.Set("streetname", newLocation.StreetName)
|
||
|
rec.Set("countrycode", newLocation.CountryCode)
|
||
|
rec.Set("county", newLocation.County)
|
||
|
rec.Set("neighbourhood", newLocation.Neighbourhood)
|
||
|
rec.Set("village", newLocation.Village)
|
||
|
rec.Set("formatted", newLocation.Formatted)
|
||
|
if err := app.Dao().SaveRecord(rec); err != nil {
|
||
|
log.Println("ERROR!! saveLocationRec SaveRecord")
|
||
|
log.Println(err)
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|