Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions graphql/schema/types/filters.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,8 @@ input StudioFilterType {
created_at: TimestampCriterionInput
"Filter by last update time"
updated_at: TimestampCriterionInput

custom_fields: [CustomFieldCriterionInput!]
}

input GalleryFilterType {
Expand Down
6 changes: 6 additions & 0 deletions graphql/schema/types/studio.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ type Studio {
updated_at: Time!
groups: [Group!]!
movies: [Movie!]! @deprecated(reason: "use groups instead")

custom_fields: Map!
}

input StudioCreateInput {
Expand All @@ -40,6 +42,8 @@ input StudioCreateInput {
aliases: [String!]
tag_ids: [ID!]
ignore_auto_tag: Boolean

custom_fields: Map
}

input StudioUpdateInput {
Expand All @@ -57,6 +61,8 @@ input StudioUpdateInput {
aliases: [String!]
tag_ids: [ID!]
ignore_auto_tag: Boolean

custom_fields: CustomFieldsInput
}

input StudioDestroyInput {
Expand Down
21 changes: 20 additions & 1 deletion internal/api/loaders/dataloaders.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ type Loaders struct {
PerformerByID *PerformerLoader
PerformerCustomFields *CustomFieldsLoader

StudioByID *StudioLoader
StudioByID *StudioLoader
StudioCustomFields *CustomFieldsLoader

TagByID *TagLoader
GroupByID *GroupLoader
FileByID *FileLoader
Expand Down Expand Up @@ -99,6 +101,11 @@ func (m Middleware) Middleware(next http.Handler) http.Handler {
maxBatch: maxBatch,
fetch: m.fetchPerformerCustomFields(ctx),
},
StudioCustomFields: &CustomFieldsLoader{
wait: wait,
maxBatch: maxBatch,
fetch: m.fetchStudioCustomFields(ctx),
},
StudioByID: &StudioLoader{
wait: wait,
maxBatch: maxBatch,
Expand Down Expand Up @@ -253,6 +260,18 @@ func (m Middleware) fetchStudios(ctx context.Context) func(keys []int) ([]*model
}
}

func (m Middleware) fetchStudioCustomFields(ctx context.Context) func(keys []int) ([]models.CustomFieldMap, []error) {
return func(keys []int) (ret []models.CustomFieldMap, errs []error) {
err := m.Repository.WithDB(ctx, func(ctx context.Context) error {
var err error
ret, err = m.Repository.Studio.GetCustomFieldsBulk(ctx, keys)
return err
})

return ret, toErrorSlice(err)
}
}

func (m Middleware) fetchTags(ctx context.Context) func(keys []int) ([]*models.Tag, []error) {
return func(keys []int) (ret []*models.Tag, errs []error) {
err := m.Repository.WithDB(ctx, func(ctx context.Context) error {
Expand Down
13 changes: 13 additions & 0 deletions internal/api/resolver_model_studio.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,19 @@ func (r *studioResolver) Groups(ctx context.Context, obj *models.Studio) (ret []
return ret, nil
}

func (r *studioResolver) CustomFields(ctx context.Context, obj *models.Studio) (map[string]interface{}, error) {
m, err := loaders.From(ctx).StudioCustomFields.Load(obj.ID)
if err != nil {
return nil, err
}

if m == nil {
return make(map[string]interface{}), nil
}

return m, nil
}

// deprecated
func (r *studioResolver) Movies(ctx context.Context, obj *models.Studio) (ret []*models.Group, err error) {
return r.Groups(ctx, obj)
Expand Down
8 changes: 7 additions & 1 deletion internal/api/resolver_mutation_studio.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func (r *mutationResolver) StudioCreate(ctx context.Context, input models.Studio
}

// Populate a new studio from the input
newStudio := models.NewStudio()
newStudio := models.NewCreateStudioInput()

newStudio.Name = input.Name
newStudio.URL = translator.string(input.URL)
Expand All @@ -52,6 +52,7 @@ func (r *mutationResolver) StudioCreate(ctx context.Context, input models.Studio
if err != nil {
return nil, fmt.Errorf("converting tag ids: %w", err)
}
newStudio.CustomFields = convertMapJSONNumbers(input.CustomFields)

// Process the base 64 encoded image string
var imageData []byte
Expand Down Expand Up @@ -124,6 +125,11 @@ func (r *mutationResolver) StudioUpdate(ctx context.Context, input models.Studio
return nil, fmt.Errorf("converting tag ids: %w", err)
}

updatedStudio.CustomFields = input.CustomFields
// convert json.Numbers to int/float
updatedStudio.CustomFields.Full = convertMapJSONNumbers(updatedStudio.CustomFields.Full)
updatedStudio.CustomFields.Partial = convertMapJSONNumbers(updatedStudio.CustomFields.Partial)

// Process the base 64 encoded image string
var imageData []byte
imageIncluded := translator.hasField("image")
Expand Down
7 changes: 3 additions & 4 deletions internal/autotag/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,16 +101,15 @@ func createPerformer(ctx context.Context, pqb models.PerformerWriter) error {

func createStudio(ctx context.Context, qb models.StudioWriter, name string) (*models.Studio, error) {
// create the studio
studio := models.Studio{
Name: name,
}
studio := models.NewCreateStudioInput()
studio.Name = name

err := qb.Create(ctx, &studio)
if err != nil {
return nil, err
}

return &studio, nil
return studio.Studio, nil
}

func createTag(ctx context.Context, qb models.TagWriter) error {
Expand Down
2 changes: 1 addition & 1 deletion internal/identify/scene_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func Test_sceneRelationships_studio(t *testing.T) {
db := mocks.NewDatabase()

db.Studio.On("Create", testCtx, mock.Anything).Run(func(args mock.Arguments) {
s := args.Get(1).(*models.Studio)
s := args.Get(1).(*models.CreateStudioInput)
s.ID = validStoredIDInt
}).Return(nil)

Expand Down
6 changes: 3 additions & 3 deletions internal/identify/studio_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ func Test_createMissingStudio(t *testing.T) {

db := mocks.NewDatabase()

db.Studio.On("Create", testCtx, mock.MatchedBy(func(p *models.Studio) bool {
db.Studio.On("Create", testCtx, mock.MatchedBy(func(p *models.CreateStudioInput) bool {
return p.Name == validName
})).Run(func(args mock.Arguments) {
s := args.Get(1).(*models.Studio)
s := args.Get(1).(*models.CreateStudioInput)
s.ID = createdID
}).Return(nil)
db.Studio.On("Create", testCtx, mock.MatchedBy(func(p *models.Studio) bool {
db.Studio.On("Create", testCtx, mock.MatchedBy(func(p *models.CreateStudioInput) bool {
return p.Name == invalidName
})).Return(errors.New("error creating studio"))

Expand Down
2 changes: 1 addition & 1 deletion pkg/gallery/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ func (i *Importer) populateStudio(ctx context.Context) error {
}

func (i *Importer) createStudio(ctx context.Context, name string) (int, error) {
newStudio := models.NewStudio()
newStudio := models.NewCreateStudioInput()
newStudio.Name = name

err := i.StudioWriter.Create(ctx, &newStudio)
Expand Down
8 changes: 4 additions & 4 deletions pkg/gallery/import_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,9 @@ func TestImporterPreImportWithMissingStudio(t *testing.T) {
}

db.Studio.On("FindByName", testCtx, missingStudioName, false).Return(nil, nil).Times(3)
db.Studio.On("Create", testCtx, mock.AnythingOfType("*models.Studio")).Run(func(args mock.Arguments) {
s := args.Get(1).(*models.Studio)
s.ID = existingStudioID
db.Studio.On("Create", testCtx, mock.AnythingOfType("*models.CreateStudioInput")).Run(func(args mock.Arguments) {
s := args.Get(1).(*models.CreateStudioInput)
s.Studio.ID = existingStudioID
}).Return(nil)

err := i.PreImport(testCtx)
Expand Down Expand Up @@ -147,7 +147,7 @@ func TestImporterPreImportWithMissingStudioCreateErr(t *testing.T) {
}

db.Studio.On("FindByName", testCtx, missingStudioName, false).Return(nil, nil).Once()
db.Studio.On("Create", testCtx, mock.AnythingOfType("*models.Studio")).Return(errors.New("Create error"))
db.Studio.On("Create", testCtx, mock.AnythingOfType("*models.CreateStudioInput")).Return(errors.New("Create error"))

err := i.PreImport(testCtx)
assert.NotNil(t, err)
Expand Down
2 changes: 1 addition & 1 deletion pkg/group/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ func (i *Importer) populateStudio(ctx context.Context) error {
}

func (i *Importer) createStudio(ctx context.Context, name string) (int, error) {
newStudio := models.NewStudio()
newStudio := models.NewCreateStudioInput()
newStudio.Name = name

err := i.StudioWriter.Create(ctx, &newStudio)
Expand Down
8 changes: 4 additions & 4 deletions pkg/group/import_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ func TestImporterPreImportWithMissingStudio(t *testing.T) {
}

db.Studio.On("FindByName", testCtx, missingStudioName, false).Return(nil, nil).Times(3)
db.Studio.On("Create", testCtx, mock.AnythingOfType("*models.Studio")).Run(func(args mock.Arguments) {
s := args.Get(1).(*models.Studio)
s.ID = existingStudioID
db.Studio.On("Create", testCtx, mock.AnythingOfType("*models.CreateStudioInput")).Run(func(args mock.Arguments) {
s := args.Get(1).(*models.CreateStudioInput)
s.Studio.ID = existingStudioID
}).Return(nil)

err := i.PreImport(testCtx)
Expand Down Expand Up @@ -156,7 +156,7 @@ func TestImporterPreImportWithMissingStudioCreateErr(t *testing.T) {
}

db.Studio.On("FindByName", testCtx, missingStudioName, false).Return(nil, nil).Once()
db.Studio.On("Create", testCtx, mock.AnythingOfType("*models.Studio")).Return(errors.New("Create error"))
db.Studio.On("Create", testCtx, mock.AnythingOfType("*models.CreateStudioInput")).Return(errors.New("Create error"))

err := i.PreImport(testCtx)
assert.NotNil(t, err)
Expand Down
2 changes: 1 addition & 1 deletion pkg/image/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ func (i *Importer) populateStudio(ctx context.Context) error {
}

func (i *Importer) createStudio(ctx context.Context, name string) (int, error) {
newStudio := models.NewStudio()
newStudio := models.NewCreateStudioInput()
newStudio.Name = name

err := i.StudioWriter.Create(ctx, &newStudio)
Expand Down
8 changes: 4 additions & 4 deletions pkg/image/import_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ func TestImporterPreImportWithMissingStudio(t *testing.T) {
}

db.Studio.On("FindByName", testCtx, missingStudioName, false).Return(nil, nil).Times(3)
db.Studio.On("Create", testCtx, mock.AnythingOfType("*models.Studio")).Run(func(args mock.Arguments) {
s := args.Get(1).(*models.Studio)
s.ID = existingStudioID
db.Studio.On("Create", testCtx, mock.AnythingOfType("*models.CreateStudioInput")).Run(func(args mock.Arguments) {
s := args.Get(1).(*models.CreateStudioInput)
s.Studio.ID = existingStudioID
}).Return(nil)

err := i.PreImport(testCtx)
Expand Down Expand Up @@ -109,7 +109,7 @@ func TestImporterPreImportWithMissingStudioCreateErr(t *testing.T) {
}

db.Studio.On("FindByName", testCtx, missingStudioName, false).Return(nil, nil).Once()
db.Studio.On("Create", testCtx, mock.AnythingOfType("*models.Studio")).Return(errors.New("Create error"))
db.Studio.On("Create", testCtx, mock.AnythingOfType("*models.CreateStudioInput")).Return(errors.New("Create error"))

err := i.PreImport(testCtx)
assert.NotNil(t, err)
Expand Down
54 changes: 50 additions & 4 deletions pkg/models/mocks/StudioReaderWriter.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions pkg/models/model_scraped_item.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ type ScrapedStudio struct {

func (ScrapedStudio) IsScrapedContent() {}

func (s *ScrapedStudio) ToStudio(endpoint string, excluded map[string]bool) *Studio {
func (s *ScrapedStudio) ToStudio(endpoint string, excluded map[string]bool) *CreateStudioInput {
// Populate a new studio from the input
ret := NewStudio()
ret := NewCreateStudioInput()
ret.Name = s.Name

if s.RemoteSiteID != nil && endpoint != "" {
Expand Down
2 changes: 1 addition & 1 deletion pkg/models/model_scraped_item_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func Test_scrapedToStudioInput(t *testing.T) {
got.StashIDs.List()[stid].UpdatedAt = time.Time{}
}
}
assert.Equal(t, tt.want, got)
assert.Equal(t, tt.want, got.Studio)
})
}
}
Expand Down
Loading