mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 20:34:37 +03:00
Parent studios (#595)
* Refactor getMultiCriterionClause Co-authored-by: Anon247 <61889302+Anon247@users.noreply.github.com>
This commit is contained in:
@@ -3,6 +3,7 @@ package manager
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -157,7 +158,8 @@ func (t *ImportTask) ImportPerformers(ctx context.Context) {
|
||||
|
||||
func (t *ImportTask) ImportStudios(ctx context.Context) {
|
||||
tx := database.DB.MustBeginTx(ctx, nil)
|
||||
qb := models.NewStudioQueryBuilder()
|
||||
|
||||
pendingParent := make(map[string][]*jsonschema.Studio)
|
||||
|
||||
for i, mappingJSON := range t.Mappings.Studios {
|
||||
index := i + 1
|
||||
@@ -172,35 +174,28 @@ func (t *ImportTask) ImportStudios(ctx context.Context) {
|
||||
|
||||
logger.Progressf("[studios] %d of %d", index, len(t.Mappings.Studios))
|
||||
|
||||
// generate checksum from studio name rather than image
|
||||
checksum := utils.MD5FromString(studioJSON.Name)
|
||||
|
||||
// Process the base 64 encoded image string
|
||||
_, imageData, err := utils.ProcessBase64Image(studioJSON.Image)
|
||||
if err != nil {
|
||||
_ = tx.Rollback()
|
||||
logger.Errorf("[studios] <%s> invalid image: %s", mappingJSON.Checksum, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Populate a new studio from the input
|
||||
newStudio := models.Studio{
|
||||
Image: imageData,
|
||||
Checksum: checksum,
|
||||
Name: sql.NullString{String: studioJSON.Name, Valid: true},
|
||||
URL: sql.NullString{String: studioJSON.URL, Valid: true},
|
||||
CreatedAt: models.SQLiteTimestamp{Timestamp: t.getTimeFromJSONTime(studioJSON.CreatedAt)},
|
||||
UpdatedAt: models.SQLiteTimestamp{Timestamp: t.getTimeFromJSONTime(studioJSON.UpdatedAt)},
|
||||
}
|
||||
|
||||
_, err = qb.Create(newStudio, tx)
|
||||
if err != nil {
|
||||
_ = tx.Rollback()
|
||||
if err := t.ImportStudio(studioJSON, pendingParent, tx); err != nil {
|
||||
tx.Rollback()
|
||||
logger.Errorf("[studios] <%s> failed to create: %s", mappingJSON.Checksum, err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// create the leftover studios, warning for missing parents
|
||||
if len(pendingParent) > 0 {
|
||||
logger.Warnf("[studios] importing studios with missing parents")
|
||||
|
||||
for _, s := range pendingParent {
|
||||
for _, orphanStudioJSON := range s {
|
||||
if err := t.ImportStudio(orphanStudioJSON, nil, tx); err != nil {
|
||||
tx.Rollback()
|
||||
logger.Errorf("[studios] <%s> failed to create: %s", orphanStudioJSON.Name, err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.Info("[studios] importing")
|
||||
if err := tx.Commit(); err != nil {
|
||||
logger.Errorf("[studios] import failed to commit: %s", err.Error())
|
||||
@@ -208,6 +203,74 @@ func (t *ImportTask) ImportStudios(ctx context.Context) {
|
||||
logger.Info("[studios] import complete")
|
||||
}
|
||||
|
||||
func (t *ImportTask) ImportStudio(studioJSON *jsonschema.Studio, pendingParent map[string][]*jsonschema.Studio, tx *sqlx.Tx) error {
|
||||
qb := models.NewStudioQueryBuilder()
|
||||
|
||||
// generate checksum from studio name rather than image
|
||||
checksum := utils.MD5FromString(studioJSON.Name)
|
||||
|
||||
// Process the base 64 encoded image string
|
||||
_, imageData, err := utils.ProcessBase64Image(studioJSON.Image)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid image: %s", err.Error())
|
||||
}
|
||||
|
||||
// Populate a new studio from the input
|
||||
newStudio := models.Studio{
|
||||
Image: imageData,
|
||||
Checksum: checksum,
|
||||
Name: sql.NullString{String: studioJSON.Name, Valid: true},
|
||||
URL: sql.NullString{String: studioJSON.URL, Valid: true},
|
||||
CreatedAt: models.SQLiteTimestamp{Timestamp: t.getTimeFromJSONTime(studioJSON.CreatedAt)},
|
||||
UpdatedAt: models.SQLiteTimestamp{Timestamp: t.getTimeFromJSONTime(studioJSON.UpdatedAt)},
|
||||
}
|
||||
|
||||
// Populate the parent ID
|
||||
if studioJSON.ParentStudio != "" {
|
||||
studio, err := qb.FindByName(studioJSON.ParentStudio, tx, false)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error finding studio by name <%s>: %s", studioJSON.ParentStudio, err.Error())
|
||||
}
|
||||
|
||||
if studio == nil {
|
||||
// its possible that the parent hasn't been created yet
|
||||
// do it after it is created
|
||||
if pendingParent == nil {
|
||||
logger.Warnf("[studios] studio <%s> does not exist", studioJSON.ParentStudio)
|
||||
} else {
|
||||
// add to the pending parent list so that it is created after the parent
|
||||
s := pendingParent[studioJSON.ParentStudio]
|
||||
s = append(s, studioJSON)
|
||||
pendingParent[studioJSON.ParentStudio] = s
|
||||
|
||||
// skip
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
newStudio.ParentID = sql.NullInt64{Int64: int64(studio.ID), Valid: true}
|
||||
}
|
||||
}
|
||||
|
||||
_, err = qb.Create(newStudio, tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// now create the studios pending this studios creation
|
||||
s := pendingParent[studioJSON.Name]
|
||||
for _, childStudioJSON := range s {
|
||||
// map is nil since we're not checking parent studios at this point
|
||||
if err := t.ImportStudio(childStudioJSON, nil, tx); err != nil {
|
||||
return fmt.Errorf("failed to create child studio <%s>: %s", childStudioJSON.Name, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// delete the entry from the map so that we know its not left over
|
||||
delete(pendingParent, studioJSON.Name)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (t *ImportTask) ImportMovies(ctx context.Context) {
|
||||
tx := database.DB.MustBeginTx(ctx, nil)
|
||||
qb := models.NewMovieQueryBuilder()
|
||||
|
||||
Reference in New Issue
Block a user