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