Performer disambiguation and aliases (#3113)

* Refactor performer relationships
* Remove checksum from performer
* Add disambiguation, overhaul aliases
* Add disambiguation filter criterion
* Improve name matching during import
* Add disambiguation filtering in UI
* Include aliases in performer select
This commit is contained in:
WithoutPants
2022-12-01 13:54:08 +11:00
committed by GitHub
parent d2395e579c
commit 4daf0a14a2
72 changed files with 2283 additions and 993 deletions

View File

@@ -17,7 +17,6 @@ import (
"github.com/stashapp/stash/pkg/file"
"github.com/stashapp/stash/pkg/hash/md5"
"github.com/stashapp/stash/pkg/models"
"github.com/stashapp/stash/pkg/sliceutil/intslice"
"github.com/stashapp/stash/pkg/sqlite"
"github.com/stashapp/stash/pkg/txn"
@@ -442,10 +441,9 @@ var (
)
var (
performerTagLinks = [][2]int{
{performerIdxWithTag, tagIdxWithPerformer},
{performerIdxWithTwoTags, tagIdx1WithPerformer},
{performerIdxWithTwoTags, tagIdx2WithPerformer},
performerTags = linkMap{
performerIdxWithTag: {tagIdxWithPerformer},
performerIdxWithTwoTags: {tagIdx1WithPerformer, tagIdx2WithPerformer},
}
)
@@ -552,14 +550,14 @@ func populateDB() error {
return fmt.Errorf("error creating movies: %s", err.Error())
}
if err := createPerformers(ctx, performersNameCase, performersNameNoCase); err != nil {
return fmt.Errorf("error creating performers: %s", err.Error())
}
if err := createTags(ctx, sqlite.TagReaderWriter, tagsNameCase, tagsNameNoCase); err != nil {
return fmt.Errorf("error creating tags: %s", err.Error())
}
if err := createPerformers(ctx, performersNameCase, performersNameNoCase); err != nil {
return fmt.Errorf("error creating performers: %s", err.Error())
}
if err := createStudios(ctx, sqlite.StudioReaderWriter, studiosNameCase, studiosNameNoCase); err != nil {
return fmt.Errorf("error creating studios: %s", err.Error())
}
@@ -584,10 +582,6 @@ func populateDB() error {
return fmt.Errorf("error creating saved filters: %s", err.Error())
}
if err := linkPerformerTags(ctx); err != nil {
return fmt.Errorf("error linking performer tags: %s", err.Error())
}
if err := linkMovieStudios(ctx, sqlite.MovieReaderWriter); err != nil {
return fmt.Errorf("error linking movie studios: %s", err.Error())
}
@@ -1335,17 +1329,21 @@ func createPerformers(ctx context.Context, n int, o int) error {
} // so count backwards to 0 as needed
// performers [ i ] and [ n + o - i - 1 ] should have similar names with only the Name!=NaMe part different
tids := indexesToIDs(tagIDs, performerTags[i])
performer := models.Performer{
Name: getPerformerStringValue(index, name),
Checksum: getPerformerStringValue(i, checksumField),
URL: getPerformerNullStringValue(i, urlField),
Favorite: getPerformerBoolValue(i),
Birthdate: getPerformerBirthdate(i),
DeathDate: getPerformerDeathDate(i),
Details: getPerformerStringValue(i, "Details"),
Ethnicity: getPerformerStringValue(i, "Ethnicity"),
Rating: getIntPtr(getRating(i)),
IgnoreAutoTag: getIgnoreAutoTag(i),
Name: getPerformerStringValue(index, name),
Disambiguation: getPerformerStringValue(index, "disambiguation"),
Aliases: models.NewRelatedStrings([]string{getPerformerStringValue(index, "alias")}),
URL: getPerformerNullStringValue(i, urlField),
Favorite: getPerformerBoolValue(i),
Birthdate: getPerformerBirthdate(i),
DeathDate: getPerformerDeathDate(i),
Details: getPerformerStringValue(i, "Details"),
Ethnicity: getPerformerStringValue(i, "Ethnicity"),
Rating: getIntPtr(getRating(i)),
IgnoreAutoTag: getIgnoreAutoTag(i),
TagIDs: models.NewRelatedIDs(tids),
}
careerLength := getPerformerCareerLength(i)
@@ -1353,20 +1351,18 @@ func createPerformers(ctx context.Context, n int, o int) error {
performer.CareerLength = *careerLength
}
if (index+1)%5 != 0 {
performer.StashIDs = models.NewRelatedStashIDs([]models.StashID{
performerStashID(i),
})
}
err := pqb.Create(ctx, &performer)
if err != nil {
return fmt.Errorf("Error creating performer %v+: %s", performer, err.Error())
}
if (index+1)%5 != 0 {
if err := pqb.UpdateStashIDs(ctx, performer.ID, []models.StashID{
performerStashID(i),
}); err != nil {
return fmt.Errorf("setting performer stash ids: %w", err)
}
}
performerIDs = append(performerIDs, performer.ID)
performerNames = append(performerNames, performer.Name)
}
@@ -1637,22 +1633,6 @@ func doLinks(links [][2]int, fn func(idx1, idx2 int) error) error {
return nil
}
func linkPerformerTags(ctx context.Context) error {
qb := db.Performer
return doLinks(performerTagLinks, func(performerIndex, tagIndex int) error {
performerID := performerIDs[performerIndex]
tagID := tagIDs[tagIndex]
tagIDs, err := qb.GetTagIDs(ctx, performerID)
if err != nil {
return err
}
tagIDs = intslice.IntAppendUnique(tagIDs, tagID)
return qb.UpdateTags(ctx, performerID, tagIDs)
})
}
func linkMovieStudios(ctx context.Context, mqb models.MovieWriter) error {
return doLinks(movieStudioLinks, func(movieIndex, studioIndex int) error {
movie := models.MoviePartial{