diff --git a/cmd/flags/flags.go b/cmd/flags/flags.go index 40bf4b1..babf6d6 100644 --- a/cmd/flags/flags.go +++ b/cmd/flags/flags.go @@ -6,4 +6,5 @@ const ( JSON = "json" INTERVAL = "interval" UTC = "utc" + WEB = "web" ) diff --git a/cmd/forecast.go b/cmd/forecast.go index 4feeffb..18acd9b 100644 --- a/cmd/forecast.go +++ b/cmd/forecast.go @@ -11,6 +11,7 @@ import ( "git.sr.ht/~timharek/yr-go/yr" "github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss/table" + "github.com/pkg/browser" "github.com/spf13/cobra" ) @@ -32,6 +33,8 @@ func forecast(cmd *cobra.Command, args []string) { cobra.CheckErr(err) isUTC, err := cmd.Flags().GetBool(flags.UTC) cobra.CheckErr(err) + isWeb, err := cmd.Flags().GetBool(flags.WEB) + cobra.CheckErr(err) lon, _ := cmd.Flags().GetFloat64(flags.LON) lat, _ := cmd.Flags().GetFloat64(flags.LAT) interval, _ := cmd.Flags().GetInt(flags.INTERVAL) @@ -43,7 +46,7 @@ func forecast(cmd *cobra.Command, args []string) { fmt.Fprintln(os.Stderr, "No location or coordinates provided.") os.Exit(1) } - var f []yr.Forecast + f := &yr.ForecastResult{} if len(args) == 0 { f, err = c.ForecastCoords(&nominatim.Coordinates{Longitude: lon, Latitude: lat}, nil) cobra.CheckErr(err) @@ -53,8 +56,17 @@ func forecast(cmd *cobra.Command, args []string) { cobra.CheckErr(err) } + if isWeb { + url := fmt.Sprintf("https://www.yr.no/en/forecast/daily-table/%.4f,%.4f", f.Coordinates.Latitude, f.Coordinates.Longitude) + err := browser.OpenURL(url) + if err != nil { + cobra.CheckErr(err) + } + os.Exit(0) + } + if interval > 0 { - f = f[:interval] + f.Forecast = f.Forecast[:interval] } if isJson { @@ -92,7 +104,7 @@ func forecast(cmd *cobra.Command, args []string) { }). Headers("time", "temp.", "rain", "wind") - for _, item := range f { + for _, item := range f.Forecast { itemTime := item.Time.Local() if isUTC { itemTime = item.Time diff --git a/cmd/now.go b/cmd/now.go index 4aa5396..2822031 100644 --- a/cmd/now.go +++ b/cmd/now.go @@ -9,6 +9,7 @@ import ( "git.sr.ht/~timharek/yr-go/cmd/flags" "git.sr.ht/~timharek/yr-go/internal/nominatim" "git.sr.ht/~timharek/yr-go/yr" + "github.com/pkg/browser" "github.com/spf13/cobra" ) @@ -29,6 +30,8 @@ func now(cmd *cobra.Command, args []string) { cobra.CheckErr(err) isUTC, err := cmd.Flags().GetBool(flags.UTC) cobra.CheckErr(err) + isWeb, err := cmd.Flags().GetBool(flags.WEB) + cobra.CheckErr(err) lon, _ := cmd.Flags().GetFloat64(flags.LON) lat, _ := cmd.Flags().GetFloat64(flags.LAT) @@ -39,20 +42,31 @@ func now(cmd *cobra.Command, args []string) { fmt.Fprintln(os.Stderr, "No location or coordinates provided.") os.Exit(1) } - n := &yr.Forecast{} + f := &yr.ForecastResult{} if len(args) == 0 { - n, err = c.NowCoords(&nominatim.Coordinates{Longitude: lon, Latitude: lat}, nil) + f, err = c.NowCoords(&nominatim.Coordinates{Longitude: lon, Latitude: lat}, nil) cobra.CheckErr(err) } else { location := args[0] - n, err = c.Now(location) + f, err = c.Now(location) cobra.CheckErr(err) } + if isWeb { + url := fmt.Sprintf("https://www.yr.no/en/forecast/hourly-table/%.4f,%.4f/?i=0", f.Coordinates.Latitude, f.Coordinates.Longitude) + err := browser.OpenURL(url) + if err != nil { + cobra.CheckErr(err) + } + os.Exit(0) + } + + n := f.Forecast[0] + if isJson { - j, err := json.MarshalIndent(n, "", " ") + j, err := json.MarshalIndent(f, "", " ") cobra.CheckErr(err) fmt.Printf("%s", j) return diff --git a/cmd/root.go b/cmd/root.go index 7551574..f8b7c08 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -23,6 +23,7 @@ func Execute() { func init() { rootCmd.PersistentFlags().Bool(flags.JSON, false, "Result in JSON") rootCmd.PersistentFlags().Bool(flags.UTC, false, "Result times in UTC") + rootCmd.PersistentFlags().Bool(flags.WEB, false, "Open result in browser") rootCmd.PersistentFlags().Float64P(flags.LON, "x", 0, "Longitude coordinate") rootCmd.PersistentFlags().Float64P(flags.LAT, "y", 0, "Latitude coordinate") } diff --git a/go.mod b/go.mod index 936eb6b..dabd9c8 100644 --- a/go.mod +++ b/go.mod @@ -3,13 +3,14 @@ module git.sr.ht/~timharek/yr-go go 1.23.1 require ( + github.com/charmbracelet/lipgloss v0.13.0 + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 ) require ( github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect - github.com/charmbracelet/lipgloss v0.13.0 // indirect github.com/charmbracelet/x/ansi v0.1.4 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect diff --git a/go.sum b/go.sum index 6c95247..8ee4036 100644 --- a/go.sum +++ b/go.sum @@ -25,6 +25,8 @@ github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZ github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -41,6 +43,7 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/justfile b/justfile index bd10a06..c53eafa 100644 --- a/justfile +++ b/justfile @@ -12,3 +12,6 @@ test: tidy: go mod tidy + +vet: + go vet ./... diff --git a/yr/yr.go b/yr/yr.go index 92ee4b7..6bf9319 100644 --- a/yr/yr.go +++ b/yr/yr.go @@ -73,7 +73,12 @@ type Forecast struct { Wind wind `json:"wind"` // In m/s } -func (c *Client) Now(q string) (*Forecast, error) { +type ForecastResult struct { + Coordinates nominatim.Coordinates `json:"coordinates"` + Forecast []Forecast `json:"forecast"` +} + +func (c *Client) Now(q string) (*ForecastResult, error) { coords, err := c.nom.Lookup(q) if err != nil { return nil, err @@ -85,18 +90,18 @@ func (c *Client) Now(q string) (*Forecast, error) { }, &coords.Location) } -func (c *Client) NowCoords(coords *nominatim.Coordinates, location *string) (*Forecast, error) { - forecasts, err := c.ForecastCoords(coords, location) +func (c *Client) NowCoords(coords *nominatim.Coordinates, location *string) (*ForecastResult, error) { + result, err := c.ForecastCoords(coords, location) if err != nil { return nil, err } - now := forecasts[0] + result.Forecast = result.Forecast[0:] - return &now, nil + return result, nil } -func (c *Client) Forecast(q string) ([]Forecast, error) { +func (c *Client) Forecast(q string) (*ForecastResult, error) { coords, err := c.nom.Lookup(q) if err != nil { return nil, err @@ -108,7 +113,7 @@ func (c *Client) Forecast(q string) ([]Forecast, error) { }, &coords.Location) } -func (c *Client) ForecastCoords(coords *nominatim.Coordinates, location *string) ([]Forecast, error) { +func (c *Client) ForecastCoords(coords *nominatim.Coordinates, location *string) (*ForecastResult, error) { f, err := c.met.Forecast(coords.Latitude, coords.Longitude, nil) if err != nil { return nil, err @@ -168,7 +173,13 @@ func (c *Client) ForecastCoords(coords *nominatim.Coordinates, location *string) } - return forecasts, nil + return &ForecastResult{ + Coordinates: nominatim.Coordinates{ + Longitude: coords.Longitude, + Latitude: coords.Latitude, + }, + Forecast: forecasts, + }, nil } func sortTimeSeries(a, b met.Timeseries) int {