0.2.68
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/ponzischeme89/memby/server/internal/credits"
|
||||
"github.com/ponzischeme89/memby/server/internal/store"
|
||||
)
|
||||
|
||||
type adminCreditsSettings struct {
|
||||
CandidateLimit int `json:"candidateLimit"`
|
||||
PrefetchEpisodes int `json:"prefetchEpisodes"`
|
||||
MaxPrefetch int `json:"maxPrefetch"`
|
||||
RetryHours int `json:"retryHours"`
|
||||
}
|
||||
|
||||
type adminCreditsCandidate struct {
|
||||
ItemID string `json:"itemId"`
|
||||
SeriesID string `json:"seriesId"`
|
||||
Season int `json:"season"`
|
||||
Episode int `json:"episode"`
|
||||
Priority int `json:"priority"`
|
||||
Reason string `json:"reason"`
|
||||
UserCount int `json:"userCount"`
|
||||
LastViewed time.Time `json:"lastViewed"`
|
||||
}
|
||||
|
||||
type adminCreditsResponse struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
Settings adminCreditsSettings `json:"settings"`
|
||||
QueueDepth int `json:"queueDepth"`
|
||||
Pending []adminCreditsCandidate `json:"pending"`
|
||||
History []store.CreditsScanHistoryRow `json:"history"`
|
||||
}
|
||||
|
||||
func creditsAdminSettings(cfg credits.Config) adminCreditsSettings {
|
||||
cfg = credits.NormaliseConfig(cfg)
|
||||
return adminCreditsSettings{
|
||||
CandidateLimit: cfg.QueueLimit, PrefetchEpisodes: cfg.PrefetchEpisodes,
|
||||
MaxPrefetch: cfg.MaxPrefetchEpisodes,
|
||||
RetryHours: int(cfg.RetryCooldown / time.Hour),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) defaultCreditsConfig() credits.Config {
|
||||
defaults := credits.DefaultConfig()
|
||||
defaults.PrefetchEpisodes = s.cfg.CreditsPrefetchEpisodes
|
||||
defaults.MaxPrefetchEpisodes = s.cfg.CreditsMaxPrefetch
|
||||
defaults.QueueLimit = s.cfg.CreditsQueueLimit
|
||||
return credits.NormaliseConfig(defaults)
|
||||
}
|
||||
|
||||
func (s *Server) handleAdminCredits(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodPut {
|
||||
s.handleAdminCreditsSettings(w, r)
|
||||
return
|
||||
}
|
||||
s.writeAdminCredits(w, r)
|
||||
}
|
||||
|
||||
func (s *Server) writeAdminCredits(w http.ResponseWriter, r *http.Request) {
|
||||
cfg := s.defaultCreditsConfig()
|
||||
pending := []adminCreditsCandidate{}
|
||||
queueDepth := 0
|
||||
if s.credits != nil {
|
||||
cfg = s.credits.Configuration()
|
||||
queueDepth = s.credits.QueueDepth()
|
||||
for _, candidate := range s.credits.Pending() {
|
||||
pending = append(pending, adminCreditsCandidate{
|
||||
ItemID: candidate.ItemID, SeriesID: candidate.SeriesID,
|
||||
Season: candidate.Season, Episode: candidate.Episode,
|
||||
Priority: candidate.Priority, Reason: candidate.Reason,
|
||||
UserCount: candidate.UserCount, LastViewed: candidate.LastViewed,
|
||||
})
|
||||
}
|
||||
} else if saved, found, err := s.store.CreditsSettings(r.Context()); err == nil && found {
|
||||
cfg.PrefetchEpisodes = saved.PrefetchEpisodes
|
||||
cfg.MaxPrefetchEpisodes = saved.MaxPrefetch
|
||||
cfg.QueueLimit = saved.CandidateLimit
|
||||
cfg.RetryCooldown = time.Duration(saved.RetryHours) * time.Hour
|
||||
cfg = credits.NormaliseConfig(cfg)
|
||||
}
|
||||
history, err := s.store.CreditsScanHistory(
|
||||
r.Context(), queryInt(r, "limit", 100, 500),
|
||||
)
|
||||
if err != nil {
|
||||
s.loggerFor(r.Context()).Warn("credits scan history read failed", "error", err)
|
||||
history = []store.CreditsScanHistoryRow{}
|
||||
}
|
||||
w.Header().Set("Cache-Control", "no-store")
|
||||
writeJSON(w, http.StatusOK, adminCreditsResponse{
|
||||
Enabled: s.credits != nil, Settings: creditsAdminSettings(cfg),
|
||||
QueueDepth: queueDepth, Pending: pending, History: history,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Server) handleAdminCreditsSettings(w http.ResponseWriter, r *http.Request) {
|
||||
var req adminCreditsSettings
|
||||
if err := json.NewDecoder(http.MaxBytesReader(w, r.Body, 4<<10)).Decode(&req); err != nil {
|
||||
writeError(w, http.StatusBadRequest, "malformed request body")
|
||||
return
|
||||
}
|
||||
if req.CandidateLimit < 1 || req.CandidateLimit > 100 {
|
||||
writeError(w, http.StatusBadRequest, "candidate limit must be between 1 and 100")
|
||||
return
|
||||
}
|
||||
if req.PrefetchEpisodes < 1 || req.PrefetchEpisodes > 10 {
|
||||
writeError(w, http.StatusBadRequest, "ordinary look-ahead must be between 1 and 10 episodes")
|
||||
return
|
||||
}
|
||||
if req.MaxPrefetch < req.PrefetchEpisodes || req.MaxPrefetch > 20 {
|
||||
writeError(w, http.StatusBadRequest, "maximum look-ahead must be at least the ordinary look-ahead and no more than 20")
|
||||
return
|
||||
}
|
||||
if req.RetryHours < 0 || req.RetryHours > 24*30 {
|
||||
writeError(w, http.StatusBadRequest, "retry delay must be between 0 and 720 hours")
|
||||
return
|
||||
}
|
||||
settings := store.CreditsSettings{
|
||||
CandidateLimit: req.CandidateLimit, PrefetchEpisodes: req.PrefetchEpisodes,
|
||||
MaxPrefetch: req.MaxPrefetch, RetryHours: req.RetryHours,
|
||||
}
|
||||
if err := s.store.SetCreditsSettings(r.Context(), settings); err != nil {
|
||||
writeError(w, http.StatusInternalServerError, "could not save credits settings")
|
||||
return
|
||||
}
|
||||
if s.credits != nil {
|
||||
cfg := s.credits.Configuration()
|
||||
cfg.QueueLimit = req.CandidateLimit
|
||||
cfg.PrefetchEpisodes = req.PrefetchEpisodes
|
||||
cfg.MaxPrefetchEpisodes = req.MaxPrefetch
|
||||
cfg.RetryCooldown = time.Duration(req.RetryHours) * time.Hour
|
||||
s.credits.Configure(cfg)
|
||||
}
|
||||
s.loggerFor(r.Context()).Info("credits detection settings changed",
|
||||
"candidate_limit", req.CandidateLimit, "prefetch", req.PrefetchEpisodes,
|
||||
"max_prefetch", req.MaxPrefetch, "retry_hours", req.RetryHours)
|
||||
s.writeAdminCredits(w, r)
|
||||
}
|
||||
Reference in New Issue
Block a user