package bot //import "github.com/kr/pretty" import ( "encoding/json" "fmt" "io/ioutil" "net/http" "os" "regexp" "time" "github.com/rs/zerolog/log" ) type MetarResponse struct { Meta struct { Timestamp time.Time `json:"timestamp"` StationsUpdated string `json:"stations_updated"` } `json:"meta"` Altimeter struct { Repr string `json:"repr"` Value float64 `json:"value"` Spoken string `json:"spoken"` } `json:"altimeter"` Clouds []interface{} `json:"clouds"` FlightRules string `json:"flight_rules"` Other []interface{} `json:"other"` Sanitized string `json:"sanitized"` Visibility struct { Repr string `json:"repr"` Value int `json:"value"` Spoken string `json:"spoken"` } `json:"visibility"` WindDirection struct { Repr string `json:"repr"` Value int `json:"value"` Spoken string `json:"spoken"` } `json:"wind_direction"` WindGust struct { Repr string `json:"repr"` Value int `json:"value"` Spoken string `json:"spoken"` } `json:"wind_gust"` WindSpeed struct { Repr string `json:"repr"` Value int `json:"value"` Spoken string `json:"spoken"` } `json:"wind_speed"` WxCodes []interface{} `json:"wx_codes"` Raw string `json:"raw"` Station string `json:"station"` Time struct { Repr string `json:"repr"` Dt time.Time `json:"dt"` } `json:"time"` Remarks string `json:"remarks"` Dewpoint struct { Repr string `json:"repr"` Value int `json:"value"` Spoken string `json:"spoken"` } `json:"dewpoint"` RemarksInfo struct { DewpointDecimal struct { Repr string `json:"repr"` Value float64 `json:"value"` Spoken string `json:"spoken"` } `json:"dewpoint_decimal"` TemperatureDecimal struct { Repr string `json:"repr"` Value float64 `json:"value"` Spoken string `json:"spoken"` } `json:"temperature_decimal"` } `json:"remarks_info"` RunwayVisibility []interface{} `json:"runway_visibility"` Temperature struct { Repr string `json:"repr"` Value int `json:"value"` Spoken string `json:"spoken"` } `json:"temperature"` WindVariableDirection []interface{} `json:"wind_variable_direction"` Units struct { Altimeter string `json:"altimeter"` Altitude string `json:"altitude"` Temperature string `json:"temperature"` Visibility string `json:"visibility"` WindSpeed string `json:"wind_speed"` } `json:"units"` } func (b *Bot) HandleWeatherRequest(channelid string, postid string, message string) { // we are using a very bare image with no CA cert bundle // actually if you docker bind mount the ca cert bundle in the right // place, golang will find it and use it. //http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} log.Info().Msgf("weather request received: `%s`", message) r := regexp.MustCompile(`metar\s+([A-Za-z]{4})`) matches := r.FindStringSubmatch(message) if len(matches) < 2 { b.SendMsgToChannel("error, sorry", postid, channelid) } loc := matches[1] token := os.Getenv("METAR_API_TOKEN") url := fmt.Sprintf("https://avwx.rest/api/metar/%s?options=&airport=true&reporting=true&format=json&onfail=cache", loc) log.Info().Msgf("calculated url: `%s`", url) client := http.Client{ Timeout: 5 * time.Second, } req, err := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", `Token `+token) resp, err := client.Do(req) if err != nil { b.SendMsgToChannel(fmt.Sprintf("weather fetch error: %s", err), postid, channelid) return } if resp.StatusCode != http.StatusOK { b.SendMsgToChannel(fmt.Sprintf("weather fetch error: http status %d", resp.StatusCode), postid, channelid) return } data, _ := ioutil.ReadAll(resp.Body) var parsedMetarResponse MetarResponse log.Info().Msgf("weather %s: %s", loc, data) err = nil err = json.Unmarshal([]byte(data), &parsedMetarResponse) if err != nil { b.SendMsgToChannel("error deserializing metar data", postid, channelid) return } b.SendMsgToChannel(fmt.Sprintf("weather for `%s`: \n```\n%+v\n```\n", loc, parsedMetarResponse), postid, channelid) }