From de8a4d9e80a229e992083adcce625e1f7bdfaf9f Mon Sep 17 00:00:00 2001 From: Evan Fiordeliso Date: Fri, 14 Apr 2023 17:32:20 -0400 Subject: [PATCH] Add handler for proxy endpoint --- web/serve.go | 42 ++++++++++++++++++++++++++++++++++++++++-- ytdl/data.go | 2 +- ytdl/meta.go | 2 +- ytdl/stream.go | 23 +++++++++++++++++++++++ 4 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 ytdl/stream.go diff --git a/web/serve.go b/web/serve.go index 300d4b1..55d740f 100644 --- a/web/serve.go +++ b/web/serve.go @@ -29,6 +29,9 @@ func Serve() error { return fiber.ErrBadRequest } url := string(urlBytes) + if len(url) < 1 { + return fiber.ErrBadRequest + } meta, err := ytdl.GetMetadata(url) if err != nil { @@ -49,8 +52,43 @@ func Serve() error { }, "views/layouts/main") }) - app.Get("/download/stream", func(c *fiber.Ctx) error { - return nil + app.Get("/download/proxy", func(c *fiber.Ctx) error { + urlBytes, err := url.QueryUnescape(c.Query("url")) + if err != nil { + slog.Error("Failed to decode url param", slog.String("error", err.Error())) + return fiber.ErrBadRequest + } + url := string(urlBytes) + if len(url) < 1 { + return fiber.ErrBadRequest + } + + formatId := c.Query("format") + if len(formatId) < 1 { + return fiber.ErrBadRequest + } + + meta, err := ytdl.GetMetadata(url) + if err != nil { + slog.Error("Failed to get metadata", slog.String("error", err.Error())) + return fiber.ErrInternalServerError + } + + format, ok := lo.Find(meta.Formats, func(format ytdl.Format) bool { + return format.FormatID == formatId + }) + if !ok { + return fiber.ErrBadRequest + } + + c.Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s-%s.%s\"", meta.ID, format.Resolution, format.Ext)) + if format.Filesize != nil { + c.Set("Content-Length", fmt.Sprint(*format.Filesize)) + } else if format.FilesizeApprox != nil { + c.Set("Content-Length", fmt.Sprint(*format.FilesizeApprox)) + } + + return ytdl.Stream(c.Response().BodyWriter(), url, format) }) listenAddr := fmt.Sprintf("%s:%d", viper.GetString("listen"), viper.GetInt("port")) diff --git a/ytdl/data.go b/ytdl/data.go index bbd6ff2..82dcc21 100644 --- a/ytdl/data.go +++ b/ytdl/data.go @@ -252,7 +252,7 @@ type Format struct { Filesize *int `json:"filesize"` // An estimate for the number of bytes - FilesizeApprox int `json:"filesize_approx"` + FilesizeApprox *int `json:"filesize_approx"` // The protocol that will be used for the actual // download, lower-case. One of "http", "https" or diff --git a/ytdl/meta.go b/ytdl/meta.go index 06a13db..b643d6d 100644 --- a/ytdl/meta.go +++ b/ytdl/meta.go @@ -17,7 +17,7 @@ func GetMetadata(url string) (Metdata, error) { cmd.Stdout = &out if err := cmd.Run(); err != nil { - return Metdata{}, nil + return Metdata{}, err } var meta Metdata diff --git a/ytdl/stream.go b/ytdl/stream.go new file mode 100644 index 0000000..b6f7f2a --- /dev/null +++ b/ytdl/stream.go @@ -0,0 +1,23 @@ +package ytdl + +import ( + "io" + "os/exec" +) + +func Stream(wr io.Writer, url string, format Format) error { + cmd := exec.Command( + "yt-dlp", + "-o", "-", + "-f", format.FormatID, + "--merge-output-format", "mkv", + url, + ) + + cmd.Stdout = wr + if err := cmd.Run(); err != nil { + return err + } + + return nil +}