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 }