package main import ( "context" "fmt" "os" "strings" "streamrip-go/internal/app" "streamrip-go/internal/config" ) // Commands that queue media and rip it: url, file and id. func cmdURL(ctx context.Context, cfg *config.Config, gopts globalOptions, args []string) int { if len(args) < 1 { printCommandHelp(os.Stdout, "url") return 2 } mainApp, err := app.New(cfg) if err != nil { fmt.Fprintf(os.Stderr, "app init error: %v\n", err) return 1 } defer func() { _ = mainApp.Close() }() rawArgs := make([]string, 0, len(args)) ignoreDB := false for _, arg := range args { if arg == "--force" || arg == "--ignore-db" { ignoreDB = true continue } rawArgs = append(rawArgs, arg) } mainApp.IgnoreDB = ignoreDB || gopts.noDB added := 0 for _, raw := range rawArgs { if addURLToQueue(ctx, mainApp, raw) { added++ } } if added == 0 { fmt.Println("nothing to rip") return 0 } if err = mainApp.Resolve(ctx); err != nil { fmt.Fprintf(os.Stderr, "resolve error: %s\n", errorWithActionableHint(err, gopts)) return 1 } if err = mainApp.Rip(ctx); err != nil { fmt.Fprintf(os.Stderr, "rip error: %s\n", errorWithActionableHint(err, gopts)) return 1 } fmt.Printf("url rip complete (%d item(s))\n", added) return 0 } func cmdFile(ctx context.Context, cfg *config.Config, gopts globalOptions, args []string) int { if len(args) < 1 { printCommandHelp(os.Stdout, "file") return 2 } ignoreDB := false for _, arg := range args[1:] { switch arg { case "--force", "--ignore-db": ignoreDB = true default: fmt.Fprintf(os.Stderr, "option error: unknown option %q\n", arg) return 2 } } content, err := os.ReadFile(args[0]) if err != nil { fmt.Fprintf(os.Stderr, "read file error: %v\n", err) return 1 } idItems, urls, repeated, jsonInput, err := parseFileInput(content) if err != nil { fmt.Fprintf(os.Stderr, "file parse error: %v\n", err) return 2 } mainApp, err := app.New(cfg) if err != nil { fmt.Fprintf(os.Stderr, "app init error: %v\n", err) return 1 } defer func() { _ = mainApp.Close() }() mainApp.IgnoreDB = ignoreDB || gopts.noDB added := 0 if jsonInput { fmt.Printf("detected json file. loading %d item(s)\n", len(idItems)) for _, item := range idItems { if err = mainApp.AddByID(ctx, item.Source, item.MediaType, item.ID); err != nil { fmt.Printf("add failed: source=%s type=%s id=%s err=%v\n", item.Source, item.MediaType, item.ID, err) continue } added++ } } else { if repeated > 0 { fmt.Printf("found %d repeated url(s)\n", repeated) } fmt.Printf("detected list of urls. loading %d item(s)\n", len(urls)) for _, raw := range urls { if addURLToQueue(ctx, mainApp, raw) { added++ } } } if added == 0 { fmt.Println("nothing to rip") return 0 } if err = mainApp.Resolve(ctx); err != nil { fmt.Fprintf(os.Stderr, "resolve error: %s\n", errorWithActionableHint(err, gopts)) return 1 } if err = mainApp.Rip(ctx); err != nil { fmt.Fprintf(os.Stderr, "rip error: %s\n", errorWithActionableHint(err, gopts)) return 1 } fmt.Printf("file rip complete (%d item(s))\n", added) return 0 } func cmdID(ctx context.Context, cfg *config.Config, gopts globalOptions, args []string) int { if len(args) < 3 { printCommandHelp(os.Stdout, "id") return 2 } source := strings.ToLower(strings.TrimSpace(args[0])) mediaType := strings.ToLower(strings.TrimSpace(args[1])) itemID := strings.TrimSpace(args[2]) opts, err := parseSmokeOptions(args[3:], 0, 4) if err != nil { fmt.Fprintf(os.Stderr, "option error: %v\n", err) return 2 } if opts.qualitySet { switch source { case "qobuz": if opts.quality < 1 { fmt.Fprintf(os.Stderr, "quality error: qobuz quality must be 1-4\n") return 2 } cfg.Session.Qobuz.Quality = opts.quality case "tidal": cfg.Session.Tidal.Quality = opts.quality case "yandex": cfg.Session.Yandex.Quality = opts.quality case "beatport": if opts.quality < 1 { fmt.Fprintf(os.Stderr, "quality error: beatport quality must be 1-4\n") return 2 } cfg.Session.Beatport.Quality = opts.quality } } mainApp, err := app.New(cfg) if err != nil { fmt.Fprintf(os.Stderr, "app init error: %v\n", err) return 1 } defer func() { _ = mainApp.Close() }() mainApp.IgnoreDB = opts.ignoreDB || gopts.noDB if err = mainApp.AddByID(ctx, source, mediaType, itemID); err != nil { fmt.Fprintf(os.Stderr, "add error: %v\n", err) return 1 } if err = mainApp.Resolve(ctx); err != nil { fmt.Fprintf(os.Stderr, "resolve error: %s\n", errorWithActionableHint(err, gopts)) return 1 } if err = mainApp.Rip(ctx); err != nil { fmt.Fprintf(os.Stderr, "rip error: %s\n", errorWithActionableHint(err, gopts)) return 1 } fmt.Printf("id rip complete: source=%s type=%s id=%s\n", source, mediaType, itemID) return 0 }