all repos — paprika @ 3d5516d37297470eabc3c1862756c048d58f03b4

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