go-pb-jubilee/geocode/geocode.go
Martin Donnelly 9b11de7902 init
2024-08-28 00:24:33 +01:00

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
}