Add Nominatim queries resolution initial support

This commit is contained in:
Igor Chubin 2022-12-09 21:02:10 +01:00
parent b8a7991cb6
commit 2ce4c28c34
2 changed files with 115 additions and 0 deletions

View file

@ -0,0 +1,49 @@
package location
import "github.com/chubin/wttr.in/internal/config"
type Location struct {
Name string
Fullname string `json:"display_name"`
Lat string
Lon string
}
type Provider interface {
Query(location string) (*Location, error)
}
type Searcher struct {
providers []Provider
}
// NewSearcher returns a new Searcher for the specified config.
func NewSearcher(config *config.Config) *Searcher {
providers := []Provider{}
for _, p := range config.Geo.Nominatim {
providers = append(providers, NewNominatim(p.Name, p.URL, p.Token))
}
return &Searcher{
providers: providers,
}
}
// Search makes queries through all known providers,
// and returns response, as soon as it is not nil.
// If all responses were nil, the last response is returned.
func (s *Searcher) Search(location string) (*Location, error) {
var (
err error
result *Location
)
for _, p := range s.providers {
result, err = p.Query(location)
if result != nil && err == nil {
return result, nil
}
}
return result, err
}

View file

@ -0,0 +1,66 @@
package location
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
)
type Nominatim struct {
name string
url string
token string
}
func NewNominatim(name, url, token string) *Nominatim {
return &Nominatim{
name: name,
url: url,
token: token,
}
}
func (n *Nominatim) Query(location string) (*Location, error) {
var (
result []Location
errResponse struct {
Error string
}
)
urlws := fmt.Sprintf(
"%s?q=%s&format=json&accept-language=native&limit=1&key=%s",
n.url, url.QueryEscape(location), n.token)
log.Println(urlws)
resp, err := http.Get(urlws)
if err != nil {
return nil, fmt.Errorf("%s: %w", n.name, err)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("%s: %w", n.name, err)
}
err = json.Unmarshal(body, &errResponse)
if err == nil && errResponse.Error != "" {
return nil, fmt.Errorf("%s: %s", n.name, errResponse.Error)
}
err = json.Unmarshal(body, &result)
if err != nil {
return nil, fmt.Errorf("%s: %w", n.name, err)
}
if len(result) != 1 {
return nil, fmt.Errorf("%s: invalid response", n.name)
}
return &result[0], nil
}