package main import ( "bytes" "encoding/json" "fmt" "os" "os/exec" "strings" ) type Weather struct { Temp float64 Humidity int Icon rune City string State string } type weathercode rune const ( CLEAR_DAY weathercode = '\ue30d' CLEAR_NIGHT weathercode = '\ue32b' PARTLY_CLOUDY_DAY weathercode = '\ue302' PARTLY_CLOUDY_NIGHT weathercode = '\ue379' CLOUDY weathercode = '\ue312' RAIN weathercode = '\ue318' THUNDERSTORM weathercode = '\ue31d' SNOW weathercode = '\ue31a' FOG weathercode = '\ue313' DEGREES_F weathercode = '\ue341' HUMIDITY weathercode = '\ue373' ) func (w *Weather) String() string { return fmt.Sprintf(" %c %.1f%c %d%c in %s, %s", w.Icon, w.Temp, DEGREES_F, w.Humidity, HUMIDITY, w.City, USStates[w.State]) // Output as ICON ##.#*F ##% in City, ST where the rune is a degree sign } func main() { city := os.Getenv("CITY") if city == "" { fmt.Print("No location found!") os.Exit(1) } city = strings.Trim(city, " \n") weathercmd := exec.Command("sh", "-c", "${HOME}/.dotfiles/bin/weather/weather.sh") var out bytes.Buffer weathercmd.Stdout = &out if err := weathercmd.Run(); err != nil { panic(err) } // parsing json time :D var temp map[string]interface{} if err := json.Unmarshal(out.Bytes(), &temp); err != nil { panic(err) } // fmting hell weather := &Weather{City: city} for k, v := range temp { if k == "main" { // weather info for nk, nv := range v.(map[string]interface{}) { if nk == "temp" { weather.Temp = nv.(float64) } else if nk == "humidity" { weather.Humidity = int(nv.(float64)) // this is as gross as it gets } } } else if k == "name" { weather.State = v.(string) } else if k == "weather" { m := v.([]interface{}) for nk, nv := range m[0].(map[string]interface{}) { if nk == "icon" { weather.Icon = getIcon(nv.(string)) } } } } fmt.Print(weather) } func tod(day bool, dayrune weathercode, nightrune weathercode) rune { if day { return rune(dayrune) } return rune(nightrune) } func getIcon(code string) rune { weather := strings.Trim(code, "nd") // trimming day or night tag var day bool if strings.Contains(code, "d") { day = true } else { day = false } switch weather { case "01": return tod(day, CLEAR_DAY, CLEAR_NIGHT) // clear skies case "02", "03": return tod(day, PARTLY_CLOUDY_DAY, PARTLY_CLOUDY_NIGHT) // small clouds case "04": return rune(CLOUDY) // big clouds with sun case "09", "10": return rune(RAIN) case "11": return rune(THUNDERSTORM) case "13": return rune(SNOW) case "50": return rune(FOG) default: return '\uFFFD' // question mark } }