package main import ( "bytes" "context" "encoding/json" "flag" "fmt" "io" "net/http" "strings" "time" ) // runAdd — тонкий CLI-клиент REST API запущенного сервиса (для отладки): // // jellybit add --context "..." --server http://localhost:8080 func runAdd(args []string) error { fs := flag.NewFlagSet("add", flag.ContinueOnError) server := fs.String("server", "http://localhost:8080", "адрес запущенного jellybit") contextStr := fs.String("context", "", "контекст для распознавания") // stdlib flag прекращает разбор на первом позиционном аргументе, поэтому // magnet (если он идёт первым) вынимаем до Parse — так работают оба // порядка: `add --context ...` и `add --context ... `. var source string if len(args) > 0 && !strings.HasPrefix(args[0], "-") { source, args = args[0], args[1:] } if err := fs.Parse(args); err != nil { return err } if source == "" { if fs.NArg() < 1 { return fmt.Errorf("usage: jellybit add [--context ...] [--server ...]") } source = fs.Arg(0) } body, err := json.Marshal(map[string]string{"source": source, "context": *contextStr}) if err != nil { return err } ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() endpoint := strings.TrimRight(*server, "/") + "/api/downloads" req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint, bytes.NewReader(body)) if err != nil { return err } req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { return fmt.Errorf("call %s: %w", endpoint, err) } defer func() { _ = resp.Body.Close() }() respBody, _ := io.ReadAll(io.LimitReader(resp.Body, 1<<16)) if resp.StatusCode >= 400 { return fmt.Errorf("server returned %d: %s", resp.StatusCode, strings.TrimSpace(string(respBody))) } fmt.Println(strings.TrimSpace(string(respBody))) return nil }