From d38ac221b1e6c5d59880a9f031fea920a3ab5a78 Mon Sep 17 00:00:00 2001 From: renanbastos93 Date: Sun, 12 Apr 2020 04:20:26 -0300 Subject: [PATCH 1/2] Feat: Add filter by GeoIP Added a new filter based on your IP to get your country. --- .gitignore | 3 ++- main.go | 69 ++++++++++++++++++++++++++++++++++++++-------------- main_test.go | 8 +++--- 3 files changed, 57 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index 0334c58..6e20787 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,5 @@ bin cover alertcovid19 coverage.html -dist \ No newline at end of file +dist +*.zip \ No newline at end of file diff --git a/main.go b/main.go index fd44aaf..a1c1aa8 100644 --- a/main.go +++ b/main.go @@ -5,9 +5,9 @@ import ( "encoding/json" "flag" "fmt" + "io/ioutil" "log" "net/http" - "os" "time" "github.com/gen2brain/beeep" @@ -15,27 +15,34 @@ import ( // Exported ... const ( - IMG string = "https://static.poder360.com.br/2020/03/23312-868x644.png" - URL = "https://covid19-brazil-api.now.sh/api/report/v1/brazil" + myIP = "http://ip-api.com/json" + IMG = "https://static.poder360.com.br/2020/03/23312-868x644.png" + URL = "https://corona.lmao.ninja/countries/" + StateBrazil = "https://covid19-brazil-api.now.sh/api/report/v1/brazil/uf/" + TIMEOUT = time.Second * 2 ) +type geoIP struct { + CountryCode string `json:"countryCode"` + Region string `json:"region"` +} + // LastValues ... type LastValues struct { - Confirmed int `json:"confirmed"` + Cases int `json:"cases"` Deaths int `json:"deaths"` Recovered int `json:"recovered"` } func (l LastValues) String() string { - return fmt.Sprintf("Confirmed: %d, Deaths: %d, Recovered: %d", l.Confirmed, l.Deaths, l.Recovered) + message := "Cases: %d, Deaths: %d, Recovered: %d" + return fmt.Sprintf(message, l.Cases, l.Deaths, l.Recovered) } // fetch runs on its own goroutine func fetch(ctx context.Context, req *http.Request, ch chan LastValues) error { defer close(ch) - var r struct { - Data LastValues `json:"data"` - } + var r LastValues body, err := http.DefaultClient.Do(req) if err != nil { log.Printf("fetchCOVID19Data: %v", err) @@ -48,17 +55,22 @@ func fetch(ctx context.Context, req *http.Request, ch chan LastValues) error { return err } + bodyBytes, _ := ioutil.ReadAll(body.Body) + log.Println("WOOW: :: ", string(bodyBytes)) + select { - case ch <- LastValues{r.Data.Confirmed, r.Data.Deaths, r.Data.Recovered}: + case ch <- LastValues{r.Cases, r.Deaths, r.Recovered}: case <-ctx.Done(): } return nil } // fetchCOVID19Data ... -func fetchCOVID19Data(ctx context.Context) <-chan LastValues { +func fetchCOVID19Data(ctx context.Context, country string) <-chan LastValues { ch := make(chan LastValues) - req, err := http.NewRequestWithContext(ctx, "GET", URL, nil) + url := URL + country + log.Println("URL ::: ", url) + req, err := http.NewRequestWithContext(ctx, "GET", url, nil) if err != nil { panic("internal error - misuse of NewRequestWithContext") } @@ -66,15 +78,15 @@ func fetchCOVID19Data(ctx context.Context) <-chan LastValues { return ch } -func routine(sleep time.Duration) { +func routine(sleep time.Duration, country string) { cachedVal := LastValues{} - const timeout = time.Second * 2 for { - ctx, cancel := context.WithTimeout(context.Background(), timeout) + ctx, cancel := context.WithTimeout(context.Background(), TIMEOUT) select { - case newVal := <-fetchCOVID19Data(ctx): + case newVal := <-fetchCOVID19Data(ctx, country): + log.Println("newval :: ", newVal) if cachedVal != newVal { - err := beeep.Alert("COVID-19 Brazil", newVal.String(), IMG) + err := beeep.Alert("COVID-19 "+country, newVal.String(), IMG) if err != nil { log.Printf("rountine: %v", err) } @@ -89,11 +101,32 @@ func routine(sleep time.Duration) { } } +func getCountryByGeoIP() geoIP { + client := http.Client{Timeout: TIMEOUT} + resp, err := client.Post( + myIP, + "application/json; charset=utf8", + nil, + ) + if err != nil { + log.Fatal(err) + } + defer resp.Body.Close() + var ip geoIP + err = json.NewDecoder(resp.Body).Decode(&ip) + if err != nil { + log.Fatalf("Oops, we cannot get your location, please verify your network.") + } + log.Println("IP :: ", ip) + return ip +} + func main() { - log.SetPrefix(os.Args[0] + ": ") + // log.SetPrefix(os.Args[0] + ": ") log.SetFlags(0) var timer time.Duration flag.DurationVar(&timer, "t", time.Hour, "interval between each api request") flag.Parse() - routine(timer) + ip := getCountryByGeoIP() + routine(timer, ip.CountryCode) } diff --git a/main_test.go b/main_test.go index 4b35bcd..ed03fe2 100644 --- a/main_test.go +++ b/main_test.go @@ -18,11 +18,11 @@ func TestLastValues_String(t *testing.T) { { name: "Test format message to show in the notification", fields: LastValues{ - Confirmed: 100, + Cases: 100, Deaths: 7, Recovered: 1, }, - want: "Confirmed: 100, Deaths: 7, Recovered: 1", + want: "Cases: 100, Deaths: 7, Recovered: 1", }, } for _, v := range tests { @@ -42,8 +42,8 @@ func TestFetch(t *testing.T) { input io.Reader want bool }{ - {"ok json", strings.NewReader(`{"data": {"confirmed": 10, "deaths": 10, "recovered": 10}}`), true}, - {"bad json", strings.NewReader(`{"data": "confirmed": 10, "deaths": 10, "recovered": 10}}`), false}, + {"ok json", strings.NewReader(`{"data": {"cases": 10, "deaths": 10, "recovered": 10}}`), true}, + {"bad json", strings.NewReader(`{"data": "cases": 10, "deaths": 10, "recovered": 10}}`), false}, } for _, v := range tests { v := v From 015c26cf7e46d5f0b52a13abb94305bc9686c609 Mon Sep 17 00:00:00 2001 From: renanbastos93 Date: Sun, 12 Apr 2020 20:55:16 -0300 Subject: [PATCH 2/2] chore: removed logs unnecessary --- main.go | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/main.go b/main.go index a1c1aa8..45b8437 100644 --- a/main.go +++ b/main.go @@ -5,7 +5,7 @@ import ( "encoding/json" "flag" "fmt" - "io/ioutil" + "os" "log" "net/http" "time" @@ -54,10 +54,6 @@ func fetch(ctx context.Context, req *http.Request, ch chan LastValues) error { log.Printf("fetchCOVID19Data: %v", err) return err } - - bodyBytes, _ := ioutil.ReadAll(body.Body) - log.Println("WOOW: :: ", string(bodyBytes)) - select { case ch <- LastValues{r.Cases, r.Deaths, r.Recovered}: case <-ctx.Done(): @@ -69,7 +65,6 @@ func fetch(ctx context.Context, req *http.Request, ch chan LastValues) error { func fetchCOVID19Data(ctx context.Context, country string) <-chan LastValues { ch := make(chan LastValues) url := URL + country - log.Println("URL ::: ", url) req, err := http.NewRequestWithContext(ctx, "GET", url, nil) if err != nil { panic("internal error - misuse of NewRequestWithContext") @@ -84,7 +79,6 @@ func routine(sleep time.Duration, country string) { ctx, cancel := context.WithTimeout(context.Background(), TIMEOUT) select { case newVal := <-fetchCOVID19Data(ctx, country): - log.Println("newval :: ", newVal) if cachedVal != newVal { err := beeep.Alert("COVID-19 "+country, newVal.String(), IMG) if err != nil { @@ -96,7 +90,6 @@ func routine(sleep time.Duration, country string) { log.Printf("rountine: %v", ctx.Err()) } cancel() - log.Printf("sleeping for %s", sleep) time.Sleep(sleep) } } @@ -117,12 +110,11 @@ func getCountryByGeoIP() geoIP { if err != nil { log.Fatalf("Oops, we cannot get your location, please verify your network.") } - log.Println("IP :: ", ip) return ip } func main() { - // log.SetPrefix(os.Args[0] + ": ") + log.SetPrefix(os.Args[0] + ": ") log.SetFlags(0) var timer time.Duration flag.DurationVar(&timer, "t", time.Hour, "interval between each api request")