This commit is contained in:
ponzischeme89
2026-08-19 06:57:59 +12:00
parent 8c847c59b8
commit 2b43b9ef12
94 changed files with 6359 additions and 778 deletions
+19 -2
View File
@@ -33,6 +33,7 @@ import (
"github.com/ponzischeme89/memby/server/internal/integrations"
serverlogging "github.com/ponzischeme89/memby/server/internal/logging"
"github.com/ponzischeme89/memby/server/internal/mdblist"
"github.com/ponzischeme89/memby/server/internal/notify"
"github.com/ponzischeme89/memby/server/internal/opensubtitles"
"github.com/ponzischeme89/memby/server/internal/radarr"
"github.com/ponzischeme89/memby/server/internal/recommend"
@@ -71,7 +72,11 @@ type Server struct {
adminEvents *adminevents.Bus
scheduler *scheduler.Scheduler
integrations *integrations.Dispatcher
sonarrMu sync.Mutex
// notify is the one door every outbound notification leaves through, and the only
// thing that writes the notification log. Producers never call a delivery provider
// directly any more — see internal/api/notifications.go.
notify *notify.Service
sonarrMu sync.Mutex
// sonarrSeriesMu guards the catalogue cache separately from the calendar's, so an add
// to My Shows never waits behind a launcher rebuilding the schedule row.
sonarrSeriesMu sync.Mutex
@@ -143,6 +148,10 @@ type Deps struct {
AdminEvents *adminevents.Bus
Scheduler *scheduler.Scheduler
Integrations *integrations.Dispatcher
// Notify is optional. A server built without one still delivers every notification —
// Send falls through to the providers regardless — it simply records nothing, which is
// what every unit test in this package wants.
Notify *notify.Service
// LogLevel is the live level of the process's own logger, so the console can turn
// debug on and watch the thing it turned it on for. Nil is allowed and means the
// level is fixed at whatever the container was started with.
@@ -150,7 +159,7 @@ type Deps struct {
}
func New(cfg config.Config, deps Deps) *Server {
return &Server{
server := &Server{
cfg: cfg,
emby: deps.Emby,
store: deps.Store,
@@ -172,9 +181,16 @@ func New(cfg config.Config, deps Deps) *Server {
scheduler: deps.Scheduler,
integrations: deps.Integrations,
notify: deps.Notify,
logLevel: deps.LogLevel,
deployedLogLevel: deployedLevel(deps.LogLevel),
}
// The providers are installed here rather than by the caller so a producer can assume
// the channels it uses exist: a channel with no provider is a configuration fault the
// audit trail would faithfully record on every single notification.
server.registerNotifiers()
return server
}
func deployedLevel(level *slog.LevelVar) slog.Level {
@@ -292,6 +308,7 @@ func (s *Server) Routes() http.Handler {
// token arrives in the query string, the way artwork's does, because a media player
// fetching a sidecar sends none of Memby's headers.
v1.Handle("GET /v1/subtitles/{file}", s.authed(s.handleStoredSubtitle))
v1.Handle("GET /v1/radarr/movies/{id}", s.authed(s.handleRadarrMovie))
v1.Handle("GET /v1/items/{id}/trailer", s.authed(s.handleTrailer))
v1.Handle("GET /v1/items/{id}/trailers", s.authed(s.handleTrailers))
v1.Handle("POST /v1/items/{id}/trailers/resolve", s.authed(s.handleResolveTrailer))