package main import ( "context" "fmt" "os" "strings" "streamrip-go/internal/config" "golang.org/x/term" ) // Commands that inspect local state: config and database. func cmdConfig(_ context.Context, cfg *config.Config, _ globalOptions, args []string) int { var err error if len(args) < 1 { printCommandHelp(os.Stdout, "config") return 2 } switch args[0] { case "open": vim := false for _, arg := range args[1:] { switch arg { case "-v", "--vim": vim = true default: fmt.Fprintf(os.Stderr, "option error: unknown option %q\n", arg) return 2 } } fmt.Printf("opening file at %s\n", cfg.Path) if err = openConfigInEditor(cfg.Path, vim); err != nil { fmt.Fprintf(os.Stderr, "open config error: %v\n", err) return 1 } case "reset": yes := false for _, arg := range args[1:] { switch arg { case "-y", "--yes": yes = true default: fmt.Fprintf(os.Stderr, "option error: unknown option %q\n", arg) return 2 } } if !yes { if !term.IsTerminal(int(os.Stdin.Fd())) { fmt.Fprintln(os.Stderr, "reset requires --yes in non-interactive mode") return 2 } ok, askErr := promptYesNo(fmt.Sprintf("Are you sure you want to reset the config file at %s? [y/N]: ", cfg.Path)) if askErr != nil { fmt.Fprintf(os.Stderr, "prompt error: %v\n", askErr) return 1 } if !ok { fmt.Println("reset aborted") return 0 } } def := config.DefaultConfigData() // Separate copies: assigning the same value to both halves made // File.Qobuz.Secrets and Session.Qobuz.Secrets share one backing // array. cfg.File = config.CloneConfigData(def) cfg.Session = config.CloneConfigData(def) if err = cfg.SaveFile(); err != nil { fmt.Fprintf(os.Stderr, "reset config error: %v\n", err) return 1 } fmt.Printf("reset the config file at %s\n", cfg.Path) case "path": if len(args) > 1 { fmt.Fprintf(os.Stderr, "option error: unexpected argument %q\n", args[1]) return 2 } fmt.Printf("config path: '%s'\n", cfg.Path) default: fmt.Fprintf(os.Stderr, "unknown config command: %s\n", args[0]) return 2 } return 0 } func cmdDatabase(_ context.Context, cfg *config.Config, _ globalOptions, args []string) int { if len(args) < 2 || args[0] != "browse" { printCommandHelp(os.Stdout, "database") return 2 } table := strings.ToLower(strings.TrimSpace(args[1])) switch table { case "downloads": rows, listErr := listDownloadsRows(cfg.Session.Database.DownloadsPath) if listErr != nil { fmt.Fprintf(os.Stderr, "database browse error: %v\n", listErr) return 1 } fmt.Println("downloads database") fmt.Println("row id") for i, id := range rows { fmt.Printf("%02d %s\n", i, id) } case "failed": rows, listErr := listFailedRows(cfg.Session.Database.FailedDownloadsPath) if listErr != nil && isNoSuchTableErr(listErr) && cfg.Session.Database.FailedDownloadsPath != cfg.Session.Database.DownloadsPath { rows, listErr = listFailedRows(cfg.Session.Database.DownloadsPath) } if listErr != nil { fmt.Fprintf(os.Stderr, "database browse error: %v\n", listErr) return 1 } fmt.Println("failed downloads database") fmt.Println("row source media_type id") for i, row := range rows { fmt.Printf("%02d %s %s %s\n", i, row.Source, row.MediaType, row.ID) } default: fmt.Fprintf(os.Stderr, "invalid database %q. choose downloads or failed\n", table) return 2 } return 0 }