diff --git a/cmd/youtubedr/thumbnail.go b/cmd/youtubedr/thumbnail.go index 360edae7..34226e5f 100644 --- a/cmd/youtubedr/thumbnail.go +++ b/cmd/youtubedr/thumbnail.go @@ -3,7 +3,6 @@ package main import ( "fmt" "io" - "math" "os" "os/exec" "path/filepath" @@ -15,7 +14,7 @@ import ( var thumbnailCmd = &cobra.Command{ Use: "thumbnail", Short: "Downloads a thumbnail from youtube", - Example: `youtubedr thumbnail -x 720 -o thumbnail.png https://www.youtube.com/watch\?v\=TGqoAUaivOY`, + Example: `youtubedr thumbnail -n maxresdefault -o thumbnail.png https://www.youtube.com/watch\?v\=TGqoAUaivOY`, Args: cobra.ExactArgs(1), Run: func(_ *cobra.Command, args []string) { exitOnError(downloadThumbnail(args[0])) @@ -23,19 +22,17 @@ var thumbnailCmd = &cobra.Command{ } var ( - minRes uint - maxRes uint - noExtend bool + thumbnailName string + noExtend bool ) func init() { rootCmd.AddCommand(thumbnailCmd) - thumbnailCmd.Flags().StringVarP(&outputFile, "filename", "o", "", "The output file, the default is generated by the video title.") - thumbnailCmd.Flags().StringVarP(&outputDir, "directory", "d", ".", "The output directory.") - thumbnailCmd.Flags().UintVarP(&minRes, "min-resolution", "n", 0, "The minimum resolution.") - thumbnailCmd.Flags().UintVarP(&maxRes, "max-resolution", "x", math.MaxUint, "The maximum resolution.") - thumbnailCmd.Flags().BoolVarP(&noExtend, "known-only", "k", false, "Whether to only try thumbnails received in video response (lower quality).") + thumbnailCmd.Flags().StringVarP(&outputFile, "filename", "o", "", "the output file, the default is generated by the video title") + thumbnailCmd.Flags().StringVarP(&outputDir, "directory", "d", ".", "the output directory") + thumbnailCmd.Flags().StringVarP(&thumbnailName, "name", "n", "", "the thumbnail name (ex. \"maxresdefault\")") + thumbnailCmd.Flags().BoolVarP(&noExtend, "known-only", "k", false, "only try thumbnails received in video response (lower quality)") } func downloadThumbnail(url string) error { @@ -50,8 +47,9 @@ func downloadThumbnail(url string) error { if !noExtend { thumbnails = thumbnails.Extended(video.ID) } - thumbnails = thumbnails.MinHeight(minRes) - thumbnails = thumbnails.MaxHeight(maxRes) + if thumbnailName != "" { + thumbnails = thumbnails.FilterName(thumbnailName) + } thumbnails.Sort() if outputFile == "" { diff --git a/thumbnails.go b/thumbnails.go index 02943aa0..9b64c5d8 100644 --- a/thumbnails.go +++ b/thumbnails.go @@ -117,38 +117,54 @@ func (t Thumbnails) FilterExt(ext ...string) Thumbnails { // FilterLive removes thumbnails that do not match the provided live status. func (t Thumbnails) FilterLive(live bool) Thumbnails { return slices.DeleteFunc(t, func(thumbnail Thumbnail) bool { - name := path.Base(thumbnail.URL) + u, err := url.Parse(thumbnail.URL) + if err != nil { + return true + } + name := path.Base(u.Path) parts := strings.SplitN(name, "_", 2) l := len(parts) > 1 && strings.HasPrefix(parts[1], "live") return l != live }) } -// MinWidth filters out thumbnails with greater than desired width. +// MinWidth filters out thumbnails with less than desired width. func (t Thumbnails) MinWidth(w uint) Thumbnails { return slices.DeleteFunc(t, func(thumbnail Thumbnail) bool { return thumbnail.Width < w }) } -// MaxWidth filters out thumbnails with less than desired width. +// MaxWidth filters out thumbnails with greater desired width. func (t Thumbnails) MaxWidth(w uint) Thumbnails { return slices.DeleteFunc(t, func(thumbnail Thumbnail) bool { return thumbnail.Width > w }) } -// MinHeight filters out thumbnails with greater than desired height. -func (t Thumbnails) MinHeight(w uint) Thumbnails { +// MinHeight filters out thumbnails with less than desired height. +func (t Thumbnails) MinHeight(h uint) Thumbnails { + return slices.DeleteFunc(t, func(thumbnail Thumbnail) bool { + return thumbnail.Height < h + }) +} + +// MaxHeight filters out thumbnails with greater than desired height. +func (t Thumbnails) MaxHeight(h uint) Thumbnails { return slices.DeleteFunc(t, func(thumbnail Thumbnail) bool { - return thumbnail.Height < w + return thumbnail.Height > h }) } -// MaxHeight filters out thumbnails with less than desired height. -func (t Thumbnails) MaxHeight(w uint) Thumbnails { +func (t Thumbnails) FilterName(names ...string) Thumbnails { return slices.DeleteFunc(t, func(thumbnail Thumbnail) bool { - return thumbnail.Height > w + u, err := url.Parse(thumbnail.URL) + if err != nil { + return true + } + fileName := path.Base(u.Path) + nameNoExt := strings.TrimSuffix(fileName, path.Ext(fileName)) + return !slices.Contains(names, nameNoExt) }) }