140 lines
3.2 KiB
Go
140 lines
3.2 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
defaultForecastTTL = 10 * time.Minute
|
|
)
|
|
|
|
func main() {
|
|
if err := run(); err != nil {
|
|
fmt.Fprintln(os.Stderr, err.Error())
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func run() error {
|
|
var (
|
|
search string
|
|
includeDesc bool
|
|
prettyOutput bool
|
|
temperatureU string
|
|
clearCache bool
|
|
refresh bool
|
|
iconTest bool
|
|
)
|
|
|
|
flag.StringVar(&search, "s", "", "Search location (e.g. \"Somerville, MA\")")
|
|
flag.StringVar(&search, "search", "", "Search location (e.g. \"Somerville, MA\")")
|
|
flag.BoolVar(&includeDesc, "d", false, "Include forecast description text")
|
|
flag.BoolVar(&includeDesc, "desc", false, "Include forecast description text")
|
|
flag.BoolVar(&prettyOutput, "pretty", false, "Enable NerdFont icons")
|
|
flag.BoolVar(&prettyOutput, "p", false, "Enable NerdFont icons")
|
|
flag.StringVar(&temperatureU, "u", "F", "Temperature unit (F or C)")
|
|
flag.StringVar(&temperatureU, "units", "F", "Temperature unit (F or C)")
|
|
flag.BoolVar(&clearCache, "clear-cache", false, "Clear cached location and forecast data")
|
|
flag.BoolVar(&clearCache, "c", false, "Clear cached location and forecast data")
|
|
flag.BoolVar(&refresh, "refresh", false, "Force refresh forecast data")
|
|
flag.BoolVar(&refresh, "r", false, "Force refresh forecast data")
|
|
flag.BoolVar(&iconTest, "icon-test", false, "Print all icons used by the program")
|
|
flag.BoolVar(&iconTest, "i", false, "Print all icons used by the program")
|
|
flag.Parse()
|
|
|
|
ua, err := buildUserAgent()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
temperatureU = strings.ToUpper(strings.TrimSpace(temperatureU))
|
|
if temperatureU == "" {
|
|
temperatureU = "F"
|
|
}
|
|
if temperatureU != "F" && temperatureU != "C" {
|
|
return fmt.Errorf("invalid unit: %s", temperatureU)
|
|
}
|
|
|
|
cacheDir, err := cacheRoot()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cache := NewCache(cacheDir)
|
|
ctx := context.Background()
|
|
|
|
if iconTest {
|
|
printIconTest()
|
|
return nil
|
|
}
|
|
|
|
if clearCache {
|
|
if err := cache.Clear(); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
var loc Location
|
|
if search != "" {
|
|
results, err := SearchLocations(ctx, search, ua)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
loc, err = SelectLocation(results)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := cache.SaveLocation(search, loc); err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
var ok bool
|
|
loc, ok, err = cache.LoadLocation()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !ok {
|
|
return fmt.Errorf("no cached location found; use -s to set a location")
|
|
}
|
|
}
|
|
|
|
client := NewNWSClient(ua)
|
|
var period ForecastPeriod
|
|
if refresh {
|
|
var err error
|
|
period, err = client.FetchForecast(ctx, loc, temperatureU)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := cache.SaveForecast(loc, temperatureU, period); err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
var err error
|
|
var fromCache bool
|
|
period, fromCache, err = cache.LoadForecast(loc, temperatureU, defaultForecastTTL)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !fromCache {
|
|
period, err = client.FetchForecast(ctx, loc, temperatureU)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := cache.SaveForecast(loc, temperatureU, period); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
line := FormatOutput(loc, period, includeDesc, prettyOutput)
|
|
fmt.Println(line)
|
|
return nil
|
|
}
|