package api import ( "context" "encoding/json" "net/http" "strings" "github.com/ponzischeme89/memby/server/internal/store" ) type sonarrProfileOption struct { ID int `json:"id"` Name string `json:"name"` Recommended bool `json:"recommended"` } type sonarrRequestAdminPolicy struct { QualityProfileID int `json:"qualityProfileId"` SearchImmediately bool `json:"searchImmediately"` Profiles []sonarrProfileOption `json:"profiles"` RecommendedID int `json:"recommendedId"` Configured bool `json:"configured"` Error string `json:"error,omitempty"` } func (s *Server) sonarrRequestAdminPolicy(ctx context.Context) sonarrRequestAdminPolicy { policy, err := s.store.SonarrRequestPolicy(ctx) if err != nil { return sonarrRequestAdminPolicy{Profiles: []sonarrProfileOption{}, Error: "Could not read the Sonarr request policy."} } result := sonarrRequestAdminPolicy{QualityProfileID: policy.QualityProfileID, SearchImmediately: policy.SearchImmediately, Profiles: []sonarrProfileOption{}} if s.sonarr == nil { result.Error = "Sonarr is not configured." return result } profiles, err := s.sonarr.QualityProfiles(ctx) if err != nil { result.Error = "Could not read Sonarr quality profiles." return result } for _, profile := range profiles { recommended := is720pProfile(profile.Name) if recommended && result.RecommendedID == 0 { result.RecommendedID = profile.ID } if profile.ID == policy.QualityProfileID { result.Configured = true } result.Profiles = append(result.Profiles, sonarrProfileOption{ID: profile.ID, Name: profile.Name, Recommended: recommended}) } if policy.QualityProfileID == 0 && result.RecommendedID != 0 { result.QualityProfileID = result.RecommendedID result.Configured = true } if !result.Configured && result.Error == "" { result.Error = "Choose an existing Sonarr quality profile before accepting TV requests." } return result } type sonarrRequestPolicyRequest struct { QualityProfileID int `json:"qualityProfileId"` SearchImmediately bool `json:"searchImmediately"` } func (s *Server) handleAdminSonarrRequestPolicy(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodGet { writeJSON(w, http.StatusOK, s.sonarrRequestAdminPolicy(r.Context())) return } if s.sonarr == nil { writeError(w, http.StatusServiceUnavailable, "Sonarr is not configured") return } var req sonarrRequestPolicyRequest 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.QualityProfileID <= 0 { writeError(w, http.StatusBadRequest, "choose a Sonarr quality profile") return } profiles, err := s.sonarr.QualityProfiles(r.Context()) if err != nil { writeError(w, http.StatusBadGateway, "could not validate Sonarr quality profiles") return } found := false for _, profile := range profiles { if profile.ID == req.QualityProfileID { found = true break } } if !found { writeError(w, http.StatusBadRequest, "the selected Sonarr quality profile no longer exists") return } if err := s.store.SetSonarrRequestPolicy(r.Context(), store.SonarrRequestPolicy{QualityProfileID: req.QualityProfileID, SearchImmediately: req.SearchImmediately}); err != nil { s.loggerFor(r.Context()).Error("Sonarr request policy write failed", "error", err) writeError(w, http.StatusInternalServerError, "could not save Sonarr request policy") return } s.loggerFor(r.Context()).Info("Sonarr request policy changed", "quality_profile_id", req.QualityProfileID, "search_immediately", req.SearchImmediately) writeJSON(w, http.StatusOK, s.sonarrRequestAdminPolicy(r.Context())) } func is720pProfile(name string) bool { return strings.EqualFold(strings.TrimSpace(name), "720p") }