Move OpenWeatherMap code to a separate struct

This commit is contained in:
Ryan Cavicchioni 2022-08-28 09:44:35 -05:00
parent af10ef4dc5
commit 7d071ebe0b
Signed by: ryanc
GPG Key ID: 877EEDAF9245103D
3 changed files with 138 additions and 100 deletions

View File

@ -1,72 +1,21 @@
package handler
import (
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"git.kill0.net/chill9/beepboop/bot"
"git.kill0.net/chill9/beepboop/lib"
"git.kill0.net/chill9/beepboop/lib/weather"
"github.com/bwmarrin/discordgo"
log "github.com/sirupsen/logrus"
)
const (
OpenWeatherMapURI = "https://api.openweathermap.org"
)
var (
EndpointWeather = lib.BuildURI(OpenWeatherMapURI, "/data/2.5/weather")
)
type (
WeatherHandler struct {
type WeatherHandler struct {
Config bot.Config
Name string
}
Temperature float32
Weather struct {
Main struct {
Temp Temperature `json:"temp"`
FeelsLike Temperature `json:"feels_like"`
TempMin Temperature `json:"temp_min"`
TempMax Temperature `json:"temp_max"`
Pressure float32 `json:"pressure"`
Humidity float32 `json:"humidity"`
} `json:"main"`
Coord struct {
Lon float32 `json:"lon"`
Lat float32 `json:"lat"`
} `json:"coord"`
Rain struct {
H1 float32 `json:"1h"`
H3 float32 `json:"3h"`
} `json:"rain"`
}
WeatherError struct {
Message string `json:"message"`
}
)
func (t *Temperature) Kelvin() float32 {
return float32(*t)
}
func (t *Temperature) Fahrenheit() float32 {
return ((float32(*t) - 273.15) * (9.0 / 5)) + 32
}
func (t *Temperature) Celcius() float32 {
return float32(*t) - 273.15
}
func NewWeatherHandler(s string) *WeatherHandler {
h := new(WeatherHandler)
h.Name = s
@ -79,9 +28,9 @@ func (h *WeatherHandler) SetConfig(config bot.Config) {
func (h *WeatherHandler) Handle(s *discordgo.Session, m *discordgo.MessageCreate) {
var (
err error
loc string
w Weather
werr WeatherError
w weather.Weather
)
if m.Author.ID == s.State.User.ID {
@ -106,51 +55,17 @@ func (h *WeatherHandler) Handle(s *discordgo.Session, m *discordgo.MessageCreate
return
}
req, err := http.NewRequest("GET", EndpointWeather, nil)
wc := weather.NewClient(h.Config.OpenWeatherMapToken)
log.Debugf("weather requested for '%s'", loc)
w, err = wc.Get(loc)
if err != nil {
log.Errorf("failed to create new request: %s", err)
log.Errorf("weather client error: %v", err)
return
}
q := req.URL.Query()
q.Add("q", loc)
q.Add("appid", h.Config.OpenWeatherMapToken)
req.URL.RawQuery = q.Encode()
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Errorf("HTTP request failed: %s", err)
return
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Errorf("reading HTTP response failed: %s", err)
return
}
if resp.StatusCode != 200 {
err = json.Unmarshal(body, &werr)
if err != nil {
log.Debugf("%s\n", body)
log.Errorf("unmarshaling JSON failed: %s", err)
return
}
log.Warnf("error: (%s) %s", resp.Status, werr.Message)
return
}
log.Debugf("weather requested for '%s'\n", loc)
err = json.Unmarshal(body, &w)
if err != nil {
log.Debugf("%s\n", body)
log.Errorf("unmarshaling JSON failed: %s", err)
return
}
log.Debugf("weather returned for '%s': %+v\n", loc, w)
log.Debugf("weather returned for '%s': %+v", loc, w)
s.ChannelMessageSend(m.ChannelID, fmt.Sprintf(
"%s (%.1f, %.1f) — C:%.1f F:%.1f K:%.1f",

42
lib/weather/structs.go Normal file
View File

@ -0,0 +1,42 @@
package weather
type (
Temperature float32
Weather struct {
Main struct {
Temp Temperature `json:"temp"`
FeelsLike Temperature `json:"feels_like"`
TempMin Temperature `json:"temp_min"`
TempMax Temperature `json:"temp_max"`
Pressure float32 `json:"pressure"`
Humidity float32 `json:"humidity"`
} `json:"main"`
Coord struct {
Lon float32 `json:"lon"`
Lat float32 `json:"lat"`
} `json:"coord"`
Rain struct {
H1 float32 `json:"1h"`
H3 float32 `json:"3h"`
} `json:"rain"`
}
WeatherError struct {
Message string `json:"message"`
}
)
func (t *Temperature) Kelvin() float32 {
return float32(*t)
}
func (t *Temperature) Fahrenheit() float32 {
return ((float32(*t) - 273.15) * (9.0 / 5)) + 32
}
func (t *Temperature) Celcius() float32 {
return float32(*t) - 273.15
}

81
lib/weather/weather.go Normal file
View File

@ -0,0 +1,81 @@
package weather
import (
"encoding/json"
"fmt"
"io"
"net/http"
"git.kill0.net/chill9/beepboop/lib"
log "github.com/sirupsen/logrus"
)
type (
WeatherClient struct {
token string
}
)
const (
OpenWeatherMapURI = "https://api.openweathermap.org"
)
var (
EndpointWeather = lib.BuildURI(OpenWeatherMapURI, "/data/2.5/weather")
)
func NewClient(token string) *WeatherClient {
return &WeatherClient{token}
}
func (c *WeatherClient) Get(loc string) (w Weather, err error) {
var (
werr WeatherError
)
req, err := http.NewRequest("GET", EndpointWeather, nil)
if err != nil {
err = fmt.Errorf("failed to create new request: %s", err)
return
}
q := req.URL.Query()
q.Add("q", loc)
q.Add("appid", c.token)
req.URL.RawQuery = q.Encode()
resp, err := http.DefaultClient.Do(req)
if err != nil {
err = fmt.Errorf("HTTP request failed: %s", err)
return
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
err = fmt.Errorf("reading HTTP response failed: %s", err)
return
}
if resp.StatusCode != 200 {
err = json.Unmarshal(body, &werr)
if err != nil {
log.Debugf("%s", body)
err = fmt.Errorf("unmarshaling JSON failed: %s", err)
return
}
err = fmt.Errorf("error: (%s) %s", resp.Status, werr.Message)
return
}
err = json.Unmarshal(body, &w)
if err != nil {
log.Debugf("%s", body)
log.Errorf("unmarshaling JSON failed: %s", err)
return
}
return
}