package main import ( "encoding/json" "fmt" "io/ioutil" "net/http" "os" "path/filepath" "strings" log "github.com/sirupsen/logrus" interfaces "vikingowl/poly-weather-script-go/interfaces" ) // Settings // // Please set your API_KEY in the 'config.json' file // You can get your API_KEY on https://openweathermap.org // Your optional lat and lon values go there as well const ( // optional CITY = "" // required BASE_URL = "https://api.openweathermap.org/data/2.5" // request-url UNITS = "metric" // standard (K), metric (C), imperial (F) TEMP_UNIT = "C" // K (Kelvin), C (Celsius), F (Fahrenheit) ) 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 "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() (lat string, lon string) { 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) } lat = fmt.Sprint(location.Location.Lat) 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) } return } func setUrls(API_KEY string, LAT string, LON string) (urls interfaces.Urls) { if CITY == "" { var ( location_lat string location_lon string ) if LAT == "" || LON == "" { location_lat, location_lon = getLocation() } else { location_lat = LAT location_lon = LON } urls.Url = fmt.Sprintf("%s/weather?lat=%s&lon=%s&units=%s&appid=%s", BASE_URL, location_lat, location_lon, UNITS, API_KEY) urls.Url_forecast = fmt.Sprintf("%s/forecast?lat=%s&lon=%s&units=%s&appid=%s", BASE_URL, location_lat, location_lon, UNITS, API_KEY) } else { urls.Url = fmt.Sprintf("%s/weather?q=%s&units=%s&appid=%s", BASE_URL, CITY, UNITS, API_KEY) urls.Url_forecast = fmt.Sprintf("%s/forecast?q=%s&units=%s&appid=%s", BASE_URL, CITY, UNITS, API_KEY) } 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 } type Config struct { API_KEY string `json:"apikey"` LAT string `json:"lat"` LON string `json:"lon"` } func loadConfig() (config Config) { path, err := os.Executable() if err != nil { log.Warningf("[LC] Can't get executable path: %v", err) } dir := filepath.Dir(path) content, err := ioutil.ReadFile(filepath.Join(dir, "./config.json")) if err != nil { log.Warningf("[LC] Unable to read config file: %v", err) } err = json.Unmarshal(content, &config) if err != nil { log.Warningf("[LC] Error during Unmarshal(): %v", err) } return } func main() { config := loadConfig() // check if api key is set if config.API_KEY == "" { log.Warningf("[main] you need an API KEY to use this script! Get one on https://openweathermap.org") os.Exit(1) } // api calls urls := setUrls(config.API_KEY, config.LAT, config.LON) 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-} " + temp + "°" + TEMP_UNIT + "%{F-}" } curr = "%{F" + color + "} " + icon + " %{F-} " + temp + "°" + TEMP_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-} " + temp + "°" + TEMP_UNIT + "%{F-}" } forecast = "%{F" + color + "} " + icon + " %{F-} " + temp + "°" + TEMP_UNIT + "%{F-}" } else { forecast = "勒" } // print output if atmosphere == "" { fmt.Printf("%s  %s", curr, forecast) } else { fmt.Printf("%s  %s", atmosphere, atmosphereForecast) } }