Files

293 lines
7.1 KiB
Go

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