mirror of
https://github.com/chubin/wttr.in
synced 2025-01-12 03:58:45 +00:00
Add Nominatim queries resolution initial support
This commit is contained in:
parent
b8a7991cb6
commit
2ce4c28c34
2 changed files with 115 additions and 0 deletions
49
internal/geo/location/location.go
Normal file
49
internal/geo/location/location.go
Normal 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
|
||||
}
|
66
internal/geo/location/nominatim.go
Normal file
66
internal/geo/location/nominatim.go
Normal 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
|
||||
|
||||
}
|
Loading…
Reference in a new issue