131 lines
3.1 KiB
Go
131 lines
3.1 KiB
Go
package web
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/samber/lo"
|
|
"github.com/spf13/viper"
|
|
"go.fifitido.net/ytdl-web/version"
|
|
"go.fifitido.net/ytdl-web/ytdl"
|
|
"go.fifitido.net/ytdl-web/ytdl/metadata"
|
|
"golang.org/x/exp/slog"
|
|
)
|
|
|
|
type routes struct {
|
|
ytdl ytdl.Ytdl
|
|
}
|
|
|
|
func (r *routes) Register(app *fiber.App) {
|
|
app.Get("/", r.IndexHandler)
|
|
app.Get("/home", r.HomeHandler)
|
|
app.Get("/download", r.DownloadHandler)
|
|
app.Head("/download/proxy", r.DownloadProxyHandler)
|
|
app.Get("/download/proxy", r.DownloadProxyHandler)
|
|
}
|
|
|
|
func (r *routes) IndexHandler(c *fiber.Ctx) error {
|
|
return c.Render("views/index", fiber.Map{
|
|
"BasePath": viper.GetString("base_path"),
|
|
"Version": version.Version,
|
|
"Build": version.Build,
|
|
"YtdlpVersion": r.ytdl.Version(),
|
|
}, "views/layouts/main")
|
|
}
|
|
|
|
func (r *routes) HomeHandler(c *fiber.Ctx) error {
|
|
return c.Render("views/index", fiber.Map{
|
|
"BasePath": viper.GetString("base_path"),
|
|
})
|
|
}
|
|
|
|
func (r *routes) DownloadHandler(c *fiber.Ctx) error {
|
|
urlBytes, err := url.QueryUnescape(c.Query("url"))
|
|
if err != nil {
|
|
return c.Render("views/index", fiber.Map{
|
|
"BasePath": viper.GetString("base_path"),
|
|
"Error": fiber.Map{
|
|
"Message": "Invalid URL",
|
|
},
|
|
})
|
|
}
|
|
url := string(urlBytes)
|
|
if len(url) < 1 {
|
|
return c.Render("views/index", fiber.Map{
|
|
"BasePath": viper.GetString("base_path"),
|
|
"Error": fiber.Map{
|
|
"Message": "Invalid URL",
|
|
},
|
|
})
|
|
}
|
|
|
|
meta, err := r.ytdl.GetMetadata(url)
|
|
if err != nil {
|
|
return c.Render("views/index", fiber.Map{
|
|
"BasePath": viper.GetString("base_path"),
|
|
"Error": fiber.Map{
|
|
"Message": "Could not find a video at that url, maybe try again?",
|
|
},
|
|
})
|
|
}
|
|
|
|
return c.Render("views/download", fiber.Map{
|
|
"BasePath": viper.GetString("base_path"),
|
|
"Url": url,
|
|
"Meta": meta,
|
|
"Videos": GetVideos(meta),
|
|
})
|
|
}
|
|
|
|
func (r *routes) DownloadProxyHandler(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 := r.ytdl.GetMetadata(url)
|
|
if err != nil {
|
|
slog.Error("Failed to get metadata", slog.String("error", err.Error()))
|
|
return fiber.ErrInternalServerError
|
|
}
|
|
|
|
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 {
|
|
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))
|
|
}
|
|
|
|
if len(videos) == 1 {
|
|
index = -1
|
|
}
|
|
|
|
return r.ytdl.Download(c.Response().BodyWriter(), url, format.FormatID, index)
|
|
}
|