mirror of https://github.com/chubin/wttr.in
parent
b8a7991cb6
commit
2ce4c28c34
@ -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
|
||||||
|
}
|
@ -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 new issue