wttr.in/internal/view/v1/api.go

193 lines
4.2 KiB
Go
Raw Normal View History

//nolint:forbidigo,funlen,nestif,goerr113,gocognit,cyclop
2022-12-23 15:25:26 +00:00
package v1
2022-06-11 16:10:07 +00:00
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"strconv"
"strings"
)
2022-12-23 16:15:17 +00:00
//nolint:tagliatelle
2022-06-11 16:10:07 +00:00
type cond struct {
ChanceOfRain string `json:"chanceofrain"`
FeelsLikeC int `json:",string"`
PrecipMM float32 `json:"precipMM,string"`
TempC int `json:"tempC,string"`
TempC2 int `json:"temp_C,string"`
Time int `json:"time,string"`
VisibleDistKM int `json:"visibility,string"`
WeatherCode int `json:"weatherCode,string"`
WeatherDesc []struct{ Value string }
WindGustKmph int `json:",string"`
Winddir16Point string
WindspeedKmph int `json:"windspeedKmph,string"`
}
type astro struct {
Moonrise string
Moonset string
Sunrise string
Sunset string
}
type weather struct {
Astronomy []astro
Date string
Hourly []cond
MaxtempC int `json:"maxtempC,string"`
MintempC int `json:"mintempC,string"`
}
type loc struct {
Query string `json:"query"`
Type string `json:"type"`
}
2022-12-23 16:15:17 +00:00
//nolint:tagliatelle
2022-06-11 16:10:07 +00:00
type resp struct {
Data struct {
Cur []cond `json:"current_condition"`
Err []struct{ Msg string } `json:"error"`
Req []loc `json:"request"`
Weather []weather `json:"weather"`
} `json:"data"`
}
2022-12-24 17:10:20 +00:00
func (g *global) getDataFromAPI() (*resp, error) {
2022-12-23 19:13:13 +00:00
var (
ret resp
params []string
)
2022-06-11 16:10:07 +00:00
2022-12-23 19:55:30 +00:00
if len(g.config.APIKey) == 0 {
2022-12-24 17:11:42 +00:00
return nil, fmt.Errorf("no API key specified. Setup instructions are in the README")
2022-06-11 16:10:07 +00:00
}
2022-12-23 19:55:30 +00:00
params = append(params, "key="+g.config.APIKey)
2022-06-11 16:10:07 +00:00
// non-flag shortcut arguments will overwrite possible flag arguments
for _, arg := range flag.Args() {
if v, err := strconv.Atoi(arg); err == nil && len(arg) == 1 {
2022-12-23 19:55:30 +00:00
g.config.Numdays = v
2022-06-11 16:10:07 +00:00
} else {
2022-12-23 19:55:30 +00:00
g.config.City = arg
2022-06-11 16:10:07 +00:00
}
}
2022-12-23 19:55:30 +00:00
if len(g.config.City) > 0 {
params = append(params, "q="+url.QueryEscape(g.config.City))
2022-06-11 16:10:07 +00:00
}
2022-12-23 19:55:30 +00:00
params = append(params, "format=json", "num_of_days="+strconv.Itoa(g.config.Numdays), "tp=3")
if g.config.Lang != "" {
params = append(params, "lang="+g.config.Lang)
2022-06-11 16:10:07 +00:00
}
2022-12-23 19:55:30 +00:00
if g.debug {
2022-06-11 16:10:07 +00:00
fmt.Fprintln(os.Stderr, params)
}
res, err := http.Get(wuri + strings.Join(params, "&"))
if err != nil {
2022-12-24 17:10:20 +00:00
return nil, err
2022-06-11 16:10:07 +00:00
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
2022-12-24 17:10:20 +00:00
return nil, err
2022-06-11 16:10:07 +00:00
}
2022-12-23 19:55:30 +00:00
if g.debug {
2022-06-11 16:10:07 +00:00
var out bytes.Buffer
2022-12-23 15:55:14 +00:00
2022-12-24 17:10:20 +00:00
err := json.Indent(&out, body, "", " ")
if err != nil {
return nil, err
}
_, err = out.WriteTo(os.Stderr)
if err != nil {
return nil, err
}
2022-12-23 15:55:14 +00:00
2022-06-11 16:10:07 +00:00
fmt.Print("\n\n")
}
2022-12-23 19:55:30 +00:00
if g.config.Lang == "" {
2022-06-11 16:10:07 +00:00
if err = json.Unmarshal(body, &ret); err != nil {
2022-12-24 17:10:20 +00:00
return nil, err
2022-06-11 16:10:07 +00:00
}
} else {
2022-12-23 19:55:30 +00:00
if err = g.unmarshalLang(body, &ret); err != nil {
2022-12-24 17:10:20 +00:00
return nil, err
2022-06-11 16:10:07 +00:00
}
}
2022-12-23 15:55:14 +00:00
2022-12-24 17:10:20 +00:00
return &ret, nil
2022-06-11 16:10:07 +00:00
}
2022-12-23 19:55:30 +00:00
func (g *global) unmarshalLang(body []byte, r *resp) error {
2022-06-11 16:10:07 +00:00
var rv map[string]interface{}
if err := json.Unmarshal(body, &rv); err != nil {
return err
}
if data, ok := rv["data"].(map[string]interface{}); ok {
if ccs, ok := data["current_condition"].([]interface{}); ok {
for _, cci := range ccs {
cc, ok := cci.(map[string]interface{})
if !ok {
continue
}
2022-12-23 19:55:30 +00:00
langs, ok := cc["lang_"+g.config.Lang].([]interface{})
2022-06-11 16:10:07 +00:00
if !ok || len(langs) == 0 {
continue
}
weatherDesc, ok := cc["weatherDesc"].([]interface{})
if !ok || len(weatherDesc) == 0 {
continue
}
weatherDesc[0] = langs[0]
}
}
if ws, ok := data["weather"].([]interface{}); ok {
for _, wi := range ws {
w, ok := wi.(map[string]interface{})
if !ok {
continue
}
if hs, ok := w["hourly"].([]interface{}); ok {
for _, hi := range hs {
h, ok := hi.(map[string]interface{})
if !ok {
continue
}
2022-12-23 19:55:30 +00:00
langs, ok := h["lang_"+g.config.Lang].([]interface{})
2022-06-11 16:10:07 +00:00
if !ok || len(langs) == 0 {
continue
}
weatherDesc, ok := h["weatherDesc"].([]interface{})
if !ok || len(weatherDesc) == 0 {
continue
}
weatherDesc[0] = langs[0]
}
}
}
}
}
var buf bytes.Buffer
if err := json.NewEncoder(&buf).Encode(rv); err != nil {
return err
}
if err := json.NewDecoder(&buf).Decode(r); err != nil {
return err
}
2022-12-23 15:55:14 +00:00
2022-06-11 16:10:07 +00:00
return nil
}