package main import ( "context" "errors" "fmt" "log/slog" "os" "time" "golang.org/x/time/rate" ) func main() { slog.SetDefault(slog.New(slog.NewTextHandler(os.Stderr, nil))) if err := run(os.Args, os.Getenv); err != nil { fmt.Fprintf(os.Stderr, "Error: %v\n", err) os.Exit(1) } } // envLookup retrieves an environment variable. type envLookup func(string) string // run dispatches to the appropriate subcommand. // It is extracted from main to allow testing of the dispatch and validation logic. func run(args []string, lookupEnv envLookup) error { if len(args) < 2 { return errors.New("Usage: popback [args...]") } switch args[1] { case "viewed": apiKey := lookupEnv("TMDB_API_KEY") if apiKey == "" { return errors.New("TMDB_API_KEY required") } output := "watchlist.csv" if len(args) > 2 { output = args[2] } tmdb := newTMDBClient(apiKey) store := newCSVStorer() return runViewed(context.Background(), tmdb, store, realTUIRunner{}, output) case "backfill": apiKey := lookupEnv("TMDB_API_KEY") if apiKey == "" { return errors.New("TMDB_API_KEY required") } authToken := lookupEnv("POPFEED_AUTH_TOKEN") if authToken == "" { return errors.New("POPFEED_AUTH_TOKEN required") } csvPath := "watchlist.csv" if len(args) > 2 { csvPath = args[2] } tmdb := newTMDBClient(apiKey) store := newCSVStorer() pf := newPopfeedClient(authToken) tmdb.http = WithRateLimit(tmdb.http, rate.NewLimiter(rate.Every(250*time.Millisecond), 1)) pf.http = WithRateLimit(pf.http, rate.NewLimiter(rate.Every(50*time.Millisecond), 1)) return runBackfill(store, tmdb, pf, csvPath) default: return fmt.Errorf("Unknown command: %s\nUsage: popback [args...]", args[1]) } }