mirror of
https://github.com/kevin-DL/services.git
synced 2026-01-11 19:04:35 +00:00
112 lines
2.7 KiB
Go
112 lines
2.7 KiB
Go
package handler
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
"github.com/micro/micro/v3/service/errors"
|
|
"github.com/micro/micro/v3/service/logger"
|
|
"googlemaps.github.io/maps"
|
|
|
|
pb "github.com/micro/services/geocoding/proto"
|
|
)
|
|
|
|
var (
|
|
ErrDownstream = errors.InternalServerError("MAP_ERROR", "Unable to connect to map provider")
|
|
ErrNoResults = errors.BadRequest("NO_RESULTS", "Unable to geocode address, no results found")
|
|
ErrMissingLatitude = errors.BadRequest("MISSING_LATITUDE", "Missing latitude")
|
|
ErrMissingLongitude = errors.BadRequest("MISSING_LONGITUDE", "Missing longitude")
|
|
)
|
|
|
|
type Geocoding struct {
|
|
Maps *maps.Client
|
|
}
|
|
|
|
func (g *Geocoding) Lookup(ctx context.Context, req *pb.LookupRequest, rsp *pb.LookupResponse) error {
|
|
// query google maps
|
|
results, err := g.Maps.Geocode(ctx, &maps.GeocodingRequest{Address: req.Address})
|
|
if err != nil {
|
|
logger.Errorf("Error geocoding: %v", err)
|
|
return ErrDownstream
|
|
}
|
|
if len(results) == 0 {
|
|
return ErrNoResults
|
|
}
|
|
|
|
rsp.Address = new(pb.Address)
|
|
rsp.Location = new(pb.Location)
|
|
|
|
// return the result
|
|
serializeResult(results[0], rsp.Address, rsp.Location)
|
|
|
|
return nil
|
|
}
|
|
|
|
// Reverse geocode an address
|
|
func (g *Geocoding) Reverse(ctx context.Context, req *pb.ReverseRequest, rsp *pb.ReverseResponse) error {
|
|
// validate the request
|
|
if req.Latitude == 0.0 {
|
|
return ErrMissingLatitude
|
|
}
|
|
if req.Longitude == 0.0 {
|
|
return ErrMissingLongitude
|
|
}
|
|
|
|
// query google maps
|
|
results, err := g.Maps.ReverseGeocode(ctx, &maps.GeocodingRequest{
|
|
LatLng: &maps.LatLng{Lat: req.Latitude, Lng: req.Longitude},
|
|
})
|
|
if err != nil {
|
|
logger.Errorf("Error geocoding: %v", err)
|
|
return ErrDownstream
|
|
}
|
|
if len(results) == 0 {
|
|
return ErrNoResults
|
|
}
|
|
|
|
rsp.Address = new(pb.Address)
|
|
rsp.Location = new(pb.Location)
|
|
|
|
// return the result
|
|
serializeResult(results[0], rsp.Address, rsp.Location)
|
|
return nil
|
|
}
|
|
|
|
func toString(a *pb.Address) string {
|
|
var comps []string
|
|
for _, c := range []string{a.LineOne, a.LineTwo, a.City, a.Postcode, a.Country} {
|
|
t := strings.TrimSpace(c)
|
|
if len(t) > 0 {
|
|
comps = append(comps, t)
|
|
}
|
|
}
|
|
return strings.Join(comps, ", ")
|
|
}
|
|
|
|
func serializeResult(r maps.GeocodingResult, a *pb.Address, l *pb.Location) {
|
|
var street, number string
|
|
|
|
for _, c := range r.AddressComponents {
|
|
for _, t := range c.Types {
|
|
switch t {
|
|
case "street_number":
|
|
number = c.LongName
|
|
case "route":
|
|
street = c.LongName
|
|
case "neighborhood":
|
|
a.LineTwo = c.LongName
|
|
case "country":
|
|
a.Country = c.LongName
|
|
case "postal_code":
|
|
a.Postcode = c.LongName
|
|
case "postal_town":
|
|
a.City = c.LongName
|
|
}
|
|
}
|
|
}
|
|
|
|
a.LineOne = strings.Join([]string{number, street}, " ")
|
|
l.Latitude = r.Geometry.Location.Lat
|
|
l.Longitude = r.Geometry.Location.Lng
|
|
}
|