package web import ( "fmt" "net/url" "github.com/gofiber/fiber/v2" "github.com/samber/lo" "github.com/spf13/viper" "github.com/sujit-baniya/flash" "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("/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"), "Flash": flash.Get(c), "Version": version.Version, "Build": version.Build, "YtdlpVersion": ytdl.GetVersion(), }, "views/layouts/main") } func (r *routes) DownloadHandler(c *fiber.Ctx) error { urlBytes, err := url.QueryUnescape(c.Query("url")) if err != nil { return flash.WithError(c, fiber.Map{ "error": true, "message": "Invalid URL", }).Redirect("/") } url := string(urlBytes) if len(url) < 1 { return flash.WithError(c, fiber.Map{ "error": true, "message": "Invalid URL", }).Redirect("/") } meta, err := r.ytdl.GetMetadata(url) if err != nil { return flash.WithError(c, fiber.Map{ "error": true, "message": "Could not find a video at that url, maybe try again?", }).Redirect("/") } return c.Render("views/download", fiber.Map{ "BasePath": viper.GetString("base_path"), "Url": url, "Meta": meta, "Videos": GetVideos(meta), "Version": version.Version, "Build": version.Build, "YtdlpVersion": ytdl.GetVersion(), }, "views/layouts/main") } 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) }