commit e281b487dc74e5bfbeaf8c45995d2462f524ad4a from: Witcher01 date: Sun Jun 6 13:29:24 2021 UTC initial commit commit - /dev/null commit + e281b487dc74e5bfbeaf8c45995d2462f524ad4a blob - /dev/null blob + 948e872bf0176fe3c7612306144ff7d8c5e58df0 (mode 644) --- /dev/null +++ README.md @@ -0,0 +1,16 @@ +# cli_incidence + +cli_incidence talks to the RKI (Robert-Koch-Institut) REST API and posts the incidence of the specified districts to STDOUT. + +# Requirements + +- The Go compiler + +# Compiling + +`go build main.go` + +# Running + +`./main -d "12062,hildburghausen"` + blob - /dev/null blob + e84132b76dc908f10577509cf293acc5b9ade142 (mode 644) --- /dev/null +++ main.go @@ -0,0 +1,121 @@ +package main + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "os" + "strings" + + "github.com/spf13/pflag" +) + +// will be set after parsing commandline arguments +var ApiString string +var DistrictApi string + +// direct response from the server +type DistrictResponseData struct { + Data map[string]DistrictResponse `json:"data"` + //Meta []MetaResponse `json:"meta"` +} + +// data field of the response +type DistrictResponse struct { + // Allgemeiner Gemeinde Schlüssel ("ID" of the district) + Ags string `json:"ags"` + Name string `json:"name"` + State string `json:"state"` + County string `json:"county"` + Population int `json:"population"` + Cases int `json:"cases"` + Deaths int `json:"deaths"` + CasesPerWeek int `json:"casesPerWeek"` + DeathsPerWeek int `json:"deathsPerWeek"` + Recovered int `json:"recovered"` + WeekIncidence float64 `json:"weekIncidence"` + CasesPer100k float64 `json:"casesPer100k"` +} + +// meta field of the response +type MetaResponse struct { + Source string `json:"source"` + Contact string `json:"contact"` + Info string `json:"info"` + LastUpdate string `json:"lastUpdate"` + LastCheckedforUpdate string `json:"lastCheckedforUpdate"` +} + +func main() { + var apiString = pflag.StringP("api", "a", "https://api.corona-zahlen.org/", "API Endpoint to use. Ensure trailing \"/\".") + var district_ids = pflag.StringSliceP("districts", "d", []string{}, "Name or AGS of the districts you want to have displayed.") + pflag.Parse() + + ApiString = *apiString + DistrictApi = ApiString + "districts/" + + if len(*district_ids) < 1 { + fmt.Println("Nothing to do, no districts given. Exiting.") + os.Exit(0) + } + + districts, err := getAllDistricts() + if err != nil { + fmt.Fprintf(os.Stderr, "unable to get districts: %v\n", err) + return + } + + districts.FilterDistricts(*district_ids) + districts.PrintIncidences() +} + +func (districts *DistrictResponseData) PrintIncidences() { + for _, v := range districts.Data { + v.PrintIncidence() + } +} + +// filters DistrictResponseData to only contain the districts specified +// districts can be specified via their AGS or name +func (districts *DistrictResponseData) FilterDistricts(district_ids []string) { +loop: + for k, v := range districts.Data { + for _, id := range district_ids { + if v.Ags == id || strings.Contains(strings.ToLower(v.Name), strings.ToLower(id)) { + continue loop + } + } + delete(districts.Data, k) + } +} + +func (district *DistrictResponse) PrintIncidence() { + fmt.Printf("%s: %.2f\n", district.Name, district.WeekIncidence) +} + +func getAllDistricts() (DistrictResponseData, error) { + var drd DistrictResponseData + // initialize a (hopefully) big enough map + // api contains about 410 districts + drd.Data = make(map[string]DistrictResponse, 410) + apiUrl := DistrictApi + + response, err := http.Get(apiUrl) + if err != nil { + return drd, err + } + defer response.Body.Close() + + responseData, err := ioutil.ReadAll(response.Body) + if err != nil { + return drd, err + } + + err = json.Unmarshal(responseData, &drd) + if err != nil { + return drd, err + } + + return drd, nil +}