diff --git a/cmd/nourybot/commands.go b/cmd/nourybot/commands.go index 150f611..096fdbc 100644 --- a/cmd/nourybot/commands.go +++ b/cmd/nourybot/commands.go @@ -71,5 +71,21 @@ func (app *Application) ParseCommand(evt *event.Event) { return } } + + case "weather": + if msgLen < 2 { + app.SendText(evt, "Not enough arguments provided") + return + } else { + location := evt.Content.AsMessage().Body[9:len(evt.Content.AsMessage().Body)] + if resp, err := commands.Weather(location); err != nil { + app.Log.Error().Err(err).Msg("Failed to handle Weather command") + app.SendText(evt, "Something went wrong.") + return + } else { + app.SendText(evt, resp) + return + } + } } } diff --git a/go.mod b/go.mod index 8c8dfff..bbe0942 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( ) require ( + github.com/briandowns/openweathermap v0.19.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.18 // indirect github.com/tidwall/gjson v1.14.4 // indirect diff --git a/go.sum b/go.sum index ad10813..a47274b 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,6 @@ github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= +github.com/briandowns/openweathermap v0.19.0 h1:nkopLMEtZLxbZI1th6dOG6xkajpszofqf53r5K8mT9k= +github.com/briandowns/openweathermap v0.19.0/go.mod h1:0GLnknqicWxXnGi1IqoOaZIw+kIe5hkt+YM5WY3j8+0= github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= diff --git a/internal/commands/commands.go b/internal/commands/commands.go index cdff10d..b518c94 100644 --- a/internal/commands/commands.go +++ b/internal/commands/commands.go @@ -1 +1,9 @@ package commands + +import "errors" + +var ( + ErrEnvFileNotFound = errors.New(".env file not found") + ErrInternalServerError = errors.New("internal server error") + ErrLocationNotFound = errors.New("location not found") +) diff --git a/internal/commands/weather.go b/internal/commands/weather.go new file mode 100644 index 0000000..c96db6a --- /dev/null +++ b/internal/commands/weather.go @@ -0,0 +1,47 @@ +package commands + +import ( + "fmt" + "os" + + owm "github.com/briandowns/openweathermap" + "github.com/joho/godotenv" +) + +// Weather queries the OpenWeatherMap Api for the given location and sends the +// current weather response to the target twitch chat. +func Weather(location string) (string, error) { + err := godotenv.Load() + if err != nil { + return "", ErrInternalServerError + } + owmKey := os.Getenv("OWM_KEY") + + w, err := owm.NewCurrent("C", "en", owmKey) + if err != nil { + return "", ErrInternalServerError + } + + if err := w.CurrentByName(location); err != nil { + return "", ErrInternalServerError + } + + // Longitude and Latitude are returned as 0 when the supplied location couldn't be + // assigned to a OpenWeatherMap location. + if w.GeoPos.Longitude == 0 && w.GeoPos.Latitude == 0 { + return "", ErrLocationNotFound + } else { + // Weather for Vilnius, LT: Feels like: 29.67°C. Currently 29.49°C with a high of 29.84°C and a low of 29.49°C, humidity: 45%, wind: 6.17m/s. + reply := fmt.Sprintf("Weather for %s, %s: Feels like: %v°C. Currently %v°C with a high of %v°C and a low of %v°C, humidity: %v%%, wind: %vm/s.", + w.Name, + w.Sys.Country, + w.Main.FeelsLike, + w.Main.Temp, + w.Main.TempMax, + w.Main.TempMin, + w.Main.Humidity, + w.Wind.Speed, + ) + return reply, nil + } +} diff --git a/internal/commands/xkcd.go b/internal/commands/xkcd.go index 6fefcb7..8676d96 100644 --- a/internal/commands/xkcd.go +++ b/internal/commands/xkcd.go @@ -17,15 +17,15 @@ type xkcdResponse struct { func Xkcd() (string, error) { response, err := http.Get("https://xkcd.com/info.0.json") if err != nil { - return "", err + return "", ErrInternalServerError } responseData, err := io.ReadAll(response.Body) if err != nil { - return "", err + return "", ErrInternalServerError } var responseObject xkcdResponse if err = json.Unmarshal(responseData, &responseObject); err != nil { - return "", err + return "", ErrInternalServerError } reply := fmt.Sprint("Current Xkcd #", responseObject.Num, " Title: ", responseObject.SafeTitle, " ", responseObject.Img) @@ -38,15 +38,15 @@ func RandomXkcd() (string, error) { response, err := http.Get(fmt.Sprint("http://xkcd.com/" + comicNum + "/info.0.json")) if err != nil { - return "", err + return "", ErrInternalServerError } responseData, err := io.ReadAll(response.Body) if err != nil { - return "", err + return "", ErrInternalServerError } var responseObject xkcdResponse if err = json.Unmarshal(responseData, &responseObject); err != nil { - return "", err + return "", ErrInternalServerError } reply := fmt.Sprint("Random Xkcd #", responseObject.Num, " Title: ", responseObject.SafeTitle, " ", responseObject.Img)