Simplify structure by moving routes into command package
This commit is contained in:
parent
f3f852fefd
commit
2630af4921
|
|
@ -1,4 +1,4 @@
|
|||
package routes
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
|
@ -8,43 +8,11 @@ import (
|
|||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/a-h/templ"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"go.fifitido.net/ytdl-web/pkg/models"
|
||||
"go.fifitido.net/ytdl-web/pkg/views"
|
||||
"go.fifitido.net/ytdl-web/pkg/ytdl"
|
||||
"go.fifitido.net/ytdl-web/pkg/ytdl/metadata"
|
||||
)
|
||||
|
||||
func Router() chi.Router {
|
||||
r := chi.NewRouter()
|
||||
r.Get("/", home)
|
||||
r.Route("/download", func(r chi.Router) {
|
||||
r.Get("/", download)
|
||||
r.Head("/proxy", proxyDownload)
|
||||
r.Get("/proxy", proxyDownload)
|
||||
})
|
||||
return r
|
||||
}
|
||||
|
||||
func renderPage(w http.ResponseWriter, r *http.Request, component templ.Component) {
|
||||
isHtmx := r.Header.Get("HX-Request") == "true"
|
||||
|
||||
if isHtmx {
|
||||
if err := templ.RenderFragments(r.Context(), w, component, "main-content"); err != nil {
|
||||
slog.ErrorContext(r.Context(), "failed to render page", slog.Any("error", err))
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
component.Render(r.Context(), w)
|
||||
}
|
||||
|
||||
func home(w http.ResponseWriter, r *http.Request) {
|
||||
renderPage(w, r, views.Home(nil))
|
||||
}
|
||||
|
||||
func getUrlParam(r *http.Request) (string, bool) {
|
||||
urlRaw := r.URL.Query().Get("url")
|
||||
if urlRaw == "" {
|
||||
|
|
@ -64,17 +32,17 @@ func download(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
videoUrl, ok := getUrlParam(r)
|
||||
if !ok {
|
||||
renderPage(w, r, views.Home(&views.Error{Message: "Invalid URL"}))
|
||||
views.Render(w, r, views.Home(&views.Error{Message: "Invalid URL"}))
|
||||
return
|
||||
}
|
||||
|
||||
meta, err := ytdl.GetMetadata(videoUrl)
|
||||
if err != nil {
|
||||
renderPage(w, r, views.Home(&views.Error{Message: "Could not find a video at that url", RetryUrl: &videoUrl}))
|
||||
views.Render(w, r, views.Home(&views.Error{Message: "Could not find a video at that url", RetryUrl: &videoUrl}))
|
||||
return
|
||||
}
|
||||
|
||||
renderPage(w, r, views.Downloads(&views.DownloadsViewModel{Url: videoUrl, Meta: meta}))
|
||||
views.Render(w, r, views.Downloads(&views.DownloadsViewModel{Url: videoUrl, Meta: meta}))
|
||||
}
|
||||
|
||||
func proxyDownload(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
@ -97,7 +65,7 @@ func proxyDownload(w http.ResponseWriter, r *http.Request) {
|
|||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
videos := models.GetVideosFromMetadata(meta)
|
||||
videos := views.GetVideosFromMetadata(meta)
|
||||
|
||||
index, err := strconv.Atoi(r.URL.Query().Get("index"))
|
||||
if err != nil || index < 0 || index >= len(videos) {
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"log/slog"
|
||||
|
||||
"github.com/dgraph-io/badger/v2"
|
||||
)
|
||||
|
||||
type badgerLogger struct {
|
||||
logger *slog.Logger
|
||||
}
|
||||
|
||||
var _ badger.Logger = (*badgerLogger)(nil)
|
||||
|
||||
// Debugf implements badger.Logger
|
||||
func (l *badgerLogger) Debugf(f string, a ...any) {
|
||||
l.logger.Debug(fmt.Sprintf(f, a...))
|
||||
}
|
||||
|
||||
// Errorf implements badger.Logger
|
||||
func (l *badgerLogger) Errorf(f string, a ...any) {
|
||||
l.logger.Error(fmt.Sprintf(f, a...))
|
||||
}
|
||||
|
||||
// Infof implements badger.Logger
|
||||
func (l *badgerLogger) Infof(f string, a ...any) {
|
||||
l.logger.Info(fmt.Sprintf(f, a...))
|
||||
}
|
||||
|
||||
// Warningf implements badger.Logger
|
||||
func (l *badgerLogger) Warningf(f string, a ...any) {
|
||||
l.logger.Warn(fmt.Sprintf(f, a...))
|
||||
}
|
||||
|
|
@ -15,9 +15,8 @@ import (
|
|||
"github.com/go-chi/chi/v5/middleware"
|
||||
slogchi "github.com/samber/slog-chi"
|
||||
"go.fifitido.net/ytdl-web/pkg/config"
|
||||
"go.fifitido.net/ytdl-web/pkg/routes"
|
||||
"go.fifitido.net/ytdl-web/pkg/serverctx"
|
||||
"go.fifitido.net/ytdl-web/pkg/utils"
|
||||
"go.fifitido.net/ytdl-web/pkg/views"
|
||||
"go.fifitido.net/ytdl-web/pkg/ytdl"
|
||||
"go.fifitido.net/ytdl-web/pkg/ytdl/cache"
|
||||
)
|
||||
|
|
@ -57,7 +56,7 @@ func main() {
|
|||
db, err := badger.Open(
|
||||
badger.
|
||||
DefaultOptions(cacheDir()).
|
||||
WithLogger(utils.NewBadgerLogger(logger.With("module", "badger"))),
|
||||
WithLogger(&badgerLogger{logger: logger.With("module", "badger")}),
|
||||
)
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
|
|
@ -87,7 +86,14 @@ func main() {
|
|||
middleware.Recoverer,
|
||||
)
|
||||
|
||||
r.Mount(basePath(), routes.Router())
|
||||
r.Route(basePath(), func(r chi.Router) {
|
||||
r.Get("/", views.Handler(views.Home(nil)))
|
||||
r.Route("/download", func(r chi.Router) {
|
||||
r.Get("/", download)
|
||||
r.Head("/proxy", proxyDownload)
|
||||
r.Get("/proxy", proxyDownload)
|
||||
})
|
||||
})
|
||||
|
||||
logger.Info("Starting HTTP server", slog.String("listen", listenAddr()))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,46 +0,0 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"go.fifitido.net/ytdl-web/pkg/ytdl/metadata"
|
||||
)
|
||||
|
||||
type Video struct {
|
||||
Meta *metadata.Metadata
|
||||
Formats []metadata.Format
|
||||
OtherFormats []metadata.Format
|
||||
}
|
||||
|
||||
func GetVideosFromMetadata(meta *metadata.Metadata) []Video {
|
||||
if meta.IsPlaylist() {
|
||||
videos := make([]Video, 0, len(meta.Entries))
|
||||
|
||||
for _, entry := range meta.Entries {
|
||||
videos = append(videos, GetVideosFromMetadata(&entry)...)
|
||||
}
|
||||
|
||||
return videos
|
||||
}
|
||||
|
||||
formats := []metadata.Format{}
|
||||
otherFormats := []metadata.Format{}
|
||||
|
||||
for _, format := range meta.Formats {
|
||||
if format.ACodec != "none" && format.VCodec != "none" && format.Protocol != "m3u8_native" {
|
||||
formats = append(formats, format)
|
||||
} else {
|
||||
otherFormats = append(otherFormats, format)
|
||||
}
|
||||
}
|
||||
|
||||
for i, j := 0, len(formats)-1; i < j; i, j = i+1, j-1 {
|
||||
formats[i], formats[j] = formats[j], formats[i]
|
||||
}
|
||||
|
||||
return []Video{
|
||||
{
|
||||
Meta: meta,
|
||||
Formats: formats,
|
||||
OtherFormats: otherFormats,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"log/slog"
|
||||
|
||||
"github.com/dgraph-io/badger/v2"
|
||||
)
|
||||
|
||||
type SlogLogger struct {
|
||||
logger *slog.Logger
|
||||
}
|
||||
|
||||
// Debugf implements badger.Logger
|
||||
func (l *SlogLogger) Debugf(f string, a ...interface{}) {
|
||||
l.logger.Debug(fmt.Sprintf(f, a...))
|
||||
}
|
||||
|
||||
// Errorf implements badger.Logger
|
||||
func (l *SlogLogger) Errorf(f string, a ...interface{}) {
|
||||
l.logger.Error(fmt.Sprintf(f, a...))
|
||||
}
|
||||
|
||||
// Infof implements badger.Logger
|
||||
func (l *SlogLogger) Infof(f string, a ...interface{}) {
|
||||
l.logger.Info(fmt.Sprintf(f, a...))
|
||||
}
|
||||
|
||||
// Warningf implements badger.Logger
|
||||
func (l *SlogLogger) Warningf(f string, a ...interface{}) {
|
||||
l.logger.Warn(fmt.Sprintf(f, a...))
|
||||
}
|
||||
|
||||
var _ badger.Logger = (*SlogLogger)(nil)
|
||||
|
||||
func NewBadgerLogger(logger *slog.Logger) badger.Logger {
|
||||
return &SlogLogger{
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
type loggerWriter struct {
|
||||
logger *slog.Logger
|
||||
logLevel slog.Level
|
||||
}
|
||||
|
||||
func (lw *loggerWriter) Write(p []byte) (n int, err error) {
|
||||
lw.logger.Log(context.Background(), lw.logLevel, string(p))
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func LoggerWriter(logger *slog.Logger, level slog.Level) io.Writer {
|
||||
return &loggerWriter{logger: logger, logLevel: level}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package views
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"net/http"
|
||||
|
||||
"github.com/a-h/templ"
|
||||
)
|
||||
|
||||
func Handler(component templ.Component) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
Render(w, r, component)
|
||||
}
|
||||
}
|
||||
|
||||
func Render(w http.ResponseWriter, r *http.Request, component templ.Component) {
|
||||
isHtmx := r.Header.Get("HX-Request") == "true"
|
||||
|
||||
if isHtmx {
|
||||
if err := templ.RenderFragments(r.Context(), w, component, "main-content"); err != nil {
|
||||
slog.ErrorContext(r.Context(), "failed to render page", slog.Any("error", err))
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
component.Render(r.Context(), w)
|
||||
}
|
||||
Loading…
Reference in New Issue