feat: Add new cmd for forecasts
Signed-off-by: Tim Hårek Andreassen <tim@harek.no>
This commit is contained in:
parent
b350835718
commit
65dd6ad1f5
4 changed files with 135 additions and 3 deletions
100
cmd/forecast.go
Normal file
100
cmd/forecast.go
Normal file
|
@ -0,0 +1,100 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"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/charmbracelet/lipgloss"
|
||||
"github.com/charmbracelet/lipgloss/table"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var forecastCmd = &cobra.Command{
|
||||
Use: "forecast <location>",
|
||||
Aliases: []string{"f", "ls"},
|
||||
Short: "Get forecasted weather",
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
Run: forecast,
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(forecastCmd)
|
||||
}
|
||||
|
||||
func forecast(cmd *cobra.Command, args []string) {
|
||||
isJson, err := cmd.Flags().GetBool(flags.JSON)
|
||||
cobra.CheckErr(err)
|
||||
lon, _ := cmd.Flags().GetFloat64(flags.LON)
|
||||
lat, _ := cmd.Flags().GetFloat64(flags.LAT)
|
||||
|
||||
c, err := yr.New()
|
||||
cobra.CheckErr(err)
|
||||
|
||||
if len(args) == 0 && (lon == 0 || lat == 0) {
|
||||
fmt.Fprintln(os.Stderr, "No location or coordinates provided.")
|
||||
os.Exit(1)
|
||||
}
|
||||
var f []yr.Forecast
|
||||
if len(args) == 0 {
|
||||
f, err = c.ForecastCoords(&nominatim.Coordinates{Longitude: lon, Latitude: lat}, nil)
|
||||
cobra.CheckErr(err)
|
||||
|
||||
} else {
|
||||
location := args[0]
|
||||
f, err = c.Forecast(location)
|
||||
cobra.CheckErr(err)
|
||||
|
||||
}
|
||||
|
||||
if isJson {
|
||||
j, err := json.MarshalIndent(f, "", " ")
|
||||
cobra.CheckErr(err)
|
||||
fmt.Printf("%s", j)
|
||||
return
|
||||
}
|
||||
|
||||
re := lipgloss.NewRenderer(os.Stdout)
|
||||
|
||||
const (
|
||||
white = lipgloss.Color("#fff")
|
||||
lightGray = lipgloss.Color("#dedede")
|
||||
)
|
||||
var (
|
||||
HeaderStyle = re.NewStyle().Foreground(white).Bold(true).Align(lipgloss.Center)
|
||||
CellStyle = re.NewStyle().Padding(0, 2)
|
||||
EvenRowStyle = CellStyle.Foreground(lightGray)
|
||||
BorderStyle = lipgloss.NewStyle().Foreground(white)
|
||||
)
|
||||
|
||||
t := table.New().
|
||||
Border(lipgloss.NormalBorder()).
|
||||
BorderStyle(BorderStyle).
|
||||
StyleFunc(func(row, col int) lipgloss.Style {
|
||||
switch {
|
||||
case row == 0:
|
||||
return HeaderStyle
|
||||
case row%2 == 0:
|
||||
return EvenRowStyle
|
||||
default:
|
||||
return CellStyle
|
||||
}
|
||||
}).
|
||||
Headers("time", "temp.", "rain", "wind")
|
||||
|
||||
for _, item := range f {
|
||||
t.Row(
|
||||
item.Time.Format(time.DateTime),
|
||||
fmt.Sprintf("%.1f °C", item.Temperature),
|
||||
fmt.Sprintf("%.1f mm", item.Percipitation),
|
||||
fmt.Sprintf("%.1f m/s %s", item.Wind.Speed, item.Wind.DirectionToString()),
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
fmt.Println(t)
|
||||
}
|
9
go.mod
9
go.mod
|
@ -8,12 +8,21 @@ require (
|
|||
)
|
||||
|
||||
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
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/muesli/termenv v0.15.2 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
golang.org/x/sys v0.19.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
|
20
go.sum
20
go.sum
|
@ -1,3 +1,9 @@
|
|||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||
github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw=
|
||||
github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY=
|
||||
github.com/charmbracelet/x/ansi v0.1.4 h1:IEU3D6+dWwPSgZ6HBH+v6oUuZ/nVawMiWj5831KfiLM=
|
||||
github.com/charmbracelet/x/ansi v0.1.4/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
|
@ -11,9 +17,20 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
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/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=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
|
@ -24,6 +41,9 @@ 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.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=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
|
|
9
yr/yr.go
9
yr/yr.go
|
@ -4,6 +4,7 @@ import (
|
|||
"cmp"
|
||||
"fmt"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"git.sr.ht/~timharek/yr-go/internal/met"
|
||||
"git.sr.ht/~timharek/yr-go/internal/nominatim"
|
||||
|
@ -66,9 +67,10 @@ func windDirection(d float64) string {
|
|||
|
||||
type Forecast struct {
|
||||
nominatim.LookupResult
|
||||
Temperature float64 `json:"temperature"` // In celsius
|
||||
Percipitation float64 `json:"percipitation"` // In mm
|
||||
Wind wind `json:"wind"` // In m/s
|
||||
Time time.Time `json:"time"`
|
||||
Temperature float64 `json:"temperature"` // In celsius
|
||||
Percipitation float64 `json:"percipitation"` // In mm
|
||||
Wind wind `json:"wind"` // In m/s
|
||||
}
|
||||
|
||||
func (c *Client) Now(q string) (*Forecast, error) {
|
||||
|
@ -155,6 +157,7 @@ func (c *Client) ForecastCoords(coords *nominatim.Coordinates, location *string)
|
|||
|
||||
forecasts = append(forecasts, Forecast{
|
||||
LookupResult: *lookupResult,
|
||||
Time: t.Time,
|
||||
Temperature: t.Data.Instant.Details.AirTemperature,
|
||||
Percipitation: float64(percipitation),
|
||||
Wind: wind{
|
||||
|
|
Loading…
Reference in a new issue