added status API endpoint

This commit is contained in:
2024-12-19 13:08:25 +01:00
parent 17fb608f45
commit f9e829dce6
8 changed files with 230 additions and 5 deletions

View File

@@ -23,6 +23,6 @@ type Format struct {
Resolution string `json:"resolution"`
VCodec string `json:"vcodec"`
ACodec string `json:"acodec"`
Size float32 `json:"filesize_approx"`
Size float64 `json:"filesize_approx"`
Language string `json:"language"`
}

View File

@@ -5,9 +5,9 @@ import "time"
// Used to unmarshall yt-dlp progress
type ProgressTemplate struct {
Percentage string `json:"percentage"`
Speed float32 `json:"speed"`
Speed float64 `json:"speed"`
Size string `json:"size"`
Eta float32 `json:"eta"`
Eta float64 `json:"eta"`
}
type PostprocessTemplate struct {
@@ -25,8 +25,8 @@ type DownloadOutput struct {
type DownloadProgress struct {
Status int `json:"process_status"`
Percentage string `json:"percentage"`
Speed float32 `json:"speed"`
ETA float32 `json:"eta"`
Speed float64 `json:"speed"`
ETA float64 `json:"eta"`
}
// Used to deser the yt-dlp -J output

View File

@@ -31,6 +31,7 @@ import (
"github.com/marcopeocchi/yt-dlp-web-ui/v3/server/openid"
"github.com/marcopeocchi/yt-dlp-web-ui/v3/server/rest"
ytdlpRPC "github.com/marcopeocchi/yt-dlp-web-ui/v3/server/rpc"
"github.com/marcopeocchi/yt-dlp-web-ui/v3/server/status"
_ "modernc.org/sqlite"
)
@@ -221,6 +222,9 @@ func newServer(c serverConfig) *http.Server {
// Logging
r.Route("/log", logging.ApplyRouter(observableLogger))
// Status
r.Route("/status", status.ApplyRouter(c.mdb))
return &http.Server{Handler: r}
}

View File

@@ -0,0 +1,28 @@
package domain
import (
"context"
"net/http"
)
type Status struct {
Downloading int `json:"downloading"`
Pending int `json:"pending"`
Completed int `json:"completed"`
DownloadSpeed int `json:"download_speed"`
}
type Repository interface {
Pending(ctx context.Context) int
Completed(ctx context.Context) int
Downloading(ctx context.Context) int
DownloadSpeed(ctx context.Context) int64
}
type Service interface {
Status(ctx context.Context) (*Status, error)
}
type RestHandler interface {
Status() http.HandlerFunc
}

View File

@@ -0,0 +1,65 @@
package repository
import (
"context"
"slices"
"github.com/marcopeocchi/yt-dlp-web-ui/v3/server/internal"
"github.com/marcopeocchi/yt-dlp-web-ui/v3/server/status/domain"
)
type Repository struct {
mdb *internal.MemoryDB
}
// DownloadSpeed implements domain.Repository.
func (r *Repository) DownloadSpeed(ctx context.Context) int64 {
processes := r.mdb.All()
var downloadSpeed float64
for _, p := range *processes {
downloadSpeed += p.Progress.Speed
}
return int64(downloadSpeed)
}
// Completed implements domain.Repository.
func (r *Repository) Completed(ctx context.Context) int {
processes := r.mdb.All()
completed := slices.DeleteFunc(*processes, func(p internal.ProcessResponse) bool {
return p.Progress.Status != internal.StatusCompleted
})
return len(completed)
}
// Downloading implements domain.Repository.
func (r *Repository) Downloading(ctx context.Context) int {
processes := r.mdb.All()
downloading := slices.DeleteFunc(*processes, func(p internal.ProcessResponse) bool {
return p.Progress.Status != internal.StatusDownloading
})
return len(downloading)
}
// Pending implements domain.Repository.
func (r *Repository) Pending(ctx context.Context) int {
processes := r.mdb.All()
pending := slices.DeleteFunc(*processes, func(p internal.ProcessResponse) bool {
return p.Progress.Status != internal.StatusPending
})
return len(pending)
}
func New(mdb *internal.MemoryDB) domain.Repository {
return &Repository{
mdb: mdb,
}
}

View File

@@ -0,0 +1,38 @@
package rest
import (
"encoding/json"
"net/http"
"github.com/marcopeocchi/yt-dlp-web-ui/v3/server/status/domain"
)
type RestHandler struct {
service domain.Service
}
// Status implements domain.RestHandler.
func (h *RestHandler) Status() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
w.Header().Set("Content-Type", "application/json")
status, err := h.service.Status(r.Context())
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if err := json.NewEncoder(w).Encode(status); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
}
func New(service domain.Service) domain.RestHandler {
return &RestHandler{
service: service,
}
}

View File

@@ -0,0 +1,69 @@
package service
import (
"context"
"sync"
"github.com/marcopeocchi/yt-dlp-web-ui/v3/server/rest"
"github.com/marcopeocchi/yt-dlp-web-ui/v3/server/status/domain"
)
type Service struct {
repository domain.Repository
utilityService *rest.Service
}
// Version implements domain.Status.
func (s *Service) Status(ctx context.Context) (*domain.Status, error) {
// rpcVersion, downloaderVersion, err := s.utilityService.GetVersion(ctx)
// if err != nil {
// return nil, err
// }
var (
wg sync.WaitGroup
pending int
downloading int
completed int
speed int64
// version = fmt.Sprintf("RPC: %s yt-dlp: %s", rpcVersion, downloaderVersion)
)
wg.Add(4)
go func() {
pending = s.repository.Pending(ctx)
wg.Done()
}()
go func() {
downloading = s.repository.Downloading(ctx)
wg.Done()
}()
go func() {
completed = s.repository.Completed(ctx)
wg.Done()
}()
go func() {
speed = s.repository.DownloadSpeed(ctx)
wg.Done()
}()
wg.Wait()
return &domain.Status{
Downloading: downloading,
Pending: pending,
Completed: completed,
DownloadSpeed: int(speed),
}, nil
}
func New(repository domain.Repository, utilityService *rest.Service) domain.Service {
return &Service{
repository: repository,
utilityService: utilityService,
}
}

21
server/status/status.go Normal file
View File

@@ -0,0 +1,21 @@
package status
import (
"github.com/go-chi/chi/v5"
"github.com/marcopeocchi/yt-dlp-web-ui/v3/server/internal"
"github.com/marcopeocchi/yt-dlp-web-ui/v3/server/status/repository"
"github.com/marcopeocchi/yt-dlp-web-ui/v3/server/status/rest"
"github.com/marcopeocchi/yt-dlp-web-ui/v3/server/status/service"
)
func ApplyRouter(mdb *internal.MemoryDB) func(chi.Router) {
var (
r = repository.New(mdb)
s = service.New(r, nil) //TODO: nil, wtf?
h = rest.New(s)
)
return func(r chi.Router) {
r.Get("/", h.Status())
}
}