main
Raw Download raw file
 1package cli
 2
 3import (
 4	"context"
 5	"fmt"
 6
 7	"github.com/crash/upvs/internal/config"
 8	"github.com/crash/upvs/internal/output"
 9	"github.com/crash/upvs/internal/pipeline"
10	"github.com/crash/upvs/internal/protect"
11	"github.com/spf13/cobra"
12)
13
14var fetchCmd = &cobra.Command{
15	Use:   "fetch",
16	Short: "Download video clips",
17	Long:  "Download clips listed in clip_index.json with concurrent workers and retry support.",
18	RunE:  runFetch,
19}
20
21func init() {
22	fetchCmd.Flags().StringVar(&dateStr, "date", "", "Target date YYYY-MM-DD (required)")
23	fetchCmd.Flags().IntVar(&cfg.Workers, "workers", config.DefaultWorkers, "Number of concurrent download workers")
24	fetchCmd.Flags().IntVar(&cfg.Retries, "retries", config.DefaultRetries, "Number of retry attempts per clip")
25	fetchCmd.MarkFlagRequired("date")
26}
27
28func runFetch(cmd *cobra.Command, args []string) error {
29	// Parse date
30	date, err := config.ParseDate(dateStr)
31	if err != nil {
32		return err
33	}
34	cfg.Date = date
35
36	// Validate required fields
37	if cfg.Host == "" {
38		return config.ErrMissingHost
39	}
40	if cfg.Username == "" || cfg.Password == "" {
41		return config.ErrMissingCredentials
42	}
43	if cfg.Camera == "" {
44		return config.ErrMissingCamera
45	}
46	if cfg.OutDir == "" {
47		return config.ErrMissingOutDir
48	}
49
50	// Create layout
51	layout := output.NewLayout(cfg.OutDir, cfg.Camera, cfg.DateString())
52
53	// Create client
54	var opts []protect.ClientOption
55	if cfg.TLSInsecure {
56		opts = append(opts, protect.WithTLSInsecure())
57	}
58	if cfg.DirectAPI {
59		opts = append(opts, protect.WithDirectAPI())
60	}
61	client := protect.NewClient(cfg.Host, opts...)
62
63	// Login
64	ctx := context.Background()
65	err = client.Login(ctx, cfg.Username, cfg.Password)
66	if err != nil {
67		return fmt.Errorf("login: %w", err)
68	}
69
70	// Run fetch
71	result, err := pipeline.Fetch(ctx, client, layout, pipeline.FetchConfig{
72		Workers: cfg.Workers,
73		Retries: cfg.Retries,
74	})
75	if err != nil {
76		return err
77	}
78
79	fmt.Printf("Fetch complete: %d downloaded, %d skipped, %d failed\n",
80		result.Downloaded, result.Skipped, result.Failed)
81
82	if result.Failed > 0 {
83		fmt.Println("Failed clips:")
84		for _, e := range result.Errors {
85			fmt.Printf("  - %v\n", e)
86		}
87	}
88
89	return nil
90}