ytdl-web/web/serve.go

117 lines
3.0 KiB
Go
Raw Normal View History

2023-04-14 11:58:32 -04:00
package web
import (
"fmt"
2023-04-14 16:07:57 -04:00
"net/url"
"sort"
2023-04-14 11:58:32 -04:00
"github.com/gofiber/fiber/v2"
2023-04-14 16:07:57 -04:00
"github.com/samber/lo"
"github.com/spf13/viper"
2023-04-14 21:55:00 -04:00
"github.com/sujit-baniya/flash"
2023-04-14 22:42:44 -04:00
"go.fifitido.net/ytdl-web/version"
2023-04-14 16:07:57 -04:00
"go.fifitido.net/ytdl-web/ytdl"
"golang.org/x/exp/slog"
2023-04-14 11:58:32 -04:00
)
func Serve() error {
engine := ViewsEngine()
app := fiber.New(fiber.Config{Views: engine})
app.Get("/", func(c *fiber.Ctx) error {
return c.Render("views/index", fiber.Map{
2023-04-14 22:42:44 -04:00
"BasePath": viper.GetString("base_path"),
"Flash": flash.Get(c),
"Version": version.Version,
"Build": version.Build,
"YtdlpVersion": ytdl.GetVersion(),
}, "views/layouts/main")
2023-04-14 11:58:32 -04:00
})
app.Get("/download", func(c *fiber.Ctx) error {
2023-04-14 16:07:57 -04:00
urlBytes, err := url.QueryUnescape(c.Query("url"))
if err != nil {
2023-04-14 21:55:00 -04:00
return flash.WithError(c, fiber.Map{
"error": true,
"message": "Invalid URL",
}).Redirect("/")
2023-04-14 16:07:57 -04:00
}
url := string(urlBytes)
2023-04-14 17:32:20 -04:00
if len(url) < 1 {
2023-04-14 21:55:00 -04:00
return flash.WithError(c, fiber.Map{
"error": true,
"message": "Invalid URL",
}).Redirect("/")
2023-04-14 17:32:20 -04:00
}
2023-04-14 16:07:57 -04:00
meta, err := ytdl.GetMetadata(url)
if err != nil {
2023-04-14 21:55:00 -04:00
return flash.WithError(c, fiber.Map{
"error": true,
"message": "Could not find a video at that url, maybe try again?",
}).Redirect("/")
2023-04-14 16:07:57 -04:00
}
formats := lo.Filter(meta.Formats, func(item ytdl.Format, _ int) bool {
2023-04-14 21:55:00 -04:00
return item.ACodec != "none" && item.VCodec != "none" && item.Protocol != "m3u8_native"
2023-04-14 16:07:57 -04:00
})
sort.Slice(formats, func(i, j int) bool {
return formats[i].Width > formats[j].Width
})
2023-04-14 11:58:32 -04:00
return c.Render("views/download", fiber.Map{
2023-04-14 22:42:44 -04:00
"BasePath": viper.GetString("base_path"),
"Url": url,
"Meta": meta,
"Formats": formats,
"Version": version.Version,
"Build": version.Build,
"YtdlpVersion": ytdl.GetVersion(),
2023-04-14 11:58:32 -04:00
}, "views/layouts/main")
})
2023-04-14 17:32:20 -04:00
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)
2023-04-14 11:58:32 -04:00
})
listenAddr := fmt.Sprintf("%s:%d", viper.GetString("listen"), viper.GetInt("port"))
return app.Listen(listenAddr)
2023-04-14 11:58:32 -04:00
}