added status API endpoint
This commit is contained in:
@@ -23,6 +23,6 @@ type Format struct {
|
|||||||
Resolution string `json:"resolution"`
|
Resolution string `json:"resolution"`
|
||||||
VCodec string `json:"vcodec"`
|
VCodec string `json:"vcodec"`
|
||||||
ACodec string `json:"acodec"`
|
ACodec string `json:"acodec"`
|
||||||
Size float32 `json:"filesize_approx"`
|
Size float64 `json:"filesize_approx"`
|
||||||
Language string `json:"language"`
|
Language string `json:"language"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import "time"
|
|||||||
// Used to unmarshall yt-dlp progress
|
// Used to unmarshall yt-dlp progress
|
||||||
type ProgressTemplate struct {
|
type ProgressTemplate struct {
|
||||||
Percentage string `json:"percentage"`
|
Percentage string `json:"percentage"`
|
||||||
Speed float32 `json:"speed"`
|
Speed float64 `json:"speed"`
|
||||||
Size string `json:"size"`
|
Size string `json:"size"`
|
||||||
Eta float32 `json:"eta"`
|
Eta float64 `json:"eta"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PostprocessTemplate struct {
|
type PostprocessTemplate struct {
|
||||||
@@ -25,8 +25,8 @@ type DownloadOutput struct {
|
|||||||
type DownloadProgress struct {
|
type DownloadProgress struct {
|
||||||
Status int `json:"process_status"`
|
Status int `json:"process_status"`
|
||||||
Percentage string `json:"percentage"`
|
Percentage string `json:"percentage"`
|
||||||
Speed float32 `json:"speed"`
|
Speed float64 `json:"speed"`
|
||||||
ETA float32 `json:"eta"`
|
ETA float64 `json:"eta"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used to deser the yt-dlp -J output
|
// Used to deser the yt-dlp -J output
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import (
|
|||||||
"github.com/marcopeocchi/yt-dlp-web-ui/v3/server/openid"
|
"github.com/marcopeocchi/yt-dlp-web-ui/v3/server/openid"
|
||||||
"github.com/marcopeocchi/yt-dlp-web-ui/v3/server/rest"
|
"github.com/marcopeocchi/yt-dlp-web-ui/v3/server/rest"
|
||||||
ytdlpRPC "github.com/marcopeocchi/yt-dlp-web-ui/v3/server/rpc"
|
ytdlpRPC "github.com/marcopeocchi/yt-dlp-web-ui/v3/server/rpc"
|
||||||
|
"github.com/marcopeocchi/yt-dlp-web-ui/v3/server/status"
|
||||||
|
|
||||||
_ "modernc.org/sqlite"
|
_ "modernc.org/sqlite"
|
||||||
)
|
)
|
||||||
@@ -221,6 +222,9 @@ func newServer(c serverConfig) *http.Server {
|
|||||||
// Logging
|
// Logging
|
||||||
r.Route("/log", logging.ApplyRouter(observableLogger))
|
r.Route("/log", logging.ApplyRouter(observableLogger))
|
||||||
|
|
||||||
|
// Status
|
||||||
|
r.Route("/status", status.ApplyRouter(c.mdb))
|
||||||
|
|
||||||
return &http.Server{Handler: r}
|
return &http.Server{Handler: r}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
28
server/status/domain/status.go
Normal file
28
server/status/domain/status.go
Normal 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
|
||||||
|
}
|
||||||
65
server/status/repository/repository.go
Normal file
65
server/status/repository/repository.go
Normal 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
38
server/status/rest/handler.go
Normal file
38
server/status/rest/handler.go
Normal 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
69
server/status/service/service.go
Normal file
69
server/status/service/service.go
Normal 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
21
server/status/status.go
Normal 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())
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user