(ctx *snap.Context)
| 2349 | } |
| 2350 | |
| 2351 | func runYoutubeToSound(ctx *snap.Context) error { |
| 2352 | var ( |
| 2353 | videoURL string |
| 2354 | err error |
| 2355 | ) |
| 2356 | |
| 2357 | if ctx.NArgs() > 0 { |
| 2358 | videoURL = strings.TrimSpace(ctx.Arg(0)) |
| 2359 | } else { |
| 2360 | videoURL, err = safariFrontmostURL() |
| 2361 | if err != nil { |
| 2362 | fmt.Fprintf(ctx.Stderr(), "Usage: %s youtubeToSound [youtube-url] [yt-dlp-args...]\n", commandName) |
| 2363 | return reportError(ctx, fmt.Errorf("determine Safari tab URL: %w", err)) |
| 2364 | } |
| 2365 | } |
| 2366 | |
| 2367 | if videoURL == "" { |
| 2368 | fmt.Fprintf(ctx.Stderr(), "Usage: %s youtubeToSound [youtube-url] [yt-dlp-args...]\n", commandName) |
| 2369 | return reportError(ctx, fmt.Errorf("youtube url cannot be empty")) |
| 2370 | } |
| 2371 | |
| 2372 | if _, err := url.ParseRequestURI(videoURL); err != nil { |
| 2373 | return reportError(ctx, fmt.Errorf("validate url %q: %w", videoURL, err)) |
| 2374 | } |
| 2375 | |
| 2376 | downloader := "yt-dlp" |
| 2377 | if _, err := exec.LookPath(downloader); err != nil { |
| 2378 | return reportError(ctx, fmt.Errorf("%s not found in PATH: %w", downloader, err)) |
| 2379 | } |
| 2380 | |
| 2381 | homeDir, err := os.UserHomeDir() |
| 2382 | if err != nil { |
| 2383 | return reportError(ctx, fmt.Errorf("determine home directory: %w", err)) |
| 2384 | } |
| 2385 | |
| 2386 | targetDir := filepath.Join(homeDir, ".flow", "youtube-sound") |
| 2387 | if err := os.MkdirAll(targetDir, 0o755); err != nil { |
| 2388 | return reportError(ctx, fmt.Errorf("create directory %s: %w", targetDir, err)) |
| 2389 | } |
| 2390 | |
| 2391 | outputTemplate := filepath.Join(targetDir, "%(title)s.%(ext)s") |
| 2392 | args := []string{"--extract-audio", "--audio-format", "mp3", "--audio-quality", "0", "--no-playlist", "-o", outputTemplate} |
| 2393 | if ctx.NArgs() > 1 { |
| 2394 | extra := ctx.Args()[1:] |
| 2395 | for _, raw := range extra { |
| 2396 | trimmed := strings.TrimSpace(raw) |
| 2397 | if trimmed != "" { |
| 2398 | args = append(args, trimmed) |
| 2399 | } |
| 2400 | } |
| 2401 | } |
| 2402 | |
| 2403 | defaultBrowser := strings.TrimSpace(os.Getenv("FLOW_YOUTUBE_COOKIES_BROWSER")) |
| 2404 | if defaultBrowser == "" { |
| 2405 | defaultBrowser = "safari" |
| 2406 | } |
| 2407 | if !strings.EqualFold(defaultBrowser, "none") && !containsCookiesArgument(args) { |
| 2408 | args = append(args, "--cookies-from-browser", defaultBrowser) |
no test coverage detected