0.2.63 update

This commit is contained in:
ponzischeme89
2026-08-14 11:47:32 +12:00
parent 9a8ecbdceb
commit 06b6490ac9
41 changed files with 921 additions and 179 deletions
+98
View File
@@ -22,6 +22,55 @@ const RequestPolicyKey = "request_policy"
// may ask; this policy answers the safe, household-wide way a TV request is created.
const SonarrRequestPolicyKey = "sonarr_request_policy"
const RadarrRequestPolicyKey = "radarr_request_policy"
const ArrIntegrationPolicyKey = "arr_integration_policy"
// ArrIntegrationPolicy lets the operator stop either *arr integration without removing
// credentials or request policy. Both start enabled for existing households.
type ArrIntegrationPolicy struct {
SonarrEnabled bool `json:"sonarrEnabled"`
RadarrEnabled bool `json:"radarrEnabled"`
UpdatedAt time.Time `json:"updatedAt"`
}
func DefaultArrIntegrationPolicy() ArrIntegrationPolicy {
return ArrIntegrationPolicy{SonarrEnabled: true, RadarrEnabled: true}
}
func (s *Store) ArrIntegrationPolicy(ctx context.Context) (ArrIntegrationPolicy, error) {
var raw []byte
err := s.pool.QueryRow(ctx, `SELECT value FROM app_settings WHERE key = $1`, ArrIntegrationPolicyKey).Scan(&raw)
if errors.Is(err, pgx.ErrNoRows) {
return DefaultArrIntegrationPolicy(), nil
}
if err != nil {
return DefaultArrIntegrationPolicy(), fmt.Errorf("store: read arr integration policy: %w", err)
}
var policy ArrIntegrationPolicy
if err := json.Unmarshal(raw, &policy); err != nil {
return DefaultArrIntegrationPolicy(), fmt.Errorf("store: decode arr integration policy: %w", err)
}
return policy, nil
}
func (s *Store) SetArrIntegrationPolicy(ctx context.Context, policy ArrIntegrationPolicy) error {
policy.UpdatedAt = time.Now().UTC()
raw, err := json.Marshal(policy)
if err != nil {
return err
}
_, err = s.pool.Exec(ctx, `
INSERT INTO app_settings (key, value, updated_at)
VALUES ($1, $2::jsonb, now())
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = now()`,
ArrIntegrationPolicyKey, string(raw))
if err != nil {
return fmt.Errorf("store: write arr integration policy: %w", err)
}
return nil
}
// PlaybackPolicyKey controls presentation behaviour that should be adjustable without
// shipping a new TV build.
const PlaybackPolicyKey = "playback_policy"
@@ -433,6 +482,55 @@ func (s *Store) SetSonarrRequestPolicy(ctx context.Context, policy SonarrRequest
return nil
}
// RadarrRequestPolicy is the movie equivalent of SonarrRequestPolicy. It persists the
// stable profile id so a renamed or removed profile becomes a safe configuration error.
type RadarrRequestPolicy struct {
QualityProfileID int `json:"qualityProfileId"`
SearchImmediately bool `json:"searchImmediately"`
UpdatedAt time.Time `json:"updatedAt"`
}
func DefaultRadarrRequestPolicy() RadarrRequestPolicy { return RadarrRequestPolicy{} }
func (s *Store) RadarrRequestPolicy(ctx context.Context) (RadarrRequestPolicy, error) {
var raw []byte
err := s.pool.QueryRow(ctx, `SELECT value FROM app_settings WHERE key = $1`, RadarrRequestPolicyKey).Scan(&raw)
if errors.Is(err, pgx.ErrNoRows) {
return DefaultRadarrRequestPolicy(), nil
}
if err != nil {
return DefaultRadarrRequestPolicy(), fmt.Errorf("store: read Radarr request policy: %w", err)
}
var policy RadarrRequestPolicy
if err := json.Unmarshal(raw, &policy); err != nil {
return DefaultRadarrRequestPolicy(), fmt.Errorf("store: decode Radarr request policy: %w", err)
}
if policy.QualityProfileID < 0 {
policy.QualityProfileID = 0
}
return policy, nil
}
func (s *Store) SetRadarrRequestPolicy(ctx context.Context, policy RadarrRequestPolicy) error {
if policy.QualityProfileID <= 0 {
return fmt.Errorf("store: Radarr request quality profile is required")
}
policy.UpdatedAt = time.Now().UTC()
raw, err := json.Marshal(policy)
if err != nil {
return err
}
_, err = s.pool.Exec(ctx, `
INSERT INTO app_settings (key, value, updated_at)
VALUES ($1, $2::jsonb, now())
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = now()`,
RadarrRequestPolicyKey, string(raw))
if err != nil {
return fmt.Errorf("store: write Radarr request policy: %w", err)
}
return nil
}
func (p RequestPolicy) Allows(userID string) bool {
for _, allowed := range p.AllowedUserIDs {
if allowed == userID {