Skip to content

Commit

Permalink
added status API endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
marcopiovanello committed Dec 19, 2024
1 parent 17fb608 commit f9e829d
Show file tree
Hide file tree
Showing 8 changed files with 230 additions and 5 deletions.
2 changes: 1 addition & 1 deletion server/formats/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
}
8 changes: 4 additions & 4 deletions server/internal/common_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
Expand Down
4 changes: 4 additions & 0 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand Down Expand Up @@ -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}
}

Expand Down
28 changes: 28 additions & 0 deletions server/status/domain/status.go
Original file line number Diff line number Diff line change
@@ -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
}
65 changes: 65 additions & 0 deletions server/status/repository/repository.go
Original file line number Diff line number Diff line change
@@ -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,
}
}
38 changes: 38 additions & 0 deletions server/status/rest/handler.go
Original file line number Diff line number Diff line change
@@ -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,
}
}
69 changes: 69 additions & 0 deletions server/status/service/service.go
Original file line number Diff line number Diff line change
@@ -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 changes: 21 additions & 0 deletions server/status/status.go
Original file line number Diff line number Diff line change
@@ -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())
}
}

0 comments on commit f9e829d

Please sign in to comment.