diff --git a/cmd/daily.go b/cmd/daily.go index 7456771..6267c1b 100644 --- a/cmd/daily.go +++ b/cmd/daily.go @@ -1,9 +1,10 @@ package cmd import ( + "bytes" + "encoding/json" "fmt" "log" - "os" "github.com/devOpifex/cranlogs/internal/color" "github.com/devOpifex/cranlogs/internal/data" @@ -16,22 +17,29 @@ func daily(_ *cobra.Command, args []string) { if len(args) == 0 { log.Fatal("no package specified") } - // TODO: this still has some issues in how its handled - // as if a specific package fails, it will cause the entire process to - // exit then. A different pattern could be to aggregate errors for - // failed packages, then print out successful ones, then at the end - // the error(s) for the failed ones - for _, pkg := range args { - daily, err := data.GetDaily(dailyPeriod, pkg) + p, err := data.NewPeriod(dailyPeriod) + if err != nil { + log.Fatal(err) + } + dailyDls, err := data.GetDaily(p, args) + if err != nil { + log.Fatalf("error getting daily downloads: %s", err) + } + + if printJson { + var out bytes.Buffer + dailyBytes, err := json.Marshal(dailyDls) if err != nil { - color.PrintError(err.Error()) - // given an error should not exit with a 0 exit code - os.Exit(-1) + log.Fatalf("error marshalling daily downloads: %s", err) } - - fmt.Printf("Package: %v %v %v\n", color.Yellow, daily.Package, color.Reset) - for _, v := range daily.Downloads { - fmt.Printf("%v%v%v: %v\n", color.Cyan, v.Day, color.Reset, v.Downloads) + json.Indent(&out, dailyBytes, "", " ") + fmt.Println(out.String()) + } else { + for _, d := range dailyDls { + fmt.Printf("Package: %v %v %v\n", color.Yellow, d.Package, color.Reset) + for _, v := range d.Downloads { + fmt.Printf("%v%v%v: %v\n", color.Cyan, v.Day, color.Reset, v.Downloads) + } } } } diff --git a/cmd/root.go b/cmd/root.go index 90b2acd..44f44f1 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -7,6 +7,8 @@ import ( "github.com/spf13/cobra" ) +var printJson bool + var rootCmd = &cobra.Command{ Use: "Cranlogs", Short: "Access the cranlogs API", @@ -25,4 +27,5 @@ func Execute() { func init() { rootCmd.AddCommand(newDailyCmd()) + rootCmd.PersistentFlags().BoolVar(&printJson, "json", false, "output in json format") } diff --git a/internal/data/daily.go b/internal/data/daily.go index f010a92..326524d 100644 --- a/internal/data/daily.go +++ b/internal/data/daily.go @@ -4,6 +4,7 @@ import ( "encoding/json" "io/ioutil" "net/http" + "strings" ) type Daily struct { @@ -18,31 +19,36 @@ type DailyDownload struct { Downloads int `json:"downloads"` } -func GetDaily(period, pkg string) (Daily, error) { +func GetDaily(period Period, pkgs []string) ([]Daily, error) { // weirdly the API returns an array of length 1 var daily []Daily - - path := URL + "downloads/daily/" + period + "/" + pkg - + path := URL + "downloads/daily/" + string(period) + "/" + strings.Join(pkgs, ",") resp, err := http.Get(path) if err != nil { - return Daily{}, err + return daily, err + } + // This is currently kind of meaningless until + // https://github.com/r-hub/cranlogs.app/issues/41 is resolved but at least + // its there + if resp.StatusCode != 200 { + return daily, err } - defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { - return Daily{}, err + return daily, err } err = json.Unmarshal(body, &daily) - + // if this errors given the current 200 status code returning an error response + // such as { "error": "Invalid query", "info": "https://github.com/metacran/cranlogs.app" } + // its still not the best error code if err != nil { - return Daily{}, err + return daily, err } - return daily[0], nil + return daily, nil }