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 }