From 8052c02af11fe4b95adc7c79def98fb8370a0822 Mon Sep 17 00:00:00 2001 From: Evan Fiordeliso Date: Tue, 23 May 2023 19:35:52 -0400 Subject: [PATCH] Fix proxy endpoint for playlists --- web/formats.go | 2 +- web/routes.go | 16 ++++++++++++++-- web/views/download.html | 16 +--------------- ytdl/cmdopts.go | 8 ++++++++ ytdl/metadata/metadata.go | 4 ++++ ytdl/ytdl.go | 8 ++++++-- 6 files changed, 34 insertions(+), 20 deletions(-) diff --git a/web/formats.go b/web/formats.go index b1d8342..007f6e1 100644 --- a/web/formats.go +++ b/web/formats.go @@ -11,7 +11,7 @@ type Video struct { } func GetVideos(meta *metadata.Metadata) []Video { - if meta.Type == "playlist" { + if meta.IsPlaylist() { return lo.Map(meta.Entries, func(video metadata.Metadata, _ int) Video { return GetVideos(&video)[0] }) diff --git a/web/routes.go b/web/routes.go index 7f7f19e..d737e24 100644 --- a/web/routes.go +++ b/web/routes.go @@ -92,7 +92,15 @@ func (r *routes) DownloadProxyHandler(c *fiber.Ctx) error { return fiber.ErrInternalServerError } - format, ok := lo.Find(meta.Formats, func(format metadata.Format) bool { + videos := GetVideos(meta) + index := c.QueryInt("index") + + if index < 0 || index >= len(videos) { + return fiber.ErrBadRequest + } + + video := videos[index] + format, ok := lo.Find(video.Formats, func(format metadata.Format) bool { return format.FormatID == formatId }) if !ok { @@ -106,5 +114,9 @@ func (r *routes) DownloadProxyHandler(c *fiber.Ctx) error { c.Set("Content-Length", fmt.Sprint(*format.FilesizeApprox)) } - return r.ytdl.Download(c.Response().BodyWriter(), url, format.FormatID) + if len(videos) == 1 { + index = -1 + } + + return r.ytdl.Download(c.Response().BodyWriter(), url, format.FormatID, index) } diff --git a/web/views/download.html b/web/views/download.html index f9da057..a55660c 100644 --- a/web/views/download.html +++ b/web/views/download.html @@ -9,20 +9,6 @@ {{$root := .}} -{{define "download"}} -
{{.Format.Format}}
-
- - Download (direct) - - - Download (proxied) - -
-{{end}} - {{range $vidIndex, $video := .Videos}} {{if not (eq $vidIndex 0)}}
@@ -40,7 +26,7 @@ Download (direct) + href="{{$root.BasePath}}/download/proxy?url={{queryEscape $root.Url}}&format={{$format.FormatID}}&index={{$vidIndex}}"> Download (proxied) diff --git a/ytdl/cmdopts.go b/ytdl/cmdopts.go index 5080bd0..314f7ac 100644 --- a/ytdl/cmdopts.go +++ b/ytdl/cmdopts.go @@ -3,6 +3,7 @@ package ytdl import ( "bytes" "encoding/json" + "fmt" "io" "strings" @@ -99,3 +100,10 @@ func WithDebug() Option { return nil } } + +func WithPlaylistIndex(index int) Option { + return func(opts *Options) error { + opts.args = append(opts.args, "--playlist-items", fmt.Sprint(index+1)) + return nil + } +} diff --git a/ytdl/metadata/metadata.go b/ytdl/metadata/metadata.go index 3e4bac0..9545ed6 100644 --- a/ytdl/metadata/metadata.go +++ b/ytdl/metadata/metadata.go @@ -176,3 +176,7 @@ type Metadata struct { Chapters []Chapter `json:"chapters"` } + +func (m Metadata) IsPlaylist() bool { + return m.Type == "playlist" +} diff --git a/ytdl/ytdl.go b/ytdl/ytdl.go index 310017d..1404304 100644 --- a/ytdl/ytdl.go +++ b/ytdl/ytdl.go @@ -11,7 +11,7 @@ import ( type Ytdl interface { GetMetadata(url string) (*metadata.Metadata, error) - Download(w io.Writer, url, format string) error + Download(w io.Writer, url, format string, index int) error } type ytdlImpl struct { @@ -82,13 +82,17 @@ func (y *ytdlImpl) GetMetadata(url string) (*metadata.Metadata, error) { } // Download implements Ytdl -func (y *ytdlImpl) Download(w io.Writer, url, format string) error { +func (y *ytdlImpl) Download(w io.Writer, url, format string, index int) error { options := append( y.baseOptions(url), WithFormat(format), WithStreamOutput(w), ) + if index >= 0 { + options = append(options, WithPlaylistIndex(index)) + } + if err := Exec(y.cfg.Ytdlp.BinaryPath, url, options...); err != nil { return err }