From 7e19a8e9afa91557b444278e5599c3542c4862cf Mon Sep 17 00:00:00 2001 From: vikingowl Date: Sun, 20 Feb 2022 01:01:48 +0100 Subject: [PATCH] updated some logic and better error handling --- .gitignore | 2 +- get-weather.go | 241 --------------------------- go.mod | 4 +- go.sum | 7 + {lib => interfaces}/interfaces.go | 2 +- main.go | 264 ++++++++++++++++++++++++++++++ 6 files changed, 276 insertions(+), 244 deletions(-) delete mode 100644 get-weather.go rename {lib => interfaces}/interfaces.go (99%) create mode 100644 main.go diff --git a/.gitignore b/.gitignore index 48a3fc2..145731f 100644 --- a/.gitignore +++ b/.gitignore @@ -33,5 +33,5 @@ go.work ======= .env -get-weather +poly-weather-script-go >>>>>>> 1f5ce74 (updated gitignore) diff --git a/get-weather.go b/get-weather.go deleted file mode 100644 index 4894f0b..0000000 --- a/get-weather.go +++ /dev/null @@ -1,241 +0,0 @@ -package main - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "log" - "net/http" - "os" - "strings" - - "github.com/joho/godotenv" - - "vikingowl/getweather/lib" -) - -// Settings -var city = "" -var apiKey = "" // get your api key on https://openweathermap.org/ -var location_lat = "" -var location_lon = "" -var units = "metric" -var temperature_unit = "C" -var baseUrl = "https://api.openweathermap.org/data/2.5" - -var atmophere_icons_list = map[int]string{ - 701: "", // Mist - 711: "", // Smoke - 721: "", // Haze - 731: "", // Dust (Sand / dust whirls) - 741: "", // Fog - 751: "", // Sand - 761: "", // Dust - 762: "", // Ash - 771: "", // Squalls - 781: "", // Tornado -} - -func setColor(apiIcon string) (color string, icon string) { - colorIcons := map[string]map[string]string{ - "#fdd835": { // yellow - "01d": "", - "01n": "", - "02d": "", - "02n": "", - "04d": "", - "04n": "", - "11d": "", - "11n": "", - }, - "$foreground": { // foreground - "03d": "", - "03n": "", - }, - "#42a5f5": { // blue - "09d": "", - "09n": "", - "10d": "", - "10n": "", - }, - "#4dd0e1": { // cyan - "13d": "ﰕ", - "13n": "ﰕ", - }, - "#9e9e9e": { // gray - "50d": "", - "50n": "", - }, - } - - for colorI, icons := range colorIcons { - if iconI, f := icons[apiIcon]; f { - color = colorI - icon = iconI - } - } - - return color, icon -} - -func setUrls(apiKey string) lib.Urls { - urls := lib.Urls{} - if city == "" { - if location_lat == "" && location_lon == "" { - res, err := http.Get("https://location.services.mozilla.com/v1/geolocate?key=geoclue") - if err != nil { - log.Fatal(err) - } - - if res.StatusCode >= 200 && res.StatusCode < 300 { - defer res.Body.Close() - - body, err := ioutil.ReadAll(res.Body) - if err != nil { - log.Fatal(err) - } - - location := lib.GeoLocation{} - if err := json.Unmarshal(body, &location); err != nil { - log.Fatal(err) - } - - // TODO: Needs better casting to string - location_lat = fmt.Sprintf("%v", location.Location.Lat) - location_lon = fmt.Sprintf("%v", location.Location.Lon) - // ------------------------------------ - } else { - log.Fatal(res.StatusCode) - } - } - - urls.Url = fmt.Sprintf("%s/weather?lat=%s&lon=%s&units=%s&appid=%s", baseUrl, location_lat, location_lon, units, apiKey) - urls.Url_forecast = fmt.Sprintf("%s/forecast?lat=%s&lon=%s&units=%s&appid=%s", baseUrl, location_lat, location_lon, units, apiKey) - } else { - urls.Url = fmt.Sprintf("%s/weather?q=%s&units=%s&appid=%s", baseUrl, city, units, apiKey) - urls.Url_forecast = fmt.Sprintf("%s/forecast?q=%s&units=%s&appid=%s", baseUrl, city, units, apiKey) - } - - return urls -} - -// TODO: Error handling -func getWeather(url string) (lib.Weather, error) { - weather := lib.Weather{} - - res, err := http.Get(url) - if err != nil { - log.Fatal(err) - } - - defer res.Body.Close() - - body, err := ioutil.ReadAll(res.Body) - if err != nil { - log.Fatal(err) - } - - if err := json.Unmarshal(body, &weather); err != nil { - log.Fatal("weather: ", err) - } - - return weather, err -} - -// TODO: Error handling -func getForecast(url string) (lib.Forecast, error) { - forecast := lib.Forecast{} - - res, err := http.Get(url) - if err != nil { - log.Fatal(err) - } - - defer res.Body.Close() - - body, err := ioutil.ReadAll(res.Body) - if err != nil { - log.Fatal(err) - } - - if err := json.Unmarshal(body, &forecast); err != nil { - log.Fatal("forecast: ", err) - } - - return forecast, err -} - -func main() { - if err := godotenv.Load(".env"); err != nil { - log.Fatal(err) - } - if apiKey == "" { - apiKey = os.Getenv("API_KEY") - if apiKey == "" { - fmt.Println("You need an API KEY to use this script! Get one on https://openweathermap.org/") - os.Exit(1) - } - } - if location_lat == "" { - location_lat = os.Getenv("LAT") - } - if location_lon == "" { - location_lon = os.Getenv("LNG") - } - - // TODO: Better error handling - urls := setUrls(apiKey) - weatherData, wErr := getWeather(urls.Url) - forecastData, fErr := getForecast(urls.Url_forecast) - // --------------------------- - var curr string - var forecast string - var atmosphere string - var atmosphereForecast string - - // process weather data - if wErr == nil { - // Get info from data - id := int(weatherData.Weather[0].ID) - group := strings.Title(weatherData.Weather[0].Main) - apiIcon := weatherData.Weather[0].Icon - temp := fmt.Sprintf("%.1f", weatherData.Main.Temp) - - color, icon := setColor(apiIcon) - - // Load other icons for Atmosphere group - if group == "Atmosphere" { - atmosphere = "%{F#e57c46}" + atmophere_icons_list[id] + "%{F$foreground} " + temp + "°" + temperature_unit + "%{F-}" - } - - curr = "%{F" + color + "}" + icon + "%{F$foreground} " + temp + "°" + temperature_unit + "%{F-}" - } else { - forecast = "勒" - } - - // process forecast data - if fErr == nil { - // Get info from data - id := int(forecastData.List[0].Weather[0].ID) - group := strings.Title(forecastData.List[0].Weather[0].Main) - apiIcon := forecastData.List[0].Weather[0].Icon - temp := fmt.Sprintf("%.1f", forecastData.List[0].Main.Temp) - - color, icon := setColor(apiIcon) - - // Load other icons for Atmosphere group - if group == "Atmosphere" { - atmosphereForecast = "%{F#e57c46}" + atmophere_icons_list[id] + "{F$foreground} " + temp + "°" + temperature_unit + "%{F-}" - } - - forecast = "%{F" + color + "}" + icon + "%{F$foreground} " + temp + "°" + temperature_unit + "%{F-}" - } else { - forecast = "勒" - } - - if atmosphere == "" { - fmt.Printf("%s  %s", curr, forecast) - } else { - fmt.Printf("%s  %s", atmosphere, atmosphereForecast) - } -} diff --git a/go.mod b/go.mod index 91deafc..e4b2dd5 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module vikingowl/getweather +module vikingowl/poly-weather-script-go go 1.17 @@ -6,6 +6,8 @@ require rsc.io/quote v1.5.2 require ( github.com/joho/godotenv v1.4.0 // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 // indirect golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect rsc.io/sampler v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index b6960c3..74a8797 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,12 @@ +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= rsc.io/quote v1.5.2 h1:w5fcysjrx7yqtD/aO+QwRjYZOKnaM9Uh2b40tElTs3Y= diff --git a/lib/interfaces.go b/interfaces/interfaces.go similarity index 99% rename from lib/interfaces.go rename to interfaces/interfaces.go index 17aa669..c78c0e7 100644 --- a/lib/interfaces.go +++ b/interfaces/interfaces.go @@ -1,4 +1,4 @@ -package lib +package interfaces type Urls struct { Url string diff --git a/main.go b/main.go new file mode 100644 index 0000000..e358ecc --- /dev/null +++ b/main.go @@ -0,0 +1,264 @@ +package main + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "strings" + + log "github.com/sirupsen/logrus" + + interfaces "vikingowl/poly-weather-script-go/interfaces" +) + +// Settings +var ( + // optional + city = "" + location_lat = "" + location_lon = "" + // required + apiKey = "" // get your api key on https://openweathermap.org/ + units = "metric" + temperature_unit = "C" + baseUrl = "https://api.openweathermap.org/data/2.5" + + atmophere_icons_list = map[int]string{ + 701: "", // Mist + 711: "", // Smoke + 721: "", // Haze + 731: "", // Dust (Sand / dust whirls) + 741: "", // Fog + 751: "", // Sand + 761: "", // Dust + 762: "", // Ash + 771: "", // Squalls + 781: "", // Tornado + } +) + +func setColor(apiIcon string) (color string, icon string) { + colorIcons := map[string]map[string]string{ + "#fdd835": { // yellow + "01d": "", + "01n": "", + "02d": "", + "02n": "", + "04d": "", + "04n": "", + "11d": "", + "11n": "", + }, + "$foreground": { // foreground + "03d": "", + "03n": "", + }, + "#42a5f5": { // blue + "09d": "", + "09n": "", + "10d": "", + "10n": "", + }, + "#4dd0e1": { // cyan + "13d": "ﰕ", + "13n": "ﰕ", + }, + "#9e9e9e": { // gray + "50d": "", + "50n": "", + }, + } + + for colorI, icons := range colorIcons { + if iconI, f := icons[apiIcon]; f { + color = colorI + icon = iconI + } + } + + return +} + +func getLocation() { + res, err := http.Get("https://location.services.mozilla.com/v1/geolocate?key=geoclue") + if err != nil { + log.Warningf("[GL] unable to get location: %v", err) + } + + if res.StatusCode >= 200 && res.StatusCode < 300 { + defer res.Body.Close() + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + log.Warningf("[GL] unable to read location response: %v", err) + } + + location := interfaces.GeoLocation{} + if err := json.Unmarshal(body, &location); err != nil { + log.Warningf("[GL] unable to marshal location data: %v", err) + } + + location_lat = fmt.Sprint(location.Location.Lat) + location_lon = fmt.Sprint(location.Location.Lon) + } else { + // TODO: needs updating if errors occur + log.Warningf("[GL] something went wrong while getting the location: %v", res.StatusCode) + } + +} + +func setUrls(apiKey string) (urls interfaces.Urls) { + if city == "" { + if location_lat == "" && location_lon == "" { + getLocation() + } + + urls.Url = fmt.Sprintf("%s/weather?lat=%s&lon=%s&units=%s&appid=%s", baseUrl, location_lat, location_lon, units, apiKey) + urls.Url_forecast = fmt.Sprintf("%s/forecast?lat=%s&lon=%s&units=%s&appid=%s", baseUrl, location_lat, location_lon, units, apiKey) + } else { + urls.Url = fmt.Sprintf("%s/weather?q=%s&units=%s&appid=%s", baseUrl, city, units, apiKey) + urls.Url_forecast = fmt.Sprintf("%s/forecast?q=%s&units=%s&appid=%s", baseUrl, city, units, apiKey) + } + + return +} + +func getWeather(url string) (weather interfaces.Weather) { + res, err := http.Get(url) + if err != nil { + log.Warningf("[GW] unable to get weather: %v", err) + } + + if res.StatusCode >= 200 && res.StatusCode < 300 { + defer res.Body.Close() + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + log.Warningf("[GW] unable to read weather: %v", err) + } + + if err := json.Unmarshal(body, &weather); err != nil { + log.Warningf("[GW] unable to marshal weather data: %v", err) + } + } else { + if res.StatusCode == 400 { + log.Warning("[GW] bad request") + } else if res.StatusCode == 401 { + log.Warning("[GW] unauthorized - wrong api key") + } else { + log.Warningf("[GW] something went wrong while getting the weather: %v", res.StatusCode) + } + } + + return +} + +func getForecast(url string) (forecast interfaces.Forecast) { + res, err := http.Get(url) + if err != nil { + log.Warningf("[GF] unable to get forecast: %v", err) + } + + if res.StatusCode >= 200 && res.StatusCode < 300 { + defer res.Body.Close() + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + log.Warningf("[GF] unable to read forecast: %v", err) + } + + if err := json.Unmarshal(body, &forecast); err != nil { + log.Warningf("[GF] unable to marshal forecast data: %v", err) + } + } else { + if res.StatusCode == 400 { + log.Warning("[GF] bad request") + } else if res.StatusCode == 401 { + log.Warning("[GF] unauthorized - wrong api key") + } else { + log.Warningf("[GF] something went wrong while getting the forecast: %v", res.StatusCode) + } + } + + return +} + +func main() { + // try to get apiKey and location from environment + // LOOKS LIKE THIS DOESN'T WORK IN POLYBAR + // TODO: Needs fix + // if apiKey == "" { + // apiKey = os.Getenv("OPEN_WEATHER_MAP_API_KEY") + // if apiKey == "" { + // log.Warning("[main] you need an API KEY to use this script! Get one on https://openweathermap.org/") + // os.Exit(1) + // } + // } + // if location_lat == "" { + // location_lat = fmt.Sprint(os.Getenv("LAT")) + // } + // if location_lon == "" { + // location_lon = fmt.Sprint(os.Getenv("LNG")) + // } + // ----------------------------------------------- + + // api calls + urls := setUrls(apiKey) + weatherData := getWeather(urls.Url) + forecastData := getForecast(urls.Url_forecast) + + var ( + curr string + forecast string + atmosphere string + atmosphereForecast string + ) + + // process weather data + if weatherData.Weather[0].ID != 0 { + // Get info from data + id := int(weatherData.Weather[0].ID) + group := strings.Title(weatherData.Weather[0].Main) + apiIcon := weatherData.Weather[0].Icon + temp := fmt.Sprintf("%.1f", weatherData.Main.Temp) + + color, icon := setColor(apiIcon) + + // Load other icons for Atmosphere group + if group == "Atmosphere" { + atmosphere = "%{F#e57c46}" + atmophere_icons_list[id] + "%{F$foreground} " + temp + "°" + temperature_unit + "%{F-}" + } + + curr = "%{F" + color + "}" + icon + "%{F$foreground} " + temp + "°" + temperature_unit + "%{F-}" + } else { + forecast = "勒" + } + + // process forecast data + if forecastData.List[0].Weather[0].ID != 0 { + // Get info from data + id := int(forecastData.List[0].Weather[0].ID) + group := strings.Title(forecastData.List[0].Weather[0].Main) + apiIcon := forecastData.List[0].Weather[0].Icon + temp := fmt.Sprintf("%.1f", forecastData.List[0].Main.Temp) + + color, icon := setColor(apiIcon) + + // Load other icons for Atmosphere group + if group == "Atmosphere" { + atmosphereForecast = "%{F#e57c46}" + atmophere_icons_list[id] + "{F$foreground} " + temp + "°" + temperature_unit + "%{F-}" + } + + forecast = "%{F" + color + "}" + icon + "%{F$foreground} " + temp + "°" + temperature_unit + "%{F-}" + } else { + forecast = "勒" + } + + // print output + if atmosphere == "" { + fmt.Printf("%s  %s", curr, forecast) + } else { + fmt.Printf("%s  %s", atmosphere, atmosphereForecast) + } +}