mirror of
https://github.com/taigrr/wtf
synced 2025-01-18 04:03:14 -08:00
[modules] Add new covid tracker module (#1037)
* Add draft of covid module * Work on pointers * Add country stats * Remove recovered, stays at 0 * Handle response code * One struct for both * List of countries * Add test * Add test for countries * Fix typos * Format numbers based on language/locale
This commit is contained in:
parent
d7da659b8b
commit
2f2df04478
@ -13,6 +13,7 @@ import (
|
||||
"github.com/wtfutil/wtf/modules/circleci"
|
||||
"github.com/wtfutil/wtf/modules/clocks"
|
||||
"github.com/wtfutil/wtf/modules/cmdrunner"
|
||||
"github.com/wtfutil/wtf/modules/covid"
|
||||
"github.com/wtfutil/wtf/modules/cryptoexchanges/bittrex"
|
||||
"github.com/wtfutil/wtf/modules/cryptoexchanges/blockfolio"
|
||||
"github.com/wtfutil/wtf/modules/cryptoexchanges/cryptolive"
|
||||
@ -137,6 +138,9 @@ func MakeWidget(
|
||||
case "clocks":
|
||||
settings := clocks.NewSettingsFromYAML(moduleName, moduleConfig, config)
|
||||
widget = clocks.NewWidget(tviewApp, settings)
|
||||
case "covid":
|
||||
settings := covid.NewSettingsFromYAML(moduleName, moduleConfig, config)
|
||||
widget = covid.NewWidget(tviewApp, settings)
|
||||
case "cmdrunner":
|
||||
settings := cmdrunner.NewSettingsFromYAML(moduleName, moduleConfig, config)
|
||||
widget = cmdrunner.NewWidget(tviewApp, settings)
|
||||
|
14
modules/covid/cases.go
Normal file
14
modules/covid/cases.go
Normal file
@ -0,0 +1,14 @@
|
||||
package covid
|
||||
|
||||
// Cases holds the latest cases
|
||||
type Cases struct {
|
||||
Latest Latest `json:"latest"`
|
||||
}
|
||||
|
||||
// Latest holds the number of global confirmed cases and deaths due to Covid
|
||||
type Latest struct {
|
||||
Confirmed int `json:"confirmed"`
|
||||
Deaths int `json:"deaths"`
|
||||
// Not currently used but holds information about the country
|
||||
Locations []interface{} `json:"locations,omitempty"`
|
||||
}
|
58
modules/covid/client.go
Normal file
58
modules/covid/client.go
Normal file
@ -0,0 +1,58 @@
|
||||
package covid
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/wtfutil/wtf/utils"
|
||||
)
|
||||
|
||||
const covidTrackerAPIURL = "https://coronavirus-tracker-api.herokuapp.com/v2/"
|
||||
|
||||
// LatestCases queries the /latest endpoint, does not take any query parameters
|
||||
func LatestCases() (*Cases, error) {
|
||||
latestURL := covidTrackerAPIURL + "latest"
|
||||
resp, err := http.Get(latestURL)
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf(resp.Status)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
var latestGlobalCases Cases
|
||||
err = utils.ParseJSON(&latestGlobalCases, resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &latestGlobalCases, nil
|
||||
}
|
||||
|
||||
// LatestCountryCases queries the /locations endpoint, takes a query parameter: the country code
|
||||
func (widget *Widget) LatestCountryCases(countries []interface{}) ([]*Cases, error) {
|
||||
countriesCovidData := []*Cases{}
|
||||
for _, name := range countries {
|
||||
countryURL := covidTrackerAPIURL + "locations?source=jhu&country_code=" + name.(string)
|
||||
resp, err := http.Get(countryURL)
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf(resp.Status)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
var latestCountryCases Cases
|
||||
err = utils.ParseJSON(&latestCountryCases, resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// add stats for each country to the slice
|
||||
countriesCovidData = append(countriesCovidData, &latestCountryCases)
|
||||
|
||||
}
|
||||
|
||||
return countriesCovidData, nil
|
||||
}
|
31
modules/covid/client_test.go
Normal file
31
modules/covid/client_test.go
Normal file
@ -0,0 +1,31 @@
|
||||
package covid
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLatestCases(t *testing.T) {
|
||||
latestCasesToAssert, err := LatestCases()
|
||||
if err != nil {
|
||||
t.Error("LatestCases() returned an error")
|
||||
}
|
||||
if latestCasesToAssert.Latest.Confirmed == 0 {
|
||||
t.Error("LatestCases() should return a non 0 integer")
|
||||
}
|
||||
}
|
||||
|
||||
func (widget *Widget) TestCountryCases(t *testing.T) {
|
||||
countryList := []string{"US", "FR"}
|
||||
c := make([]interface{}, len(countryList))
|
||||
for i, v := range countryList {
|
||||
c[i] = v
|
||||
}
|
||||
latestCountryCasesToAssert, err := widget.LatestCountryCases(c)
|
||||
if err != nil {
|
||||
t.Error("LatestCountryCases() returned an error")
|
||||
}
|
||||
if len(latestCountryCasesToAssert) == 0 {
|
||||
t.Error("LatestCountryCases() should not be empty")
|
||||
}
|
||||
|
||||
}
|
31
modules/covid/settings.go
Normal file
31
modules/covid/settings.go
Normal file
@ -0,0 +1,31 @@
|
||||
package covid
|
||||
|
||||
import (
|
||||
"github.com/olebedev/config"
|
||||
"github.com/wtfutil/wtf/cfg"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultFocusable = false
|
||||
defaultTitle = "Covid tracker"
|
||||
)
|
||||
|
||||
// Settings is the struct for this module's settings
|
||||
type Settings struct {
|
||||
*cfg.Common
|
||||
|
||||
countries []interface{} `help:"Countries (codes) from which to retrieve stats."`
|
||||
}
|
||||
|
||||
// NewSettingsFromYAML returns the settings from the config yaml file
|
||||
func NewSettingsFromYAML(name string, ymlConfig *config.Config, globalConfig *config.Config) *Settings {
|
||||
|
||||
settings := Settings{
|
||||
Common: cfg.NewCommonSettingsFromModule(name, defaultTitle, defaultFocusable, ymlConfig, globalConfig),
|
||||
|
||||
// List of countries to retrieve stats from
|
||||
countries: ymlConfig.UList("countries"),
|
||||
}
|
||||
|
||||
return &settings
|
||||
}
|
87
modules/covid/widget.go
Normal file
87
modules/covid/widget.go
Normal file
@ -0,0 +1,87 @@
|
||||
package covid
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/rivo/tview"
|
||||
"github.com/wtfutil/wtf/view"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/message"
|
||||
)
|
||||
|
||||
// Widget is the struct that defines this module widget
|
||||
type Widget struct {
|
||||
view.TextWidget
|
||||
|
||||
settings *Settings
|
||||
err error
|
||||
}
|
||||
|
||||
// NewWidget creates a new widget for this module
|
||||
func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
widget := &Widget{
|
||||
TextWidget: view.NewTextWidget(app, nil, settings.Common),
|
||||
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
widget.View.SetScrollable(true)
|
||||
|
||||
return widget
|
||||
}
|
||||
|
||||
// Refresh checks if this module widget is disabled
|
||||
func (widget *Widget) Refresh() {
|
||||
if widget.Disabled() {
|
||||
return
|
||||
}
|
||||
|
||||
widget.Redraw(widget.content)
|
||||
}
|
||||
|
||||
// Render renders this module widget
|
||||
func (widget *Widget) Render() {
|
||||
widget.Redraw(widget.content)
|
||||
}
|
||||
|
||||
// Display stats based on the user's locale
|
||||
func (widget *Widget) displayStats(cases int) string {
|
||||
prntr := message.NewPrinter(language.English)
|
||||
str := fmt.Sprintf("%s", prntr.Sprintf("%d", cases))
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
func (widget *Widget) content() (string, string, bool) {
|
||||
title := defaultTitle
|
||||
if widget.CommonSettings().Title != "" {
|
||||
title = widget.CommonSettings().Title
|
||||
}
|
||||
|
||||
cases, err := LatestCases()
|
||||
var covidStats string
|
||||
if err != nil {
|
||||
widget.err = err
|
||||
} else {
|
||||
// Display global stats
|
||||
covidStats = fmt.Sprintf("[%s]Global[white]\n", widget.settings.Colors.Subheading)
|
||||
covidStats += fmt.Sprintf("%s: %s\n", "Confirmed", widget.displayStats(cases.Latest.Confirmed))
|
||||
covidStats += fmt.Sprintf("%s: %s\n", "Deaths", widget.displayStats(cases.Latest.Deaths))
|
||||
}
|
||||
// Retrieve country stats if country codes are set in the config
|
||||
if len(widget.settings.countries) > 0 {
|
||||
countryCases, err := widget.LatestCountryCases(widget.settings.countries)
|
||||
if err != nil {
|
||||
widget.err = err
|
||||
} else {
|
||||
for i, name := range countryCases {
|
||||
covidStats += fmt.Sprintf("[%s]Country[white]: %s\n", widget.settings.Colors.Subheading, widget.settings.countries[i])
|
||||
covidStats += fmt.Sprintf("%s: %s\n", "Confirmed", widget.displayStats(name.Latest.Confirmed))
|
||||
covidStats += fmt.Sprintf("%s: %s\n", "Deaths", widget.displayStats(name.Latest.Deaths))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return title, covidStats, true
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user