Lidarr: album adds that Lidarr accepts, artist monitoring that sticks #138
@@ -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