refactor: build cobra commands with constructors
This commit is contained in:
+19
-18
@@ -14,32 +14,33 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var opts downloader.Options
|
func newDownloadCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
var downloadCmd = &cobra.Command{
|
|
||||||
Use: "download",
|
Use: "download",
|
||||||
Short: "Download tracks from Deezer",
|
Short: "Download tracks from Deezer",
|
||||||
Annotations: map[string]string{updateNoticeAnnotation: "true"},
|
Annotations: map[string]string{updateNoticeAnnotation: "true"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
opts := &downloader.Options{}
|
||||||
RootCmd.AddCommand(downloadCmd)
|
cmd.PersistentFlags().StringVarP(&opts.Quality, "quality", "q", "mp3_320", "download quality [mp3_128, mp3_320, flac]")
|
||||||
|
cmd.PersistentFlags().DurationVarP(&opts.Timeout, "timeout", "t", 2*time.Minute, "timeout for each download (e.g. 10s, 1m, 2m30s)")
|
||||||
|
cmd.PersistentFlags().BoolVar(&opts.BPM, "bpm", false, "fetch BPM/key and add to file tags")
|
||||||
|
cmd.PersistentFlags().BoolVar(&opts.Genre, "genre", false, "fetch genre and add to file tags")
|
||||||
|
cmd.PersistentFlags().BoolVar(&opts.Strict, "strict", false, "fail the download if the requested quality is unavailable")
|
||||||
|
|
||||||
downloadCmd.PersistentFlags().StringVarP(&opts.Quality, "quality", "q", "mp3_320", "download quality [mp3_128, mp3_320, flac]")
|
// Every subcommand shares opts: registering the artist-only --limit flag
|
||||||
downloadCmd.PersistentFlags().DurationVarP(&opts.Timeout, "timeout", "t", 2*time.Minute, "timeout for each download (e.g. 10s, 1m, 2m30s)")
|
// stores its default in the shared struct, which Validate requires for all kinds.
|
||||||
downloadCmd.PersistentFlags().BoolVar(&opts.BPM, "bpm", false, "fetch BPM/key and add to file tags")
|
cmd.AddCommand(
|
||||||
downloadCmd.PersistentFlags().BoolVar(&opts.Genre, "genre", false, "fetch genre and add to file tags")
|
newDownloadSubCmd(deezer.KindAlbum, opts),
|
||||||
downloadCmd.PersistentFlags().BoolVar(&opts.Strict, "strict", false, "fail the download if the requested quality is unavailable")
|
newDownloadSubCmd(deezer.KindPlaylist, opts),
|
||||||
|
newDownloadSubCmd(deezer.KindArtist, opts),
|
||||||
downloadCmd.AddCommand(
|
newDownloadSubCmd(deezer.KindTrack, opts),
|
||||||
newDownloadCmd(deezer.KindAlbum),
|
|
||||||
newDownloadCmd(deezer.KindPlaylist),
|
|
||||||
newDownloadCmd(deezer.KindArtist),
|
|
||||||
newDownloadCmd(deezer.KindTrack),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDownloadCmd(kind deezer.Kind) *cobra.Command {
|
func newDownloadSubCmd(kind deezer.Kind, opts *downloader.Options) *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: fmt.Sprintf("%s <%s_id>", kind, kind),
|
Use: fmt.Sprintf("%s <%s_id>", kind, kind),
|
||||||
Short: downloadShort(kind),
|
Short: downloadShort(kind),
|
||||||
@@ -61,7 +62,7 @@ func newDownloadCmd(kind deezer.Kind) *cobra.Command {
|
|||||||
}
|
}
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
err = downloader.New(cfg, st, kind).Run(cmd.Context(), opts, args[0])
|
err = downloader.New(cfg, st, kind).Run(cmd.Context(), *opts, args[0])
|
||||||
if errors.Is(err, context.Canceled) {
|
if errors.Is(err, context.Canceled) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-4
@@ -7,7 +7,8 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var loginCmd = &cobra.Command{
|
func newLoginCmd() *cobra.Command {
|
||||||
|
return &cobra.Command{
|
||||||
Use: "login",
|
Use: "login",
|
||||||
Short: "Log in to Deezer with your email and password",
|
Short: "Log in to Deezer with your email and password",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
@@ -31,7 +32,4 @@ var loginCmd = &cobra.Command{
|
|||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
RootCmd.AddCommand(loginCmd)
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-4
@@ -7,7 +7,8 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var logoutCmd = &cobra.Command{
|
func newLogoutCmd() *cobra.Command {
|
||||||
|
return &cobra.Command{
|
||||||
Use: "logout",
|
Use: "logout",
|
||||||
Short: "Remove stored Deezer credentials",
|
Short: "Remove stored Deezer credentials",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
@@ -21,7 +22,4 @@ var logoutCmd = &cobra.Command{
|
|||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
RootCmd.AddCommand(logoutCmd)
|
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-10
@@ -14,26 +14,40 @@ import (
|
|||||||
|
|
||||||
const updateNoticeAnnotation = "godeez:update-notice"
|
const updateNoticeAnnotation = "godeez:update-notice"
|
||||||
|
|
||||||
var RootCmd = &cobra.Command{
|
|
||||||
Use: "godeez",
|
|
||||||
Short: "GoDeez is a tool to download music from Deezer",
|
|
||||||
SilenceUsage: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
func Execute(ctx context.Context) error {
|
func Execute(ctx context.Context) error {
|
||||||
|
root := NewRootCmd()
|
||||||
|
|
||||||
var notice <-chan string
|
var notice <-chan string
|
||||||
if wantsUpdateNotice() {
|
if wantsUpdateNotice(root) {
|
||||||
notice = updater.StartCheck(ctx)
|
notice = updater.StartCheck(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := RootCmd.ExecuteContext(ctx)
|
err := root.ExecuteContext(ctx)
|
||||||
|
|
||||||
printUpdateNotice(notice)
|
printUpdateNotice(notice)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func wantsUpdateNotice() bool {
|
func NewRootCmd() *cobra.Command {
|
||||||
|
root := &cobra.Command{
|
||||||
|
Use: "godeez",
|
||||||
|
Short: "GoDeez is a tool to download music from Deezer",
|
||||||
|
SilenceUsage: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
root.AddCommand(
|
||||||
|
newDownloadCmd(),
|
||||||
|
newLoginCmd(),
|
||||||
|
newLogoutCmd(),
|
||||||
|
newUpdateCmd(),
|
||||||
|
newVersionCmd(),
|
||||||
|
)
|
||||||
|
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
|
||||||
|
func wantsUpdateNotice(root *cobra.Command) bool {
|
||||||
if !term.IsTerminal(int(os.Stderr.Fd())) {
|
if !term.IsTerminal(int(os.Stderr.Fd())) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -43,7 +57,7 @@ func wantsUpdateNotice() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
target, _, err := RootCmd.Find(args)
|
target, _, err := root.Find(args)
|
||||||
if err != nil || target == nil {
|
if err != nil || target == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-13
@@ -11,17 +11,19 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var updateOpts struct {
|
type updateOptions struct {
|
||||||
checkOnly bool
|
checkOnly bool
|
||||||
force bool
|
force bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var updateCmd = &cobra.Command{
|
func newUpdateCmd() *cobra.Command {
|
||||||
|
opts := &updateOptions{}
|
||||||
|
cmd := &cobra.Command{
|
||||||
Use: "update",
|
Use: "update",
|
||||||
Short: "Update GoDeez to the latest version",
|
Short: "Update GoDeez to the latest version",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
err := runUpdate(cmd.Context())
|
err := runUpdate(cmd.Context(), opts)
|
||||||
if errors.Is(err, context.Canceled) {
|
if errors.Is(err, context.Canceled) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -30,7 +32,13 @@ var updateCmd = &cobra.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func runUpdate(ctx context.Context) error {
|
cmd.Flags().BoolVar(&opts.checkOnly, "check", false, "only report whether an update is available")
|
||||||
|
cmd.Flags().BoolVar(&opts.force, "force", false, "reinstall even if already up to date")
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func runUpdate(ctx context.Context, opts *updateOptions) error {
|
||||||
if err := updater.CheckUpdatable(); err != nil {
|
if err := updater.CheckUpdatable(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -47,13 +55,13 @@ func runUpdate(ctx context.Context) error {
|
|||||||
latest := release.Version()
|
latest := release.Version()
|
||||||
fmt.Printf("Current: %s\nLatest: %s\n", current, latest)
|
fmt.Printf("Current: %s\nLatest: %s\n", current, latest)
|
||||||
|
|
||||||
if !updater.IsNewer(current, latest) && !updateOpts.force {
|
if !updater.IsNewer(current, latest) && !opts.force {
|
||||||
fmt.Println("Already up to date.")
|
fmt.Println("Already up to date.")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if updateOpts.checkOnly {
|
if opts.checkOnly {
|
||||||
fmt.Printf("Run `godeez update` to install %s.\n", latest)
|
fmt.Printf("Run `godeez update` to install %s.\n", latest)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -66,10 +74,3 @@ func runUpdate(ctx context.Context) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
RootCmd.AddCommand(updateCmd)
|
|
||||||
|
|
||||||
updateCmd.Flags().BoolVar(&updateOpts.checkOnly, "check", false, "only report whether an update is available")
|
|
||||||
updateCmd.Flags().BoolVar(&updateOpts.force, "force", false, "reinstall even if already up to date")
|
|
||||||
}
|
|
||||||
|
|||||||
+2
-4
@@ -8,7 +8,8 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var versionCmd = &cobra.Command{
|
func newVersionCmd() *cobra.Command {
|
||||||
|
return &cobra.Command{
|
||||||
Use: "version",
|
Use: "version",
|
||||||
Short: "Print the current version of GoDeez",
|
Short: "Print the current version of GoDeez",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
@@ -26,7 +27,4 @@ var versionCmd = &cobra.Command{
|
|||||||
fmt.Printf(" platform: %s/%s\n", runtime.GOOS, runtime.GOARCH)
|
fmt.Printf(" platform: %s/%s\n", runtime.GOOS, runtime.GOARCH)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
RootCmd.AddCommand(versionCmd)
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user