Fix proxy endpoint for playlists

This commit is contained in:
Evan Fiordeliso 2023-05-23 19:35:52 -04:00
parent 7e5c4856b4
commit 8052c02af1
6 changed files with 34 additions and 20 deletions

View File

@ -11,7 +11,7 @@ type Video struct {
} }
func GetVideos(meta *metadata.Metadata) []Video { 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 lo.Map(meta.Entries, func(video metadata.Metadata, _ int) Video {
return GetVideos(&video)[0] return GetVideos(&video)[0]
}) })

View File

@ -92,7 +92,15 @@ func (r *routes) DownloadProxyHandler(c *fiber.Ctx) error {
return fiber.ErrInternalServerError 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 return format.FormatID == formatId
}) })
if !ok { if !ok {
@ -106,5 +114,9 @@ func (r *routes) DownloadProxyHandler(c *fiber.Ctx) error {
c.Set("Content-Length", fmt.Sprint(*format.FilesizeApprox)) 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)
} }

View File

@ -9,20 +9,6 @@
{{$root := .}} {{$root := .}}
{{define "download"}}
<div style="font-size: smaller">{{.Format.Format}}</div>
<div class="flex-grow-1 d-flex gap-3">
<a class="btn btn-primary flex-grow-1" download="{{.Meta.ID}}-{{.Format.Resolution}}.{{.Format.Ext}}" P
href="{{.Format.Url}}">
Download (direct)
</a>
<a class="btn btn-primary flex-grow-1" download="{{.Meta.ID}}-{{.Format.Resolution}}.{{.Format.Ext}}"
href="{{.BasePath}}/download/proxy?url={{queryEscape .Url}}&format={{.Format.FormatID}}">
Download (proxied)
</a>
</div>
{{end}}
{{range $vidIndex, $video := .Videos}} {{range $vidIndex, $video := .Videos}}
{{if not (eq $vidIndex 0)}} {{if not (eq $vidIndex 0)}}
<hr class="mt-5" /> <hr class="mt-5" />
@ -40,7 +26,7 @@
Download (direct) Download (direct)
</a> </a>
<a class="btn btn-primary flex-grow-1" download="{{$root.Meta.ID}}-{{$format.Resolution}}.{{$format.Ext}}" <a class="btn btn-primary flex-grow-1" download="{{$root.Meta.ID}}-{{$format.Resolution}}.{{$format.Ext}}"
href="{{$root.BasePath}}/download/proxy?url={{queryEscape $root.Url}}&format={{$format.FormatID}}"> href="{{$root.BasePath}}/download/proxy?url={{queryEscape $root.Url}}&format={{$format.FormatID}}&index={{$vidIndex}}">
Download (proxied) Download (proxied)
</a> </a>
</div> </div>

View File

@ -3,6 +3,7 @@ package ytdl
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt"
"io" "io"
"strings" "strings"
@ -99,3 +100,10 @@ func WithDebug() Option {
return nil 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
}
}

View File

@ -176,3 +176,7 @@ type Metadata struct {
Chapters []Chapter `json:"chapters"` Chapters []Chapter `json:"chapters"`
} }
func (m Metadata) IsPlaylist() bool {
return m.Type == "playlist"
}

View File

@ -11,7 +11,7 @@ import (
type Ytdl interface { type Ytdl interface {
GetMetadata(url string) (*metadata.Metadata, error) 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 { type ytdlImpl struct {
@ -82,13 +82,17 @@ func (y *ytdlImpl) GetMetadata(url string) (*metadata.Metadata, error) {
} }
// Download implements Ytdl // 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( options := append(
y.baseOptions(url), y.baseOptions(url),
WithFormat(format), WithFormat(format),
WithStreamOutput(w), WithStreamOutput(w),
) )
if index >= 0 {
options = append(options, WithPlaylistIndex(index))
}
if err := Exec(y.cfg.Ytdlp.BinaryPath, url, options...); err != nil { if err := Exec(y.cfg.Ytdlp.BinaryPath, url, options...); err != nil {
return err return err
} }