feat: add edit artist endpoint (section 1.4)
- Add GET/PUT /api/artists/{id} for artist settings
- Update sync to create artists table entry (library settings)
- Support partial updates for monitored, path, quality/metadata profiles
- Add e2e tests for get, edit, partial update flows
This commit is contained in:
+141
-13
@@ -251,19 +251,6 @@ func (db *DB) CountAlbums(ctx context.Context) (int64, error) {
|
||||
return count, err
|
||||
}
|
||||
|
||||
func (db *DB) GetArtistByForeignID(ctx context.Context, foreignArtistID string) (*ArtistMetadataRow, error) {
|
||||
var a ArtistMetadataRow
|
||||
err := db.pool.QueryRow(ctx, `
|
||||
SELECT id, foreign_artist_id, name, sort_name, artist_type, genres, created_at, updated_at
|
||||
FROM artist_metadata
|
||||
WHERE foreign_artist_id = $1
|
||||
`, foreignArtistID).Scan(&a.ID, &a.ForeignArtistID, &a.Name, &a.SortName, &a.ArtistType, &a.Genres, &a.CreatedAt, &a.UpdatedAt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &a, nil
|
||||
}
|
||||
|
||||
func (db *DB) CountAlbumsByArtist(ctx context.Context, artistMetadataID uuid.UUID) (int64, error) {
|
||||
var count int64
|
||||
err := db.pool.QueryRow(ctx, `
|
||||
@@ -288,3 +275,144 @@ func (db *DB) DeleteArtistByForeignID(ctx context.Context, foreignArtistID strin
|
||||
}
|
||||
return result.RowsAffected() > 0, nil
|
||||
}
|
||||
|
||||
type ArtistRow struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
MetadataID uuid.UUID `json:"metadata_id"`
|
||||
ForeignArtistID string `json:"foreign_artist_id"`
|
||||
Name string `json:"name"`
|
||||
QualityProfileID *uuid.UUID `json:"quality_profile_id"`
|
||||
MetadataProfileID *uuid.UUID `json:"metadata_profile_id"`
|
||||
RootFolderID *uuid.UUID `json:"root_folder_id"`
|
||||
Path *string `json:"path"`
|
||||
Monitored bool `json:"monitored"`
|
||||
MonitorNewItems string `json:"monitor_new_items"`
|
||||
}
|
||||
|
||||
func (db *DB) UpsertArtist(ctx context.Context, metadataID uuid.UUID) (uuid.UUID, error) {
|
||||
var existingID uuid.UUID
|
||||
err := db.pool.QueryRow(ctx, `
|
||||
SELECT id FROM artists WHERE metadata_id = $1
|
||||
`, metadataID).Scan(&existingID)
|
||||
if err == nil {
|
||||
return existingID, nil
|
||||
}
|
||||
|
||||
var resultID uuid.UUID
|
||||
err = db.pool.QueryRow(ctx, `
|
||||
INSERT INTO artists (metadata_id, monitored, monitor_new_items)
|
||||
VALUES ($1, true, 'all')
|
||||
RETURNING id
|
||||
`, metadataID).Scan(&resultID)
|
||||
return resultID, err
|
||||
}
|
||||
|
||||
func (db *DB) GetArtistByForeignID(ctx context.Context, foreignArtistID string) (*ArtistRow, error) {
|
||||
var a ArtistRow
|
||||
err := db.pool.QueryRow(ctx, `
|
||||
SELECT a.id, a.metadata_id, am.foreign_artist_id, am.name,
|
||||
a.quality_profile_id, a.metadata_profile_id, a.root_folder_id,
|
||||
a.path, a.monitored, a.monitor_new_items
|
||||
FROM artists a
|
||||
JOIN artist_metadata am ON a.metadata_id = am.id
|
||||
WHERE am.foreign_artist_id = $1
|
||||
`, foreignArtistID).Scan(
|
||||
&a.ID, &a.MetadataID, &a.ForeignArtistID, &a.Name,
|
||||
&a.QualityProfileID, &a.MetadataProfileID, &a.RootFolderID,
|
||||
&a.Path, &a.Monitored, &a.MonitorNewItems,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &a, nil
|
||||
}
|
||||
|
||||
type ArtistUpdate struct {
|
||||
QualityProfileID *string `json:"quality_profile_id"`
|
||||
MetadataProfileID *string `json:"metadata_profile_id"`
|
||||
RootFolderID *string `json:"root_folder_id"`
|
||||
Path *string `json:"path"`
|
||||
Monitored *bool `json:"monitored"`
|
||||
MonitorNewItems *string `json:"monitor_new_items"`
|
||||
}
|
||||
|
||||
func (db *DB) UpdateArtistByForeignID(ctx context.Context, foreignArtistID string, update ArtistUpdate) (*ArtistRow, error) {
|
||||
metadataRow, err := db.GetArtistMetadataByForeignID(ctx, foreignArtistID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if update.Monitored != nil {
|
||||
_, err = db.pool.Exec(ctx, `
|
||||
UPDATE artists SET monitored = $1 WHERE metadata_id = $2
|
||||
`, *update.Monitored, metadataRow.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if update.Path != nil {
|
||||
_, err = db.pool.Exec(ctx, `
|
||||
UPDATE artists SET path = $1 WHERE metadata_id = $2
|
||||
`, *update.Path, metadataRow.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if update.QualityProfileID != nil {
|
||||
var qpID *uuid.UUID
|
||||
if *update.QualityProfileID != "" {
|
||||
parsed, err := uuid.Parse(*update.QualityProfileID)
|
||||
if err == nil {
|
||||
qpID = &parsed
|
||||
}
|
||||
}
|
||||
_, err = db.pool.Exec(ctx, `
|
||||
UPDATE artists SET quality_profile_id = $1 WHERE metadata_id = $2
|
||||
`, qpID, metadataRow.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if update.RootFolderID != nil {
|
||||
var rfID *uuid.UUID
|
||||
if *update.RootFolderID != "" {
|
||||
parsed, err := uuid.Parse(*update.RootFolderID)
|
||||
if err == nil {
|
||||
rfID = &parsed
|
||||
}
|
||||
}
|
||||
_, err = db.pool.Exec(ctx, `
|
||||
UPDATE artists SET root_folder_id = $1 WHERE metadata_id = $2
|
||||
`, rfID, metadataRow.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if update.MonitorNewItems != nil {
|
||||
_, err = db.pool.Exec(ctx, `
|
||||
UPDATE artists SET monitor_new_items = $1 WHERE metadata_id = $2
|
||||
`, *update.MonitorNewItems, metadataRow.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return db.GetArtistByForeignID(ctx, foreignArtistID)
|
||||
}
|
||||
|
||||
func (db *DB) GetArtistMetadataByForeignID(ctx context.Context, foreignArtistID string) (*ArtistMetadataRow, error) {
|
||||
var a ArtistMetadataRow
|
||||
err := db.pool.QueryRow(ctx, `
|
||||
SELECT id, foreign_artist_id, name, sort_name, artist_type, genres, created_at, updated_at
|
||||
FROM artist_metadata
|
||||
WHERE foreign_artist_id = $1
|
||||
`, foreignArtistID).Scan(&a.ID, &a.ForeignArtistID, &a.Name, &a.SortName, &a.ArtistType, &a.Genres, &a.CreatedAt, &a.UpdatedAt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &a, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user