You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

118 lines
2.7 KiB
Go

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
}
}