mirror of
https://github.com/stashapp/stash.git
synced 2025-12-18 04:44:37 +03:00
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:
@@ -142,22 +142,26 @@ func (j *autoTagJob) autoTagPerformers(ctx context.Context, progress *job.Progre
|
||||
PerPage: &perPage,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error querying performers: %v", err)
|
||||
return fmt.Errorf("error querying performers: %w", err)
|
||||
}
|
||||
} else {
|
||||
performerIdInt, err := strconv.Atoi(performerId)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing performer id %s: %s", performerId, err.Error())
|
||||
return fmt.Errorf("parsing performer id %s: %w", performerId, err)
|
||||
}
|
||||
|
||||
performer, err := performerQuery.Find(ctx, performerIdInt)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error finding performer id %s: %s", performerId, err.Error())
|
||||
return fmt.Errorf("finding performer id %s: %w", performerId, err)
|
||||
}
|
||||
|
||||
if performer == nil {
|
||||
return fmt.Errorf("performer with id %s not found", performerId)
|
||||
}
|
||||
|
||||
if err := performer.LoadAliases(ctx, j.txnManager.Performer); err != nil {
|
||||
return fmt.Errorf("loading aliases for performer %d: %w", performer.ID, err)
|
||||
}
|
||||
performers = append(performers, performer)
|
||||
}
|
||||
|
||||
|
||||
@@ -899,13 +899,13 @@ func (t *ExportTask) exportPerformer(ctx context.Context, wg *sync.WaitGroup, jo
|
||||
newPerformerJSON, err := performer.ToJSON(ctx, performerReader, p)
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("[performers] <%s> error getting performer JSON: %s", p.Checksum, err.Error())
|
||||
logger.Errorf("[performers] <%s> error getting performer JSON: %s", p.Name, err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
tags, err := repo.Tag.FindByPerformerID(ctx, p.ID)
|
||||
if err != nil {
|
||||
logger.Errorf("[performers] <%s> error getting performer tags: %s", p.Checksum, err.Error())
|
||||
logger.Errorf("[performers] <%s> error getting performer tags: %s", p.Name, err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -918,7 +918,7 @@ func (t *ExportTask) exportPerformer(ctx context.Context, wg *sync.WaitGroup, jo
|
||||
fn := newPerformerJSON.Filename()
|
||||
|
||||
if err := t.json.savePerformer(fn, newPerformerJSON); err != nil {
|
||||
logger.Errorf("[performers] <%s> failed to save json: %s", p.Checksum, err.Error())
|
||||
logger.Errorf("[performers] <%s> failed to save json: %s", p.Name, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,10 +6,10 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/stashapp/stash/pkg/hash/md5"
|
||||
"github.com/stashapp/stash/pkg/logger"
|
||||
"github.com/stashapp/stash/pkg/models"
|
||||
"github.com/stashapp/stash/pkg/scraper/stashbox"
|
||||
"github.com/stashapp/stash/pkg/sliceutil/stringslice"
|
||||
"github.com/stashapp/stash/pkg/txn"
|
||||
"github.com/stashapp/stash/pkg/utils"
|
||||
)
|
||||
@@ -90,7 +90,10 @@ func (t *StashBoxPerformerTagTask) stashBoxPerformerTag(ctx context.Context) {
|
||||
partial := models.NewPerformerPartial()
|
||||
|
||||
if performer.Aliases != nil && !excluded["aliases"] {
|
||||
partial.Aliases = models.NewOptionalString(*performer.Aliases)
|
||||
partial.Aliases = &models.UpdateStrings{
|
||||
Values: stringslice.FromString(*performer.Aliases, ","),
|
||||
Mode: models.RelationshipUpdateModeSet,
|
||||
}
|
||||
}
|
||||
if performer.Birthdate != nil && *performer.Birthdate != "" && !excluded["birthdate"] {
|
||||
value := getDate(performer.Birthdate)
|
||||
@@ -134,8 +137,6 @@ func (t *StashBoxPerformerTagTask) stashBoxPerformerTag(ctx context.Context) {
|
||||
}
|
||||
if excluded["name"] && performer.Name != nil {
|
||||
partial.Name = models.NewOptionalString(*performer.Name)
|
||||
checksum := md5.FromString(*performer.Name)
|
||||
partial.Checksum = models.NewOptionalString(checksum)
|
||||
}
|
||||
if performer.Piercings != nil && !excluded["piercings"] {
|
||||
partial.Piercings = models.NewOptionalString(*performer.Piercings)
|
||||
@@ -149,22 +150,21 @@ func (t *StashBoxPerformerTagTask) stashBoxPerformerTag(ctx context.Context) {
|
||||
if performer.URL != nil && !excluded["url"] {
|
||||
partial.URL = models.NewOptionalString(*performer.URL)
|
||||
}
|
||||
|
||||
txnErr := txn.WithTxn(ctx, instance.Repository, func(ctx context.Context) error {
|
||||
r := instance.Repository
|
||||
_, err := r.Performer.UpdatePartial(ctx, t.performer.ID, partial)
|
||||
|
||||
if !t.refresh {
|
||||
err = r.Performer.UpdateStashIDs(ctx, t.performer.ID, []models.StashID{
|
||||
if !t.refresh {
|
||||
partial.StashIDs = &models.UpdateStashIDs{
|
||||
StashIDs: []models.StashID{
|
||||
{
|
||||
Endpoint: t.box.Endpoint,
|
||||
StashID: *performer.RemoteSiteID,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
},
|
||||
Mode: models.RelationshipUpdateModeSet,
|
||||
}
|
||||
}
|
||||
|
||||
txnErr := txn.WithTxn(ctx, instance.Repository, func(ctx context.Context) error {
|
||||
r := instance.Repository
|
||||
_, err := r.Performer.UpdatePartial(ctx, t.performer.ID, partial)
|
||||
|
||||
if len(performer.Images) > 0 && !excluded["image"] {
|
||||
image, err := utils.ReadImageFromURL(ctx, performer.Images[0])
|
||||
@@ -192,10 +192,9 @@ func (t *StashBoxPerformerTagTask) stashBoxPerformerTag(ctx context.Context) {
|
||||
} else if t.name != nil && performer.Name != nil {
|
||||
currentTime := time.Now()
|
||||
newPerformer := models.Performer{
|
||||
Aliases: getString(performer.Aliases),
|
||||
Aliases: models.NewRelatedStrings(stringslice.FromString(*performer.Aliases, ",")),
|
||||
Birthdate: getDate(performer.Birthdate),
|
||||
CareerLength: getString(performer.CareerLength),
|
||||
Checksum: md5.FromString(*performer.Name),
|
||||
Country: getString(performer.Country),
|
||||
CreatedAt: currentTime,
|
||||
Ethnicity: getString(performer.Ethnicity),
|
||||
@@ -211,21 +210,18 @@ func (t *StashBoxPerformerTagTask) stashBoxPerformerTag(ctx context.Context) {
|
||||
Tattoos: getString(performer.Tattoos),
|
||||
Twitter: getString(performer.Twitter),
|
||||
URL: getString(performer.URL),
|
||||
UpdatedAt: currentTime,
|
||||
}
|
||||
err := txn.WithTxn(ctx, instance.Repository, func(ctx context.Context) error {
|
||||
r := instance.Repository
|
||||
err := r.Performer.Create(ctx, &newPerformer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = r.Performer.UpdateStashIDs(ctx, newPerformer.ID, []models.StashID{
|
||||
StashIDs: models.NewRelatedStashIDs([]models.StashID{
|
||||
{
|
||||
Endpoint: t.box.Endpoint,
|
||||
StashID: *performer.RemoteSiteID,
|
||||
},
|
||||
})
|
||||
}),
|
||||
UpdatedAt: currentTime,
|
||||
}
|
||||
|
||||
err := txn.WithTxn(ctx, instance.Repository, func(ctx context.Context) error {
|
||||
r := instance.Repository
|
||||
err := r.Performer.Create(ctx, &newPerformer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user