all repos — paprika @ 7284194835942c15cd83b83e1247c7cf86cbd74e

go rewrite of taigabot

plugins/weather/weather.go (view raw)

  1package weather
  2
  3import (
  4	_ "embed"
  5	"encoding/json"
  6	"fmt"
  7	"net/http"
  8	"strings"
  9)
 10
 11type WeatherData struct {
 12	Properties struct {
 13		Meta struct {
 14			Units struct {
 15				AirPressureAtSeaLevel string `json:"air_pressure_at_sea_level"`
 16				AirTemperature        string `json:"air_temperature"`
 17				RelativeHumidity      string `json:"relative_humidity"`
 18				WindSpeed             string `json:"wind_speed"`
 19			} `json:"units"`
 20		} `json:"meta"`
 21		Timeseries []struct {
 22			Data struct {
 23				Instant struct {
 24					Details struct {
 25						AirPressureAtSeaLevel float64 `json:"air_pressure_at_sea_level"`
 26						AirTemperature        float64 `json:"air_temperature"`
 27						RelativeHumidity      float64 `json:"relative_humidity"`
 28						WindSpeed             float64 `json:"wind_speed"`
 29					} `json:"details"`
 30				} `json:"instant"`
 31				Next12Hours struct {
 32					Summary struct {
 33						SymbolCode string `json:"symbol_code"`
 34					} `json:"summary"`
 35				} `json:"next_12_hours"`
 36			} `json:"data"`
 37		} `json:"timeseries"`
 38	} `json:"properties"`
 39}
 40
 41func getWeatherData(lonlat [2]float64) (*WeatherData, error) {
 42	url := "https://api.met.no/weatherapi/locationforecast/2.0/compact.json?lat=%f16&lon=%f"
 43	url = fmt.Sprintf(url, lonlat[1], lonlat[0])
 44
 45	client := &http.Client{}
 46	req, _ := http.NewRequest("GET", url, nil)
 47	req.Header.Add("User-Agent", "taigobot github.com/icyphox/taigobot")
 48
 49	res, err := client.Do(req)
 50	if err != nil {
 51		return nil, err
 52	}
 53
 54	wd := WeatherData{}
 55
 56	json.NewDecoder(res.Body).Decode(&wd)
 57	defer res.Body.Close()
 58
 59	return &wd, nil
 60}
 61
 62func ctof(c float64) float64 {
 63	return c*9/5 + 32
 64}
 65
 66//go:embed data/weather.json
 67var wj []byte
 68
 69func symbolToDesc(s string) string {
 70	m := make(map[string]interface{})
 71	json.Unmarshal(wj, &m)
 72
 73	// Some symbols have a _, which isn't present in
 74	// the data. So we strip it.
 75	s = strings.Split(s, "_")[0]
 76
 77	// lmao
 78	return m[s].(map[string]interface{})["desc"].(string) + ", "
 79}
 80
 81// Looks like Nominatim uses (lon,lat).
 82func GetWeather(lonlat [2]float64, location string) (string, error) {
 83	wd, err := getWeatherData(lonlat)
 84	if err != nil {
 85		return "", err
 86	}
 87
 88	info := strings.Builder{}
 89
 90	// Location.
 91	fmt.Fprintf(&info, "\x02%s\x02: ", location)
 92
 93	// Description of weather.
 94	sym := wd.Properties.Timeseries[0].Data.Next12Hours.Summary.SymbolCode
 95	desc := symbolToDesc(sym)
 96	fmt.Fprintf(&info, "%s", desc)
 97
 98	// Current temperature.
 99	temp := wd.Properties.Timeseries[0].Data.Instant.Details.AirTemperature
100	var tempFmt string
101	if temp > 28 {
102		tempFmt = "\x0304%0.2f°C\x03 (\x0304%0.2f°F\x03), "
103	} else if temp > 18 {
104		tempFmt = "\x0303%0.2f°C\x03 (\x0303%0.2f°F\x03), "
105	} else {
106		tempFmt = "\x0311%0.2f°C\x03 (\x0311%0.2f°F\x03), "
107	}
108	fmt.Fprintf(
109		&info,
110		"\x02Currently:\x02 "+tempFmt,
111		temp,
112		ctof(temp),
113	)
114
115	// Humidity.
116	hum := wd.Properties.Timeseries[0].Data.Instant.Details.RelativeHumidity
117	humUnit := wd.Properties.Meta.Units.RelativeHumidity
118	fmt.Fprintf(
119		&info,
120		"\x02Humidity:\x02 %0.2f%s, ",
121		hum,
122		humUnit,
123	)
124
125	// Wind speed.
126	ws := wd.Properties.Timeseries[0].Data.Instant.Details.WindSpeed
127	wsUnit := wd.Properties.Meta.Units.WindSpeed
128	fmt.Fprintf(
129		&info,
130		"\x02Wind Speed:\x02 %0.1f%s, ",
131		ws,
132		wsUnit,
133	)
134
135	// Pressure.
136	ps := wd.Properties.Timeseries[0].Data.Instant.Details.AirPressureAtSeaLevel
137	psUnit := wd.Properties.Meta.Units.AirPressureAtSeaLevel
138	fmt.Fprintf(&info,
139		"\x02Pressure:\x02 %0.1f%s",
140		ps,
141		psUnit,
142	)
143
144	return info.String(), nil
145}