fix(lidarr): send the artist add's monitor choice in addOptions (#5239)
release / govulncheck (push) Successful in 29s
release / web (push) Successful in 1m58s
release / go (push) Successful in 2m14s
release / integration (push) Successful in 5m17s
release / android (push) Successful in 6m21s
release / Build signed APK (releases and dev) (push) Successful in 6m38s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 2m1s
release / Verify release artifacts (tag releases only) (push) Skipped
release / govulncheck (push) Successful in 29s
release / web (push) Successful in 1m58s
release / go (push) Successful in 2m14s
release / integration (push) Successful in 5m17s
release / android (push) Successful in 6m21s
release / Build signed APK (releases and dev) (push) Successful in 6m38s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 2m1s
release / Verify release artifacts (tag releases only) (push) Skipped
ArtistResource has no top-level `monitor`. Lidarr reads the choice from AddOptions (AddArtistOptions, a MonitoringOptions), so the "all"/"future" we sent there was dropped on deserialisation. AddOptions.Monitor stayed Unknown, and AlbumMonitoredService.SetAlbumMonitoredStatus returns early on Unknown. The request's monitoring was never applied. Send monitor and monitored inside addOptions with searchForMissingAlbums, the shape Lidarr's getNewArtist.js posts, and set monitorNewItems "all" explicitly: both choices mean new releases are watched. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -274,13 +274,20 @@ func (c *Client) LookupTrack(ctx context.Context, term string) ([]LookupResult,
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddArtist posts to POST /api/v1/artist. MonitorAll=true sends monitor="all";
|
// AddArtist posts to POST /api/v1/artist. MonitorAll=true monitors every
|
||||||
// false sends "future". Returns nil on 2xx; typed error otherwise.
|
// album ("all"); false monitors only releases from now on ("future"). New
|
||||||
|
// releases are monitored either way. Returns nil on 2xx; typed error
|
||||||
|
// otherwise.
|
||||||
//
|
//
|
||||||
// All four of artistName, foreignArtistId, qualityProfileId, and
|
// All four of artistName, foreignArtistId, qualityProfileId, and
|
||||||
// metadataProfileId are required by Lidarr. Omitting any one produces a
|
// metadataProfileId are required by Lidarr. Omitting any one produces a
|
||||||
// 400 with field-level validation messages (e.g. "'Metadata Profile Id'
|
// 400 with field-level validation messages (e.g. "'Metadata Profile Id'
|
||||||
// must be greater than '0'").
|
// must be greater than '0'").
|
||||||
|
//
|
||||||
|
// The monitor choice belongs in addOptions (AddArtistOptions, a
|
||||||
|
// MonitoringOptions). ArtistResource has no top-level `monitor`, so a
|
||||||
|
// choice sent there is dropped, AddOptions.Monitor stays Unknown and
|
||||||
|
// Lidarr skips applying it (#5239).
|
||||||
func (c *Client) AddArtist(ctx context.Context, p AddArtistParams) error {
|
func (c *Client) AddArtist(ctx context.Context, p AddArtistParams) error {
|
||||||
monitor := "future"
|
monitor := "future"
|
||||||
if p.MonitorAll {
|
if p.MonitorAll {
|
||||||
@@ -293,8 +300,12 @@ func (c *Client) AddArtist(ctx context.Context, p AddArtistParams) error {
|
|||||||
"metadataProfileId": p.MetadataProfileID,
|
"metadataProfileId": p.MetadataProfileID,
|
||||||
"rootFolderPath": p.RootFolderPath,
|
"rootFolderPath": p.RootFolderPath,
|
||||||
"monitored": true,
|
"monitored": true,
|
||||||
"monitor": monitor,
|
"monitorNewItems": "all",
|
||||||
"addOptions": map[string]any{"searchForMissingAlbums": true},
|
"addOptions": map[string]any{
|
||||||
|
"monitor": monitor,
|
||||||
|
"monitored": true,
|
||||||
|
"searchForMissingAlbums": true,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%w: marshal: %v", ErrInvalidPayload, err)
|
return fmt.Errorf("%w: marshal: %v", ErrInvalidPayload, err)
|
||||||
|
|||||||
@@ -288,13 +288,24 @@ func TestAddArtist_PostsCorrectBody(t *testing.T) {
|
|||||||
if decoded["monitored"] != true {
|
if decoded["monitored"] != true {
|
||||||
t.Errorf("monitored = %v, want true", decoded["monitored"])
|
t.Errorf("monitored = %v, want true", decoded["monitored"])
|
||||||
}
|
}
|
||||||
if decoded["monitor"] != "all" {
|
if decoded["monitorNewItems"] != "all" {
|
||||||
t.Errorf("monitor = %v, want all (MonitorAll=true)", decoded["monitor"])
|
t.Errorf("monitorNewItems = %v, want all", decoded["monitorNewItems"])
|
||||||
|
}
|
||||||
|
// #5239: ArtistResource has no top-level monitor; Lidarr reads the
|
||||||
|
// choice from addOptions and silently drops it anywhere else.
|
||||||
|
if _, set := decoded["monitor"]; set {
|
||||||
|
t.Errorf("monitor sent at top level (%v), where Lidarr ignores it", decoded["monitor"])
|
||||||
}
|
}
|
||||||
opts, ok := decoded["addOptions"].(map[string]any)
|
opts, ok := decoded["addOptions"].(map[string]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("addOptions missing or wrong type: %T", decoded["addOptions"])
|
t.Fatalf("addOptions missing or wrong type: %T", decoded["addOptions"])
|
||||||
}
|
}
|
||||||
|
if opts["monitor"] != "all" {
|
||||||
|
t.Errorf("addOptions.monitor = %v, want all (MonitorAll=true)", opts["monitor"])
|
||||||
|
}
|
||||||
|
if opts["monitored"] != true {
|
||||||
|
t.Errorf("addOptions.monitored = %v, want true", opts["monitored"])
|
||||||
|
}
|
||||||
if opts["searchForMissingAlbums"] != true {
|
if opts["searchForMissingAlbums"] != true {
|
||||||
t.Errorf("addOptions.searchForMissingAlbums = %v, want true", opts["searchForMissingAlbums"])
|
t.Errorf("addOptions.searchForMissingAlbums = %v, want true", opts["searchForMissingAlbums"])
|
||||||
}
|
}
|
||||||
@@ -309,8 +320,8 @@ func TestAddArtist_MonitorFuture(t *testing.T) {
|
|||||||
defer srv.Close()
|
defer srv.Close()
|
||||||
|
|
||||||
_ = c.AddArtist(context.Background(), AddArtistParams{MonitorAll: false})
|
_ = c.AddArtist(context.Background(), AddArtistParams{MonitorAll: false})
|
||||||
if decoded["monitor"] != "future" {
|
if opts, _ := decoded["addOptions"].(map[string]any); opts["monitor"] != "future" {
|
||||||
t.Errorf("monitor = %v, want future (MonitorAll=false)", decoded["monitor"])
|
t.Errorf("addOptions.monitor = %v, want future (MonitorAll=false)", opts["monitor"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ type AddArtistParams struct {
|
|||||||
QualityProfileID int
|
QualityProfileID int
|
||||||
MetadataProfileID int
|
MetadataProfileID int
|
||||||
RootFolderPath string
|
RootFolderPath string
|
||||||
MonitorAll bool // true => monitor="all"; false => "future"
|
MonitorAll bool // true => addOptions.monitor="all"; false => "future"
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddAlbumParams identify the album to add and carry the settings Lidarr
|
// AddAlbumParams identify the album to add and carry the settings Lidarr
|
||||||
|
|||||||
Reference in New Issue
Block a user