Skip to content

Commit

Permalink
Add Cobra CLI framework
Browse files Browse the repository at this point in the history
  • Loading branch information
msharris committed Mar 14, 2024
1 parent f2674e4 commit a02b3f2
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 115 deletions.
120 changes: 120 additions & 0 deletions app/app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package app

import (
"encoding/xml"
"errors"
"fmt"
"io"
"log"
"net/http"
"strconv"
"strings"
"time"
)

type XMLStations struct {
XMLName xml.Name `xml:"stations"`
Locations []XMLLocation `xml:"location"`
}

type XMLLocation struct {
XMLName xml.Name `xml:"location"`
Id string `xml:"id,attr"`
Name string `xml:"name"`
Index string `xml:"index"`
Time string `xml:"time"`
Date string `xml:"date"`
FullDate string `xml:"fulldate"`
UTCDateTime string `xml:"utcdatetime"`
Status string `xml:"status"`
}

type Station struct {
Id string
Name string
UVIndex float64
Time time.Time
Available bool
}

func (xmlStations *XMLStations) Stations() []Station {
var stations []Station
for _, xmlLoc := range xmlStations.Locations {
stations = append(stations, xmlLoc.Station())
}
return stations
}

func (xmlLoc *XMLLocation) Station() Station {
station := Station{
Id: strings.ToUpper(xmlLoc.Name),
Name: xmlLoc.Id,
Available: xmlLoc.Status == "ok",
}

station.UVIndex, _ = strconv.ParseFloat(xmlLoc.Index, 64)

station.Time, _ = time.Parse("2006/01/02 15:04", xmlLoc.UTCDateTime)
if locName, err := getLocationName(station.Name); err == nil {
loc, _ := time.LoadLocation(locName)
station.Time = station.Time.In(loc)
}

return station
}

func getLocationName(stationName string) (string, error) {
m := map[string]string{
"Adelaide": "Australia/Adelaide",
"Alice Springs": "Australia/Darwin",
"Brisbane": "Australia/Brisbane",
"Canberra": "Australia/Sydney",
"Casey": "Antarctica/Casey",
"Darwin": "Australia/Darwin",
"Davis": "Antarctica/Davis",
"Emerald": "Australia/Brisbane",
"Gold Coast": "Australia/Brisbane",
"Kingston": "Australia/Hobart",
"Macquarie Island": "Antarctica/Macquarie",
"Mawson": "Antarctica/Mawson",
"Melbourne": "Australia/Melbourne",
"Newcastle": "Australia/Sydney",
"Perth": "Australia/Perth",
"Sydney": "Australia/Sydney",
"Townsville": "Australia/Brisbane",
}

if name, ok := m[stationName]; !ok {
return name, errors.New(fmt.Sprintf("No time zone configured for station %v", stationName))
} else {
return name, nil
}
}

func (s Station) String() string {
return fmt.Sprintf("%-17v %4.1f %v", s.Name, s.UVIndex, s.Time.Format("Mon 2 Jan 3:04 pm"))
}

func Run() {
resp, err := http.Get("https://uvdata.arpansa.gov.au/xml/uvvalues.xml")
if err != nil {
log.Fatal("ARPANSA data file unavailable")
}
defer resp.Body.Close()

body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal("Unable to read ARPANSA data file")
}

var xmlStations XMLStations
err = xml.Unmarshal(body, &xmlStations)
if err != nil {
log.Fatal("Unexpected format of ARPANSA data file")
}

stations := xmlStations.Stations()
for _, s := range stations {
fmt.Println(s)
}
}
30 changes: 30 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package cmd

import (
"fmt"
"github.com/msharris/uv/app"
"github.com/spf13/cobra"
"os"
)

var rootCmd = &cobra.Command{
Use: "uv",
Short: "Shows the current UV index for various locations around Australia",
Long: `uv is an app that shows the current UV index for various locations around Australia.
UV observations are sourced from the ARPANSA API.`,
Run: func(cmd *cobra.Command, args []string) {
app.Run()
},
}

func Execute() {
err := rootCmd.Execute()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}

func init() {
// Flags will go here
}
7 changes: 7 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
module github.com/msharris/uv

go 1.22

require github.com/spf13/cobra v1.8.0

require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
)
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
117 changes: 2 additions & 115 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,120 +1,7 @@
package main

import (
"encoding/xml"
"errors"
"fmt"
"io"
"log"
"net/http"
"strconv"
"strings"
"time"
)

type XMLStations struct {
XMLName xml.Name `xml:"stations"`
Locations []XMLLocation `xml:"location"`
}

type XMLLocation struct {
XMLName xml.Name `xml:"location"`
Id string `xml:"id,attr"`
Name string `xml:"name"`
Index string `xml:"index"`
Time string `xml:"time"`
Date string `xml:"date"`
FullDate string `xml:"fulldate"`
UTCDateTime string `xml:"utcdatetime"`
Status string `xml:"status"`
}

type Station struct {
Id string
Name string
UVIndex float64
Time time.Time
Available bool
}

func (xmlStations *XMLStations) Stations() []Station {
var stations []Station
for _, xmlLoc := range xmlStations.Locations {
stations = append(stations, xmlLoc.Station())
}
return stations
}

func (xmlLoc *XMLLocation) Station() Station {
station := Station{
Id: strings.ToUpper(xmlLoc.Name),
Name: xmlLoc.Id,
Available: xmlLoc.Status == "ok",
}

station.UVIndex, _ = strconv.ParseFloat(xmlLoc.Index, 64)

station.Time, _ = time.Parse("2006/01/02 15:04", xmlLoc.UTCDateTime)
if locName, err := getLocationName(station.Name); err == nil {
loc, _ := time.LoadLocation(locName)
station.Time = station.Time.In(loc)
}

return station
}

func getLocationName(stationName string) (string, error) {
m := map[string]string{
"Adelaide": "Australia/Adelaide",
"Alice Springs": "Australia/Darwin",
"Brisbane": "Australia/Brisbane",
"Canberra": "Australia/Sydney",
"Casey": "Antarctica/Casey",
"Darwin": "Australia/Darwin",
"Davis": "Antarctica/Davis",
"Emerald": "Australia/Brisbane",
"Gold Coast": "Australia/Brisbane",
"Kingston": "Australia/Hobart",
"Macquarie Island": "Antarctica/Macquarie",
"Mawson": "Antarctica/Mawson",
"Melbourne": "Australia/Melbourne",
"Newcastle": "Australia/Sydney",
"Perth": "Australia/Perth",
"Sydney": "Australia/Sydney",
"Townsville": "Australia/Brisbane",
}

if name, ok := m[stationName]; !ok {
return name, errors.New(fmt.Sprintf("No time zone configured for station %v", stationName))
} else {
return name, nil
}
}

func (s Station) String() string {
return fmt.Sprintf("%-17v %4.1f %v", s.Name, s.UVIndex, s.Time.Format("Mon 2 Jan 3:04 pm"))
}
import "github.com/msharris/uv/cmd"

func main() {
resp, err := http.Get("https://uvdata.arpansa.gov.au/xml/uvvalues.xml")
if err != nil {
log.Fatal("ARPANSA data file unavailable")
}
defer resp.Body.Close()

body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal("Unable to read ARPANSA data file")
}

var xmlStations XMLStations
err = xml.Unmarshal(body, &xmlStations)
if err != nil {
log.Fatal("Unexpected format of ARPANSA data file")
}

stations := xmlStations.Stations()
for _, s := range stations {
fmt.Println(s)
}
cmd.Execute()
}

0 comments on commit a02b3f2

Please sign in to comment.