Move routes to a struct and add a HEAD handler for /download/proxy
This commit is contained in:
parent
dba5305302
commit
20a9e6d01a
|
@ -2,7 +2,7 @@ version: "3"
|
||||||
|
|
||||||
vars:
|
vars:
|
||||||
OUT: ./out/ytdl-web
|
OUT: ./out/ytdl-web
|
||||||
VERSION: 1.0.2
|
VERSION: 1.0.3
|
||||||
VERSION_PKG: go.fifitido.net/ytdl-web/version
|
VERSION_PKG: go.fifitido.net/ytdl-web/version
|
||||||
BUILD:
|
BUILD:
|
||||||
sh: git rev-parse --short HEAD
|
sh: git rev-parse --short HEAD
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
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"
|
||||||
|
"golang.org/x/exp/slog"
|
||||||
|
)
|
||||||
|
|
||||||
|
type routes struct{}
|
||||||
|
|
||||||
|
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 := 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 := 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)
|
||||||
|
}
|
91
web/serve.go
91
web/serve.go
|
@ -2,104 +2,17 @@ package web
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"github.com/samber/lo"
|
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"github.com/sujit-baniya/flash"
|
|
||||||
"go.fifitido.net/ytdl-web/version"
|
|
||||||
"go.fifitido.net/ytdl-web/ytdl"
|
|
||||||
"golang.org/x/exp/slog"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Serve() error {
|
func Serve() error {
|
||||||
engine := ViewsEngine()
|
engine := ViewsEngine()
|
||||||
app := fiber.New(fiber.Config{Views: engine})
|
app := fiber.New(fiber.Config{Views: engine})
|
||||||
|
routes := &routes{}
|
||||||
|
|
||||||
app.Get("/", func(c *fiber.Ctx) error {
|
routes.Register(app)
|
||||||
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")
|
|
||||||
})
|
|
||||||
|
|
||||||
app.Get("/download", func(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 := 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")
|
|
||||||
})
|
|
||||||
|
|
||||||
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"))
|
listenAddr := fmt.Sprintf("%s:%d", viper.GetString("listen"), viper.GetInt("port"))
|
||||||
|
|
||||||
|
|
|
@ -168,11 +168,11 @@ type Metadata struct {
|
||||||
|
|
||||||
// Time in seconds where the reproduction should start, as
|
// Time in seconds where the reproduction should start, as
|
||||||
// specified in the URL.
|
// specified in the URL.
|
||||||
StartTime *int64 `json:"start_time"`
|
StartTime *float64 `json:"start_time"`
|
||||||
|
|
||||||
// Time in seconds where the reproduction should end, as
|
// Time in seconds where the reproduction should end, as
|
||||||
// specified in the URL.
|
// specified in the URL.
|
||||||
EndTime *int64 `json:"end_time"`
|
EndTime *float64 `json:"end_time"`
|
||||||
|
|
||||||
Chapters []Chapter `json:"chapters"`
|
Chapters []Chapter `json:"chapters"`
|
||||||
}
|
}
|
||||||
|
@ -437,10 +437,10 @@ type Comment struct {
|
||||||
|
|
||||||
type Chapter struct {
|
type Chapter struct {
|
||||||
// The start time of the chapter in seconds
|
// The start time of the chapter in seconds
|
||||||
StartTime int64 `json:"start_time"`
|
StartTime float64 `json:"start_time"`
|
||||||
|
|
||||||
// The end time of the chapter in seconds
|
// The end time of the chapter in seconds
|
||||||
EndTime int64 `json:"end_time"`
|
EndTime float64 `json:"end_time"`
|
||||||
|
|
||||||
Title *string `json:"title"`
|
Title *string `json:"title"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package ytdl
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
@ -20,11 +21,14 @@ func GetMetadata(url string) (Metadata, error) {
|
||||||
cmd.Stdout = &out
|
cmd.Stdout = &out
|
||||||
|
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
|
|
||||||
|
fmt.Printf("%+v\n", err)
|
||||||
return Metadata{}, err
|
return Metadata{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var meta Metadata
|
var meta Metadata
|
||||||
if err := json.Unmarshal(out.Bytes(), &meta); err != nil {
|
if err := json.Unmarshal(out.Bytes(), &meta); err != nil {
|
||||||
|
fmt.Printf("%+v\n", err)
|
||||||
return Metadata{}, err
|
return Metadata{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue