mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 04:14:39 +03:00
Multiple scene URLs (#3852)
* Add URLs scene relationship * Update unit tests * Update scene edit and details pages * Update scrapers to use urls * Post-process scenes during query scrape * Update UI for URLs * Change urls label
This commit is contained in:
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/stashapp/stash/pkg/file"
|
||||
"github.com/stashapp/stash/pkg/logger"
|
||||
"github.com/stashapp/stash/pkg/models"
|
||||
"github.com/stashapp/stash/pkg/sliceutil"
|
||||
"github.com/stashapp/stash/pkg/sliceutil/intslice"
|
||||
"github.com/stashapp/stash/pkg/sliceutil/stringslice"
|
||||
)
|
||||
@@ -472,6 +473,113 @@ func (t *stringTable) modifyJoins(ctx context.Context, id int, v []string, mode
|
||||
return nil
|
||||
}
|
||||
|
||||
type orderedValueTable[T comparable] struct {
|
||||
table
|
||||
valueColumn exp.IdentifierExpression
|
||||
}
|
||||
|
||||
func (t *orderedValueTable[T]) positionColumn() exp.IdentifierExpression {
|
||||
const positionColumn = "position"
|
||||
return t.table.table.Col(positionColumn)
|
||||
}
|
||||
|
||||
func (t *orderedValueTable[T]) get(ctx context.Context, id int) ([]T, error) {
|
||||
q := dialect.Select(t.valueColumn).From(t.table.table).Where(t.idColumn.Eq(id)).Order(t.positionColumn().Asc())
|
||||
|
||||
const single = false
|
||||
var ret []T
|
||||
if err := queryFunc(ctx, q, single, func(rows *sqlx.Rows) error {
|
||||
var v T
|
||||
if err := rows.Scan(&v); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ret = append(ret, v)
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("getting stash ids from %s: %w", t.table.table.GetTable(), err)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (t *orderedValueTable[T]) insertJoin(ctx context.Context, id int, position int, v T) (sql.Result, error) {
|
||||
q := dialect.Insert(t.table.table).Cols(t.idColumn.GetCol(), t.positionColumn().GetCol(), t.valueColumn.GetCol()).Vals(
|
||||
goqu.Vals{id, position, v},
|
||||
)
|
||||
ret, err := exec(ctx, q)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("inserting into %s: %w", t.table.table.GetTable(), err)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (t *orderedValueTable[T]) insertJoins(ctx context.Context, id int, startPos int, v []T) error {
|
||||
for i, fk := range v {
|
||||
if _, err := t.insertJoin(ctx, id, i+startPos, fk); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *orderedValueTable[T]) replaceJoins(ctx context.Context, id int, v []T) error {
|
||||
if err := t.destroy(ctx, []int{id}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
const startPos = 0
|
||||
return t.insertJoins(ctx, id, startPos, v)
|
||||
}
|
||||
|
||||
func (t *orderedValueTable[T]) addJoins(ctx context.Context, id int, v []T) error {
|
||||
// get existing foreign keys
|
||||
existing, err := t.get(ctx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// only add values that are not already present
|
||||
filtered := sliceutil.Exclude(v, existing)
|
||||
|
||||
if len(filtered) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
startPos := len(existing)
|
||||
return t.insertJoins(ctx, id, startPos, filtered)
|
||||
}
|
||||
|
||||
func (t *orderedValueTable[T]) destroyJoins(ctx context.Context, id int, v []T) error {
|
||||
existing, err := t.get(ctx, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting existing %s: %w", t.table.table.GetTable(), err)
|
||||
}
|
||||
|
||||
newValue := sliceutil.Exclude(existing, v)
|
||||
if len(newValue) == len(existing) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return t.replaceJoins(ctx, id, newValue)
|
||||
}
|
||||
|
||||
func (t *orderedValueTable[T]) modifyJoins(ctx context.Context, id int, v []T, mode models.RelationshipUpdateMode) error {
|
||||
switch mode {
|
||||
case models.RelationshipUpdateModeSet:
|
||||
return t.replaceJoins(ctx, id, v)
|
||||
case models.RelationshipUpdateModeAdd:
|
||||
return t.addJoins(ctx, id, v)
|
||||
case models.RelationshipUpdateModeRemove:
|
||||
return t.destroyJoins(ctx, id, v)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type scenesMoviesTable struct {
|
||||
table
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user