Files
logiflow/pkg/geocode/geocode.go

60 lines
1.3 KiB
Go

package geocode
import (
"context"
"encoding/json"
"fmt"
"log/slog"
"net/http"
neturl "net/url"
"strconv"
)
type OsrmResult struct {
Routes []struct {
Geometry struct {
Coordinates [][]float64 `json:"coordinates"`
} `json:"geometry"`
Distance float64 `json:"distance"`
Duration float64 `json:"duration"`
} `json:"routes"`
}
func Geocode(ctx context.Context, address string) (lat, lon float64, err error) {
url := fmt.Sprintf(
"https://nominatim.openstreetmap.org/search?q=%s&format=json&limit=1",
neturl.QueryEscape(address),
)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return 0, 0, err
}
req.Header.Set("User-Agent", "logiflow/1.0")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return 0, 0, err
}
defer func() {
if err := resp.Body.Close(); err != nil {
slog.Warn("failed to close response body", slog.String("error", err.Error()))
}
}()
var results []struct {
Lat string `json:"lat"`
Lon string `json:"lon"`
}
if err := json.NewDecoder(resp.Body).Decode(&results); err != nil {
return 0, 0, err
}
if len(results) == 0 {
return 0, 0, fmt.Errorf("address not found: %s", address)
}
lat, _ = strconv.ParseFloat(results[0].Lat, 64)
lon, _ = strconv.ParseFloat(results[0].Lon, 64)
return lat, lon, nil
}