diff --git a/app/widget_maker.go b/app/widget_maker.go index a6b1f471..ad0d343f 100644 --- a/app/widget_maker.go +++ b/app/widget_maker.go @@ -50,6 +50,7 @@ import ( "github.com/wtfutil/wtf/modules/twitter" "github.com/wtfutil/wtf/modules/unknown" "github.com/wtfutil/wtf/modules/victorops" + "github.com/wtfutil/wtf/modules/weatherservices/arpansagovau" "github.com/wtfutil/wtf/modules/weatherservices/prettyweather" "github.com/wtfutil/wtf/modules/weatherservices/weather" "github.com/wtfutil/wtf/modules/zendesk" @@ -73,6 +74,9 @@ func MakeWidget( // Always in alphabetical order switch moduleConfig.UString("type", moduleName) { + case "arpansagovau": + settings := arpansagovau.NewSettingsFromYAML(moduleName, moduleConfig, config) + widget = arpansagovau.NewWidget(app, settings) case "bamboohr": settings := bamboohr.NewSettingsFromYAML(moduleName, moduleConfig, config) widget = bamboohr.NewWidget(app, settings) diff --git a/modules/weatherservices/arpansagovau/client.go b/modules/weatherservices/arpansagovau/client.go new file mode 100644 index 00000000..6eeba504 --- /dev/null +++ b/modules/weatherservices/arpansagovau/client.go @@ -0,0 +1,80 @@ +package arpansagovau + +import ( + "encoding/xml" + "fmt" + "io" + "net/http" +) + +type Stations struct { + XMLName xml.Name `xml:"stations"` + Text string `xml:",chardata"` + Location []struct { + Text string `xml:",chardata"` + ID string `xml:"id,attr"` + Name string `xml:"name"` // adl, ali, bri, can, cas, ... + Index float32 `xml:"index"` // 0.0, 0.0, 0.0, 0.0, 0.0, ... + Time string `xml:"time"` // 7:24 PM, 7:24 PM, 7:54 PM... + Date string `xml:"date"` // 29/08/2019, 29/08/2019, 2... + Fulldate string `xml:"fulldate"` // Thursday, 29 August 2019,... + Utcdatetime string `xml:"utcdatetime"` // 2019/08/29 09:54, 2019/08... + Status string `xml:"status"` // ok, ok, ok, ok, ok, ok, o... + } `xml:"location"` +} + + +type location struct { + name string + index float32 + time string + date string + status string +} + +func GetLocationData(cityname string) (*location, error) { + var locdata location; + resp, err := apiRequest() + if err != nil { + return nil, err + } + + stations, err := parseXML(resp.Body); + if(err != nil) { + return nil, err + } + + for _, city := range stations.Location { + if(city.ID == cityname) { + locdata = location { name: city.ID, index: city.Index, time: city.Time, date: city.Date, status: city.Status } + break; + } + } + return &locdata, err +} + +/* -------------------- Unexported Functions -------------------- */ + +func apiRequest() (*http.Response, error) { + req, err := http.NewRequest("GET", "https://uvdata.arpansa.gov.au/xml/uvvalues.xml", nil) + + httpClient := &http.Client{} + resp, err := httpClient.Do(req) + if err != nil { + return nil, err + } + + if resp.StatusCode != 200 { + return nil, fmt.Errorf(resp.Status) + } + + return resp, nil +} +func parseXML(text io.Reader) (Stations, error) { + dec := xml.NewDecoder(text) + dec.Strict = false + + var v Stations; + err := dec.Decode(&v) + return v, err; +} diff --git a/modules/weatherservices/arpansagovau/settings.go b/modules/weatherservices/arpansagovau/settings.go new file mode 100644 index 00000000..c8bd9dc4 --- /dev/null +++ b/modules/weatherservices/arpansagovau/settings.go @@ -0,0 +1,22 @@ +package arpansagovau + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const defaultTitle = "ARPANSA UV Data" + +type Settings struct { + common *cfg.Common + city string; +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config, globalConfig *config.Config) *Settings { + settings := Settings{ + common: cfg.NewCommonSettingsFromModule(name, defaultTitle, ymlConfig, globalConfig), + city: ymlConfig.UString("locationid"), + } + + return &settings +} diff --git a/modules/weatherservices/arpansagovau/widget.go b/modules/weatherservices/arpansagovau/widget.go new file mode 100644 index 00000000..1a8167d9 --- /dev/null +++ b/modules/weatherservices/arpansagovau/widget.go @@ -0,0 +1,95 @@ +package arpansagovau + +import ( + "fmt" + "github.com/rivo/tview" + "github.com/wtfutil/wtf/view" +) + +type Widget struct { + view.TextWidget + location *location + lastError error + settings *Settings +} + +func NewWidget(app *tview.Application, settings *Settings) *Widget { + locationData, err := GetLocationData(settings.city) + widget := Widget { + TextWidget: view.NewTextWidget(app, settings.common, false), + location: locationData, + lastError: err, + settings: settings, + } + + widget.View.SetWrap(true) + + return &widget +} + +func (widget *Widget) content() (string, string, bool) { + + locationData, err := GetLocationData(widget.settings.city) + widget.location = locationData + widget.lastError = err + + if widget.lastError != nil { + return widget.CommonSettings().Title, fmt.Sprintf("Err: %s", widget.lastError.Error()), true + } + + return widget.CommonSettings().Title, formatLocationData(widget.location), true +} + +func (widget *Widget) Refresh() { + + widget.Redraw(widget.content) +} + +func formatLocationData(location *location) string { + var level string + var color string + var content string + + if(location.name == "") { + return "[red]No data?" + } + + if(location.status != "ok") { + content = "[red]Data unavailable for " + content += location.name + return content + } + + switch { + case location.index < 2.5: + color = "[green]" + level = " (LOW)" + case location.index >= 2.5 && location.index < 5.5: + color = "[yellow]" + level = " (MODERATE)" + case location.index >= 5.5 && location.index < 7.5: + color = "[orange]" + level = " (HIGH)" + case location.index >= 7.5 && location.index < 10.5: + color = "[red]" + level = " (VERY HIGH)" + case location.index >= 10.5: + color = "[fuchsia]" + level = " (EXTREME)" + } + + content = "Location: " + content += location.name + content += "\nUV index: " + content += color + content += fmt.Sprintf("%.2f", location.index) + content += level + content += "[white]\nLocal time: " + content += location.time + content += " " + content += location.date + content += "\nDetector status: " + content += location.status + + return content +}