mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 04:14:39 +03:00
Add updated_at field to stash_id's (#5259)
* Add updated_at field to stash_id's * Only set updated at on stash ids when actually updating in identify --------- Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
This commit is contained in:
@@ -129,9 +129,6 @@ models:
|
|||||||
model: github.com/stashapp/stash/internal/identify.FieldStrategy
|
model: github.com/stashapp/stash/internal/identify.FieldStrategy
|
||||||
ScraperSource:
|
ScraperSource:
|
||||||
model: github.com/stashapp/stash/pkg/scraper.Source
|
model: github.com/stashapp/stash/pkg/scraper.Source
|
||||||
# rebind inputs to types
|
|
||||||
StashIDInput:
|
|
||||||
model: github.com/stashapp/stash/pkg/models.StashID
|
|
||||||
IdentifySourceInput:
|
IdentifySourceInput:
|
||||||
model: github.com/stashapp/stash/internal/identify.Source
|
model: github.com/stashapp/stash/internal/identify.Source
|
||||||
IdentifyFieldOptionsInput:
|
IdentifyFieldOptionsInput:
|
||||||
|
|||||||
@@ -13,11 +13,13 @@ input StashBoxInput {
|
|||||||
type StashID {
|
type StashID {
|
||||||
endpoint: String!
|
endpoint: String!
|
||||||
stash_id: String!
|
stash_id: String!
|
||||||
|
updated_at: Time!
|
||||||
}
|
}
|
||||||
|
|
||||||
input StashIDInput {
|
input StashIDInput {
|
||||||
endpoint: String!
|
endpoint: String!
|
||||||
stash_id: String!
|
stash_id: String!
|
||||||
|
updated_at: Time
|
||||||
}
|
}
|
||||||
|
|
||||||
input StashBoxFingerprintSubmissionInput {
|
input StashBoxFingerprintSubmissionInput {
|
||||||
|
|||||||
@@ -335,13 +335,13 @@ func (t changesetTranslator) updateStringsBulk(value *BulkUpdateStrings, field s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t changesetTranslator) updateStashIDs(value []models.StashID, field string) *models.UpdateStashIDs {
|
func (t changesetTranslator) updateStashIDs(value models.StashIDInputs, field string) *models.UpdateStashIDs {
|
||||||
if !t.hasField(field) {
|
if !t.hasField(field) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return &models.UpdateStashIDs{
|
return &models.UpdateStashIDs{
|
||||||
StashIDs: value,
|
StashIDs: value.ToStashIDs(),
|
||||||
Mode: models.RelationshipUpdateModeSet,
|
Mode: models.RelationshipUpdateModeSet,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ func (r *mutationResolver) PerformerCreate(ctx context.Context, input models.Per
|
|||||||
newPerformer.Height = input.HeightCm
|
newPerformer.Height = input.HeightCm
|
||||||
newPerformer.Weight = input.Weight
|
newPerformer.Weight = input.Weight
|
||||||
newPerformer.IgnoreAutoTag = translator.bool(input.IgnoreAutoTag)
|
newPerformer.IgnoreAutoTag = translator.bool(input.IgnoreAutoTag)
|
||||||
newPerformer.StashIDs = models.NewRelatedStashIDs(input.StashIds)
|
newPerformer.StashIDs = models.NewRelatedStashIDs(models.StashIDInputs(input.StashIds).ToStashIDs())
|
||||||
|
|
||||||
newPerformer.URLs = models.NewRelatedStrings([]string{})
|
newPerformer.URLs = models.NewRelatedStrings([]string{})
|
||||||
if input.URL != nil {
|
if input.URL != nil {
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ func (r *mutationResolver) SceneCreate(ctx context.Context, input models.SceneCr
|
|||||||
newScene.Director = translator.string(input.Director)
|
newScene.Director = translator.string(input.Director)
|
||||||
newScene.Rating = input.Rating100
|
newScene.Rating = input.Rating100
|
||||||
newScene.Organized = translator.bool(input.Organized)
|
newScene.Organized = translator.bool(input.Organized)
|
||||||
newScene.StashIDs = models.NewRelatedStashIDs(input.StashIds)
|
newScene.StashIDs = models.NewRelatedStashIDs(models.StashIDInputs(input.StashIds).ToStashIDs())
|
||||||
|
|
||||||
newScene.Date, err = translator.datePtr(input.Date)
|
newScene.Date, err = translator.datePtr(input.Date)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ func (r *mutationResolver) StudioCreate(ctx context.Context, input models.Studio
|
|||||||
newStudio.Details = translator.string(input.Details)
|
newStudio.Details = translator.string(input.Details)
|
||||||
newStudio.IgnoreAutoTag = translator.bool(input.IgnoreAutoTag)
|
newStudio.IgnoreAutoTag = translator.bool(input.IgnoreAutoTag)
|
||||||
newStudio.Aliases = models.NewRelatedStrings(input.Aliases)
|
newStudio.Aliases = models.NewRelatedStrings(input.Aliases)
|
||||||
newStudio.StashIDs = models.NewRelatedStashIDs(input.StashIds)
|
newStudio.StashIDs = models.NewRelatedStashIDs(models.StashIDInputs(input.StashIds).ToStashIDs())
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
|||||||
@@ -245,7 +245,18 @@ func (t *SceneIdentifier) getSceneUpdater(ctx context.Context, s *models.Scene,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stashIDs, err := rel.stashIDs(ctx)
|
// SetCoverImage defaults to true if unset
|
||||||
|
if options.SetCoverImage == nil || *options.SetCoverImage {
|
||||||
|
ret.CoverImage, err = rel.cover(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if anything changed, also update the updated at time on the applicable stash id
|
||||||
|
changed := !ret.IsEmpty()
|
||||||
|
|
||||||
|
stashIDs, err := rel.stashIDs(ctx, changed)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -256,14 +267,6 @@ func (t *SceneIdentifier) getSceneUpdater(ctx context.Context, s *models.Scene,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCoverImage defaults to true if unset
|
|
||||||
if options.SetCoverImage == nil || *options.SetCoverImage {
|
|
||||||
ret.CoverImage, err = rel.cover(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/stashapp/stash/pkg/logger"
|
"github.com/stashapp/stash/pkg/logger"
|
||||||
"github.com/stashapp/stash/pkg/models"
|
"github.com/stashapp/stash/pkg/models"
|
||||||
@@ -182,7 +183,13 @@ func (g sceneRelationships) tags(ctx context.Context) ([]int, error) {
|
|||||||
return tagIDs, nil
|
return tagIDs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g sceneRelationships) stashIDs(ctx context.Context) ([]models.StashID, error) {
|
// stashIDs returns the updated stash IDs for the scene
|
||||||
|
// returns nil if not applicable or no changes were made
|
||||||
|
// if setUpdateTime is true, then the updated_at field will be set to the current time
|
||||||
|
// for the applicable matching stash ID
|
||||||
|
func (g sceneRelationships) stashIDs(ctx context.Context, setUpdateTime bool) ([]models.StashID, error) {
|
||||||
|
updateTime := time.Now()
|
||||||
|
|
||||||
remoteSiteID := g.result.result.RemoteSiteID
|
remoteSiteID := g.result.result.RemoteSiteID
|
||||||
fieldStrategy := g.fieldOptions["stash_ids"]
|
fieldStrategy := g.fieldOptions["stash_ids"]
|
||||||
target := g.scene
|
target := g.scene
|
||||||
@@ -199,7 +206,7 @@ func (g sceneRelationships) stashIDs(ctx context.Context) ([]models.StashID, err
|
|||||||
strategy = fieldStrategy.Strategy
|
strategy = fieldStrategy.Strategy
|
||||||
}
|
}
|
||||||
|
|
||||||
var stashIDs []models.StashID
|
var stashIDs models.StashIDs
|
||||||
originalStashIDs := target.StashIDs.List()
|
originalStashIDs := target.StashIDs.List()
|
||||||
|
|
||||||
if strategy == FieldStrategyMerge {
|
if strategy == FieldStrategyMerge {
|
||||||
@@ -208,15 +215,17 @@ func (g sceneRelationships) stashIDs(ctx context.Context) ([]models.StashID, err
|
|||||||
stashIDs = append(stashIDs, originalStashIDs...)
|
stashIDs = append(stashIDs, originalStashIDs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// find and update the stash id if it exists
|
||||||
for i, stashID := range stashIDs {
|
for i, stashID := range stashIDs {
|
||||||
if endpoint == stashID.Endpoint {
|
if endpoint == stashID.Endpoint {
|
||||||
// if stashID is the same, then don't set
|
// if stashID is the same, then don't set
|
||||||
if stashID.StashID == *remoteSiteID {
|
if !setUpdateTime && stashID.StashID == *remoteSiteID {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace the stash id and return
|
// replace the stash id and return
|
||||||
stashID.StashID = *remoteSiteID
|
stashID.StashID = *remoteSiteID
|
||||||
|
stashID.UpdatedAt = updateTime
|
||||||
stashIDs[i] = stashID
|
stashIDs[i] = stashID
|
||||||
return stashIDs, nil
|
return stashIDs, nil
|
||||||
}
|
}
|
||||||
@@ -226,9 +235,12 @@ func (g sceneRelationships) stashIDs(ctx context.Context) ([]models.StashID, err
|
|||||||
stashIDs = append(stashIDs, models.StashID{
|
stashIDs = append(stashIDs, models.StashID{
|
||||||
StashID: *remoteSiteID,
|
StashID: *remoteSiteID,
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
|
UpdatedAt: updateTime,
|
||||||
})
|
})
|
||||||
|
|
||||||
if sliceutil.SliceSame(originalStashIDs, stashIDs) {
|
// don't return if nothing was changed
|
||||||
|
// if we're setting update time, then we always return
|
||||||
|
if !setUpdateTime && stashIDs.HasSameStashIDs(originalStashIDs) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/stashapp/stash/pkg/models"
|
"github.com/stashapp/stash/pkg/models"
|
||||||
"github.com/stashapp/stash/pkg/models/mocks"
|
"github.com/stashapp/stash/pkg/models/mocks"
|
||||||
@@ -550,6 +551,7 @@ func Test_sceneRelationships_stashIDs(t *testing.T) {
|
|||||||
{
|
{
|
||||||
StashID: remoteSiteID,
|
StashID: remoteSiteID,
|
||||||
Endpoint: existingEndpoint,
|
Endpoint: existingEndpoint,
|
||||||
|
UpdatedAt: time.Time{},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
@@ -561,12 +563,15 @@ func Test_sceneRelationships_stashIDs(t *testing.T) {
|
|||||||
fieldOptions: make(map[string]*FieldOptions),
|
fieldOptions: make(map[string]*FieldOptions),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setTime := time.Now()
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
scene *models.Scene
|
scene *models.Scene
|
||||||
fieldOptions *FieldOptions
|
fieldOptions *FieldOptions
|
||||||
endpoint string
|
endpoint string
|
||||||
remoteSiteID *string
|
remoteSiteID *string
|
||||||
|
setUpdateTime bool
|
||||||
want []models.StashID
|
want []models.StashID
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
@@ -578,6 +583,7 @@ func Test_sceneRelationships_stashIDs(t *testing.T) {
|
|||||||
},
|
},
|
||||||
newEndpoint,
|
newEndpoint,
|
||||||
&remoteSiteID,
|
&remoteSiteID,
|
||||||
|
false,
|
||||||
nil,
|
nil,
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
@@ -587,6 +593,7 @@ func Test_sceneRelationships_stashIDs(t *testing.T) {
|
|||||||
defaultOptions,
|
defaultOptions,
|
||||||
"",
|
"",
|
||||||
&remoteSiteID,
|
&remoteSiteID,
|
||||||
|
false,
|
||||||
nil,
|
nil,
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
@@ -596,6 +603,7 @@ func Test_sceneRelationships_stashIDs(t *testing.T) {
|
|||||||
defaultOptions,
|
defaultOptions,
|
||||||
newEndpoint,
|
newEndpoint,
|
||||||
nil,
|
nil,
|
||||||
|
false,
|
||||||
nil,
|
nil,
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
@@ -605,19 +613,38 @@ func Test_sceneRelationships_stashIDs(t *testing.T) {
|
|||||||
defaultOptions,
|
defaultOptions,
|
||||||
existingEndpoint,
|
existingEndpoint,
|
||||||
&remoteSiteID,
|
&remoteSiteID,
|
||||||
|
false,
|
||||||
nil,
|
nil,
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"merge existing set update time",
|
||||||
|
sceneWithStashIDs,
|
||||||
|
defaultOptions,
|
||||||
|
existingEndpoint,
|
||||||
|
&remoteSiteID,
|
||||||
|
true,
|
||||||
|
[]models.StashID{
|
||||||
|
{
|
||||||
|
StashID: remoteSiteID,
|
||||||
|
Endpoint: existingEndpoint,
|
||||||
|
UpdatedAt: setTime,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"merge existing new value",
|
"merge existing new value",
|
||||||
sceneWithStashIDs,
|
sceneWithStashIDs,
|
||||||
defaultOptions,
|
defaultOptions,
|
||||||
existingEndpoint,
|
existingEndpoint,
|
||||||
&newRemoteSiteID,
|
&newRemoteSiteID,
|
||||||
|
false,
|
||||||
[]models.StashID{
|
[]models.StashID{
|
||||||
{
|
{
|
||||||
StashID: newRemoteSiteID,
|
StashID: newRemoteSiteID,
|
||||||
Endpoint: existingEndpoint,
|
Endpoint: existingEndpoint,
|
||||||
|
UpdatedAt: setTime,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
@@ -628,14 +655,17 @@ func Test_sceneRelationships_stashIDs(t *testing.T) {
|
|||||||
defaultOptions,
|
defaultOptions,
|
||||||
newEndpoint,
|
newEndpoint,
|
||||||
&newRemoteSiteID,
|
&newRemoteSiteID,
|
||||||
|
false,
|
||||||
[]models.StashID{
|
[]models.StashID{
|
||||||
{
|
{
|
||||||
StashID: remoteSiteID,
|
StashID: remoteSiteID,
|
||||||
Endpoint: existingEndpoint,
|
Endpoint: existingEndpoint,
|
||||||
|
UpdatedAt: time.Time{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
StashID: newRemoteSiteID,
|
StashID: newRemoteSiteID,
|
||||||
Endpoint: newEndpoint,
|
Endpoint: newEndpoint,
|
||||||
|
UpdatedAt: setTime,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
@@ -648,10 +678,12 @@ func Test_sceneRelationships_stashIDs(t *testing.T) {
|
|||||||
},
|
},
|
||||||
newEndpoint,
|
newEndpoint,
|
||||||
&newRemoteSiteID,
|
&newRemoteSiteID,
|
||||||
|
false,
|
||||||
[]models.StashID{
|
[]models.StashID{
|
||||||
{
|
{
|
||||||
StashID: newRemoteSiteID,
|
StashID: newRemoteSiteID,
|
||||||
Endpoint: newEndpoint,
|
Endpoint: newEndpoint,
|
||||||
|
UpdatedAt: setTime,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
@@ -664,9 +696,28 @@ func Test_sceneRelationships_stashIDs(t *testing.T) {
|
|||||||
},
|
},
|
||||||
existingEndpoint,
|
existingEndpoint,
|
||||||
&remoteSiteID,
|
&remoteSiteID,
|
||||||
|
false,
|
||||||
nil,
|
nil,
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"overwrite same set update time",
|
||||||
|
sceneWithStashIDs,
|
||||||
|
&FieldOptions{
|
||||||
|
Strategy: FieldStrategyOverwrite,
|
||||||
|
},
|
||||||
|
existingEndpoint,
|
||||||
|
&remoteSiteID,
|
||||||
|
true,
|
||||||
|
[]models.StashID{
|
||||||
|
{
|
||||||
|
StashID: remoteSiteID,
|
||||||
|
Endpoint: existingEndpoint,
|
||||||
|
UpdatedAt: setTime,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
@@ -681,11 +732,20 @@ func Test_sceneRelationships_stashIDs(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
got, err := tr.stashIDs(testCtx)
|
got, err := tr.stashIDs(testCtx, tt.setUpdateTime)
|
||||||
|
|
||||||
if (err != nil) != tt.wantErr {
|
if (err != nil) != tt.wantErr {
|
||||||
t.Errorf("sceneRelationships.stashIDs() error = %v, wantErr %v", err, tt.wantErr)
|
t.Errorf("sceneRelationships.stashIDs() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// massage updatedAt times to be consistent for comparison
|
||||||
|
for i := range got {
|
||||||
|
if !got[i].UpdatedAt.IsZero() {
|
||||||
|
got[i].UpdatedAt = setTime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(got, tt.want) {
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("sceneRelationships.stashIDs() = %+v, want %+v", got, tt.want)
|
t.Errorf("sceneRelationships.stashIDs() = %+v, want %+v", got, tt.want)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -192,9 +192,9 @@ func (s ScenePartial) UpdateInput(id int) SceneUpdateInput {
|
|||||||
dateStr = &v
|
dateStr = &v
|
||||||
}
|
}
|
||||||
|
|
||||||
var stashIDs []StashID
|
var stashIDs StashIDs
|
||||||
if s.StashIDs != nil {
|
if s.StashIDs != nil {
|
||||||
stashIDs = s.StashIDs.StashIDs
|
stashIDs = StashIDs(s.StashIDs.StashIDs)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret := SceneUpdateInput{
|
ret := SceneUpdateInput{
|
||||||
@@ -212,7 +212,7 @@ func (s ScenePartial) UpdateInput(id int) SceneUpdateInput {
|
|||||||
PerformerIds: s.PerformerIDs.IDStrings(),
|
PerformerIds: s.PerformerIDs.IDStrings(),
|
||||||
Movies: s.GroupIDs.SceneMovieInputs(),
|
Movies: s.GroupIDs.SceneMovieInputs(),
|
||||||
TagIds: s.TagIDs.IDStrings(),
|
TagIds: s.TagIDs.IDStrings(),
|
||||||
StashIds: stashIDs,
|
StashIds: stashIDs.ToStashIDInputs(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package models
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/stashapp/stash/pkg/sliceutil/stringslice"
|
"github.com/stashapp/stash/pkg/sliceutil/stringslice"
|
||||||
"github.com/stashapp/stash/pkg/utils"
|
"github.com/stashapp/stash/pkg/utils"
|
||||||
@@ -31,6 +32,7 @@ func (s *ScrapedStudio) ToStudio(endpoint string, excluded map[string]bool) *Stu
|
|||||||
{
|
{
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
StashID: *s.RemoteSiteID,
|
StashID: *s.RemoteSiteID,
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -65,6 +67,7 @@ func (s *ScrapedStudio) GetImage(ctx context.Context, excluded map[string]bool)
|
|||||||
func (s *ScrapedStudio) ToPartial(id string, endpoint string, excluded map[string]bool, existingStashIDs []StashID) StudioPartial {
|
func (s *ScrapedStudio) ToPartial(id string, endpoint string, excluded map[string]bool, existingStashIDs []StashID) StudioPartial {
|
||||||
ret := NewStudioPartial()
|
ret := NewStudioPartial()
|
||||||
ret.ID, _ = strconv.Atoi(id)
|
ret.ID, _ = strconv.Atoi(id)
|
||||||
|
currentTime := time.Now()
|
||||||
|
|
||||||
if s.Name != "" && !excluded["name"] {
|
if s.Name != "" && !excluded["name"] {
|
||||||
ret.Name = NewOptionalString(s.Name)
|
ret.Name = NewOptionalString(s.Name)
|
||||||
@@ -92,6 +95,7 @@ func (s *ScrapedStudio) ToPartial(id string, endpoint string, excluded map[strin
|
|||||||
ret.StashIDs.Set(StashID{
|
ret.StashIDs.Set(StashID{
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
StashID: *s.RemoteSiteID,
|
StashID: *s.RemoteSiteID,
|
||||||
|
UpdatedAt: currentTime,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,6 +141,7 @@ func (ScrapedPerformer) IsScrapedContent() {}
|
|||||||
|
|
||||||
func (p *ScrapedPerformer) ToPerformer(endpoint string, excluded map[string]bool) *Performer {
|
func (p *ScrapedPerformer) ToPerformer(endpoint string, excluded map[string]bool) *Performer {
|
||||||
ret := NewPerformer()
|
ret := NewPerformer()
|
||||||
|
currentTime := time.Now()
|
||||||
ret.Name = *p.Name
|
ret.Name = *p.Name
|
||||||
|
|
||||||
if p.Aliases != nil && !excluded["aliases"] {
|
if p.Aliases != nil && !excluded["aliases"] {
|
||||||
@@ -246,6 +251,7 @@ func (p *ScrapedPerformer) ToPerformer(endpoint string, excluded map[string]bool
|
|||||||
{
|
{
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
StashID: *p.RemoteSiteID,
|
StashID: *p.RemoteSiteID,
|
||||||
|
UpdatedAt: currentTime,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -377,6 +383,7 @@ func (p *ScrapedPerformer) ToPartial(endpoint string, excluded map[string]bool,
|
|||||||
ret.StashIDs.Set(StashID{
|
ret.StashIDs.Set(StashID{
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
StashID: *p.RemoteSiteID,
|
StashID: *p.RemoteSiteID,
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,6 +87,11 @@ func Test_scrapedToStudioInput(t *testing.T) {
|
|||||||
|
|
||||||
got.CreatedAt = time.Time{}
|
got.CreatedAt = time.Time{}
|
||||||
got.UpdatedAt = time.Time{}
|
got.UpdatedAt = time.Time{}
|
||||||
|
if got.StashIDs.Loaded() && len(got.StashIDs.List()) > 0 {
|
||||||
|
for stid := range got.StashIDs.List() {
|
||||||
|
got.StashIDs.List()[stid].UpdatedAt = time.Time{}
|
||||||
|
}
|
||||||
|
}
|
||||||
assert.Equal(t, tt.want, got)
|
assert.Equal(t, tt.want, got)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -243,6 +248,12 @@ func Test_scrapedToPerformerInput(t *testing.T) {
|
|||||||
|
|
||||||
got.CreatedAt = time.Time{}
|
got.CreatedAt = time.Time{}
|
||||||
got.UpdatedAt = time.Time{}
|
got.UpdatedAt = time.Time{}
|
||||||
|
|
||||||
|
if got.StashIDs.Loaded() && len(got.StashIDs.List()) > 0 {
|
||||||
|
for stid := range got.StashIDs.List() {
|
||||||
|
got.StashIDs.List()[stid].UpdatedAt = time.Time{}
|
||||||
|
}
|
||||||
|
}
|
||||||
assert.Equal(t, tt.want, got)
|
assert.Equal(t, tt.want, got)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -263,7 +274,7 @@ func TestScrapedStudio_ToPartial(t *testing.T) {
|
|||||||
images = []string{image}
|
images = []string{image}
|
||||||
|
|
||||||
existingEndpoint = "existingEndpoint"
|
existingEndpoint = "existingEndpoint"
|
||||||
existingStashID = StashID{"existingStashID", existingEndpoint}
|
existingStashID = StashID{"existingStashID", existingEndpoint, time.Time{}}
|
||||||
existingStashIDs = []StashID{existingStashID}
|
existingStashIDs = []StashID{existingStashID}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -362,6 +373,11 @@ func TestScrapedStudio_ToPartial(t *testing.T) {
|
|||||||
|
|
||||||
// unset updatedAt - we don't need to compare it
|
// unset updatedAt - we don't need to compare it
|
||||||
got.UpdatedAt = OptionalTime{}
|
got.UpdatedAt = OptionalTime{}
|
||||||
|
if got.StashIDs != nil && len(got.StashIDs.StashIDs) > 0 {
|
||||||
|
for stid := range got.StashIDs.StashIDs {
|
||||||
|
got.StashIDs.StashIDs[stid].UpdatedAt = time.Time{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
assert.Equal(t, tt.want, got)
|
assert.Equal(t, tt.want, got)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ type PerformerCreateInput struct {
|
|||||||
TagIds []string `json:"tag_ids"`
|
TagIds []string `json:"tag_ids"`
|
||||||
// This should be a URL or a base64 encoded data URL
|
// This should be a URL or a base64 encoded data URL
|
||||||
Image *string `json:"image"`
|
Image *string `json:"image"`
|
||||||
StashIds []StashID `json:"stash_ids"`
|
StashIds []StashIDInput `json:"stash_ids"`
|
||||||
Rating100 *int `json:"rating100"`
|
Rating100 *int `json:"rating100"`
|
||||||
Details *string `json:"details"`
|
Details *string `json:"details"`
|
||||||
DeathDate *string `json:"death_date"`
|
DeathDate *string `json:"death_date"`
|
||||||
@@ -264,7 +264,7 @@ type PerformerUpdateInput struct {
|
|||||||
TagIds []string `json:"tag_ids"`
|
TagIds []string `json:"tag_ids"`
|
||||||
// This should be a URL or a base64 encoded data URL
|
// This should be a URL or a base64 encoded data URL
|
||||||
Image *string `json:"image"`
|
Image *string `json:"image"`
|
||||||
StashIds []StashID `json:"stash_ids"`
|
StashIds []StashIDInput `json:"stash_ids"`
|
||||||
Rating100 *int `json:"rating100"`
|
Rating100 *int `json:"rating100"`
|
||||||
Details *string `json:"details"`
|
Details *string `json:"details"`
|
||||||
DeathDate *string `json:"death_date"`
|
DeathDate *string `json:"death_date"`
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ type SceneCreateInput struct {
|
|||||||
TagIds []string `json:"tag_ids"`
|
TagIds []string `json:"tag_ids"`
|
||||||
// This should be a URL or a base64 encoded data URL
|
// This should be a URL or a base64 encoded data URL
|
||||||
CoverImage *string `json:"cover_image"`
|
CoverImage *string `json:"cover_image"`
|
||||||
StashIds []StashID `json:"stash_ids"`
|
StashIds []StashIDInput `json:"stash_ids"`
|
||||||
// The first id will be assigned as primary.
|
// The first id will be assigned as primary.
|
||||||
// Files will be reassigned from existing scenes if applicable.
|
// Files will be reassigned from existing scenes if applicable.
|
||||||
// Files must not already be primary for another scene.
|
// Files must not already be primary for another scene.
|
||||||
@@ -192,7 +192,7 @@ type SceneUpdateInput struct {
|
|||||||
TagIds []string `json:"tag_ids"`
|
TagIds []string `json:"tag_ids"`
|
||||||
// This should be a URL or a base64 encoded data URL
|
// This should be a URL or a base64 encoded data URL
|
||||||
CoverImage *string `json:"cover_image"`
|
CoverImage *string `json:"cover_image"`
|
||||||
StashIds []StashID `json:"stash_ids"`
|
StashIds []StashIDInput `json:"stash_ids"`
|
||||||
ResumeTime *float64 `json:"resume_time"`
|
ResumeTime *float64 `json:"resume_time"`
|
||||||
PlayDuration *float64 `json:"play_duration"`
|
PlayDuration *float64 `json:"play_duration"`
|
||||||
PlayCount *int `json:"play_count"`
|
PlayCount *int `json:"play_count"`
|
||||||
|
|||||||
@@ -1,8 +1,89 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"slices"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
type StashID struct {
|
type StashID struct {
|
||||||
StashID string `db:"stash_id" json:"stash_id"`
|
StashID string `db:"stash_id" json:"stash_id"`
|
||||||
Endpoint string `db:"endpoint" json:"endpoint"`
|
Endpoint string `db:"endpoint" json:"endpoint"`
|
||||||
|
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s StashID) ToStashIDInput() StashIDInput {
|
||||||
|
t := s.UpdatedAt
|
||||||
|
return StashIDInput{
|
||||||
|
StashID: s.StashID,
|
||||||
|
Endpoint: s.Endpoint,
|
||||||
|
UpdatedAt: &t,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type StashIDs []StashID
|
||||||
|
|
||||||
|
func (s StashIDs) ToStashIDInputs() StashIDInputs {
|
||||||
|
if s == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := make(StashIDInputs, len(s))
|
||||||
|
for i, v := range s {
|
||||||
|
ret[i] = v.ToStashIDInput()
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasSameStashIDs returns true if the two lists of StashIDs are the same, ignoring order and updated at time.
|
||||||
|
func (s StashIDs) HasSameStashIDs(other StashIDs) bool {
|
||||||
|
if len(s) != len(other) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range s {
|
||||||
|
if !slices.ContainsFunc(other, func(o StashID) bool {
|
||||||
|
return o.StashID == v.StashID && o.Endpoint == v.Endpoint
|
||||||
|
}) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
type StashIDInput struct {
|
||||||
|
StashID string `db:"stash_id" json:"stash_id"`
|
||||||
|
Endpoint string `db:"endpoint" json:"endpoint"`
|
||||||
|
UpdatedAt *time.Time `db:"updated_at" json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s StashIDInput) ToStashID() StashID {
|
||||||
|
ret := StashID{
|
||||||
|
StashID: s.StashID,
|
||||||
|
Endpoint: s.Endpoint,
|
||||||
|
}
|
||||||
|
if s.UpdatedAt != nil {
|
||||||
|
ret.UpdatedAt = *s.UpdatedAt
|
||||||
|
} else {
|
||||||
|
// default to now if not provided
|
||||||
|
ret.UpdatedAt = time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
type StashIDInputs []StashIDInput
|
||||||
|
|
||||||
|
func (s StashIDInputs) ToStashIDs() StashIDs {
|
||||||
|
if s == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := make(StashIDs, len(s))
|
||||||
|
for i, v := range s {
|
||||||
|
ret[i] = v.ToStashID()
|
||||||
|
}
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateStashIDs struct {
|
type UpdateStashIDs struct {
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ type StudioCreateInput struct {
|
|||||||
ParentID *string `json:"parent_id"`
|
ParentID *string `json:"parent_id"`
|
||||||
// This should be a URL or a base64 encoded data URL
|
// This should be a URL or a base64 encoded data URL
|
||||||
Image *string `json:"image"`
|
Image *string `json:"image"`
|
||||||
StashIds []StashID `json:"stash_ids"`
|
StashIds []StashIDInput `json:"stash_ids"`
|
||||||
Rating100 *int `json:"rating100"`
|
Rating100 *int `json:"rating100"`
|
||||||
Favorite *bool `json:"favorite"`
|
Favorite *bool `json:"favorite"`
|
||||||
Details *string `json:"details"`
|
Details *string `json:"details"`
|
||||||
@@ -68,7 +68,7 @@ type StudioUpdateInput struct {
|
|||||||
ParentID *string `json:"parent_id"`
|
ParentID *string `json:"parent_id"`
|
||||||
// This should be a URL or a base64 encoded data URL
|
// This should be a URL or a base64 encoded data URL
|
||||||
Image *string `json:"image"`
|
Image *string `json:"image"`
|
||||||
StashIds []StashID `json:"stash_ids"`
|
StashIds []StashIDInput `json:"stash_ids"`
|
||||||
Rating100 *int `json:"rating100"`
|
Rating100 *int `json:"rating100"`
|
||||||
Favorite *bool `json:"favorite"`
|
Favorite *bool `json:"favorite"`
|
||||||
Details *string `json:"details"`
|
Details *string `json:"details"`
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/stashapp/stash/pkg/models"
|
"github.com/stashapp/stash/pkg/models"
|
||||||
"github.com/stashapp/stash/pkg/models/mocks"
|
"github.com/stashapp/stash/pkg/models/mocks"
|
||||||
@@ -236,16 +237,19 @@ func TestUpdateSet_UpdateInput(t *testing.T) {
|
|||||||
tagIDStrs := intslice.IntSliceToStringSlice(tagIDs)
|
tagIDStrs := intslice.IntSliceToStringSlice(tagIDs)
|
||||||
stashID := "stashID"
|
stashID := "stashID"
|
||||||
endpoint := "endpoint"
|
endpoint := "endpoint"
|
||||||
|
updatedAt := time.Now()
|
||||||
stashIDs := []models.StashID{
|
stashIDs := []models.StashID{
|
||||||
{
|
{
|
||||||
StashID: stashID,
|
StashID: stashID,
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
stashIDInputs := []models.StashID{
|
stashIDInputs := []models.StashIDInput{
|
||||||
{
|
{
|
||||||
StashID: stashID,
|
StashID: stashID,
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
|
UpdatedAt: &updatedAt,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ const (
|
|||||||
cacheSizeEnv = "STASH_SQLITE_CACHE_SIZE"
|
cacheSizeEnv = "STASH_SQLITE_CACHE_SIZE"
|
||||||
)
|
)
|
||||||
|
|
||||||
var appSchemaVersion uint = 68
|
var appSchemaVersion uint = 69
|
||||||
|
|
||||||
//go:embed migrations/*.sql
|
//go:embed migrations/*.sql
|
||||||
var migrationsBox embed.FS
|
var migrationsBox embed.FS
|
||||||
|
|||||||
3
pkg/sqlite/migrations/69_stash_id_updated_at.up.sql
Normal file
3
pkg/sqlite/migrations/69_stash_id_updated_at.up.sql
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE `performer_stash_ids` ADD COLUMN `updated_at` datetime not null default '1970-01-01T00:00:00Z';
|
||||||
|
ALTER TABLE `scene_stash_ids` ADD COLUMN `updated_at` datetime not null default '1970-01-01T00:00:00Z';
|
||||||
|
ALTER TABLE `studio_stash_ids` ADD COLUMN `updated_at` datetime not null default '1970-01-01T00:00:00Z';
|
||||||
@@ -14,11 +14,6 @@ import (
|
|||||||
|
|
||||||
const idColumn = "id"
|
const idColumn = "id"
|
||||||
|
|
||||||
type objectList interface {
|
|
||||||
Append(o interface{})
|
|
||||||
New() interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
type repository struct {
|
type repository struct {
|
||||||
tableName string
|
tableName string
|
||||||
idColumn string
|
idColumn string
|
||||||
@@ -124,17 +119,6 @@ func (r *repository) queryFunc(ctx context.Context, query string, args []interfa
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *repository) query(ctx context.Context, query string, args []interface{}, out objectList) error {
|
|
||||||
return r.queryFunc(ctx, query, args, false, func(rows *sqlx.Rows) error {
|
|
||||||
object := out.New()
|
|
||||||
if err := rows.StructScan(object); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
out.Append(object)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *repository) queryStruct(ctx context.Context, query string, args []interface{}, out interface{}) error {
|
func (r *repository) queryStruct(ctx context.Context, query string, args []interface{}, out interface{}) error {
|
||||||
if err := r.queryFunc(ctx, query, args, true, func(rows *sqlx.Rows) error {
|
if err := r.queryFunc(ctx, query, args, true, func(rows *sqlx.Rows) error {
|
||||||
if err := rows.StructScan(out); err != nil {
|
if err := rows.StructScan(out); err != nil {
|
||||||
@@ -421,7 +405,7 @@ type stashIDRepository struct {
|
|||||||
type stashIDs []models.StashID
|
type stashIDs []models.StashID
|
||||||
|
|
||||||
func (s *stashIDs) Append(o interface{}) {
|
func (s *stashIDs) Append(o interface{}) {
|
||||||
*s = append(*s, *o.(*models.StashID))
|
*s = append(*s, o.(models.StashID))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stashIDs) New() interface{} {
|
func (s *stashIDs) New() interface{} {
|
||||||
@@ -429,10 +413,17 @@ func (s *stashIDs) New() interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *stashIDRepository) get(ctx context.Context, id int) ([]models.StashID, error) {
|
func (r *stashIDRepository) get(ctx context.Context, id int) ([]models.StashID, error) {
|
||||||
query := fmt.Sprintf("SELECT stash_id, endpoint from %s WHERE %s = ?", r.tableName, r.idColumn)
|
query := fmt.Sprintf("SELECT stash_id, endpoint, updated_at from %s WHERE %s = ?", r.tableName, r.idColumn)
|
||||||
var ret stashIDs
|
var ret stashIDs
|
||||||
err := r.query(ctx, query, []interface{}{id}, &ret)
|
err := r.queryFunc(ctx, query, []interface{}{id}, false, func(rows *sqlx.Rows) error {
|
||||||
return []models.StashID(ret), err
|
var v stashIDRow
|
||||||
|
if err := rows.StructScan(&v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ret.Append(v.resolve())
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return ret, err
|
||||||
}
|
}
|
||||||
|
|
||||||
type filesRepository struct {
|
type filesRepository struct {
|
||||||
|
|||||||
@@ -277,17 +277,19 @@ type stashIDTable struct {
|
|||||||
type stashIDRow struct {
|
type stashIDRow struct {
|
||||||
StashID null.String `db:"stash_id"`
|
StashID null.String `db:"stash_id"`
|
||||||
Endpoint null.String `db:"endpoint"`
|
Endpoint null.String `db:"endpoint"`
|
||||||
|
UpdatedAt Timestamp `db:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *stashIDRow) resolve() models.StashID {
|
func (r *stashIDRow) resolve() models.StashID {
|
||||||
return models.StashID{
|
return models.StashID{
|
||||||
StashID: r.StashID.String,
|
StashID: r.StashID.String,
|
||||||
Endpoint: r.Endpoint.String,
|
Endpoint: r.Endpoint.String,
|
||||||
|
UpdatedAt: r.UpdatedAt.Timestamp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *stashIDTable) get(ctx context.Context, id int) ([]models.StashID, error) {
|
func (t *stashIDTable) get(ctx context.Context, id int) ([]models.StashID, error) {
|
||||||
q := dialect.Select("endpoint", "stash_id").From(t.table.table).Where(t.idColumn.Eq(id))
|
q := dialect.Select("endpoint", "stash_id", "updated_at").From(t.table.table).Where(t.idColumn.Eq(id))
|
||||||
|
|
||||||
const single = false
|
const single = false
|
||||||
var ret []models.StashID
|
var ret []models.StashID
|
||||||
@@ -308,8 +310,8 @@ func (t *stashIDTable) get(ctx context.Context, id int) ([]models.StashID, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *stashIDTable) insertJoin(ctx context.Context, id int, v models.StashID) (sql.Result, error) {
|
func (t *stashIDTable) insertJoin(ctx context.Context, id int, v models.StashID) (sql.Result, error) {
|
||||||
q := dialect.Insert(t.table.table).Cols(t.idColumn.GetCol(), "endpoint", "stash_id").Vals(
|
var q = dialect.Insert(t.table.table).Cols(t.idColumn.GetCol(), "endpoint", "stash_id", "updated_at").Vals(
|
||||||
goqu.Vals{id, v.Endpoint, v.StashID},
|
goqu.Vals{id, v.Endpoint, v.StashID, v.UpdatedAt},
|
||||||
)
|
)
|
||||||
ret, err := exec(ctx, q)
|
ret, err := exec(ctx, q)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ fragment SlimPerformerData on Performer {
|
|||||||
stash_ids {
|
stash_ids {
|
||||||
endpoint
|
endpoint
|
||||||
stash_id
|
stash_id
|
||||||
|
updated_at
|
||||||
}
|
}
|
||||||
rating100
|
rating100
|
||||||
death_date
|
death_date
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ fragment PerformerData on Performer {
|
|||||||
stash_ids {
|
stash_ids {
|
||||||
stash_id
|
stash_id
|
||||||
endpoint
|
endpoint
|
||||||
|
updated_at
|
||||||
}
|
}
|
||||||
rating100
|
rating100
|
||||||
details
|
details
|
||||||
|
|||||||
@@ -84,5 +84,6 @@ fragment SlimSceneData on Scene {
|
|||||||
stash_ids {
|
stash_ids {
|
||||||
endpoint
|
endpoint
|
||||||
stash_id
|
stash_id
|
||||||
|
updated_at
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ fragment SceneData on Scene {
|
|||||||
stash_ids {
|
stash_ids {
|
||||||
endpoint
|
endpoint
|
||||||
stash_id
|
stash_id
|
||||||
|
updated_at
|
||||||
}
|
}
|
||||||
|
|
||||||
sceneStreams {
|
sceneStreams {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ fragment SlimStudioData on Studio {
|
|||||||
stash_ids {
|
stash_ids {
|
||||||
endpoint
|
endpoint
|
||||||
stash_id
|
stash_id
|
||||||
|
updated_at
|
||||||
}
|
}
|
||||||
parent_studio {
|
parent_studio {
|
||||||
id
|
id
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ fragment StudioData on Studio {
|
|||||||
stash_ids {
|
stash_ids {
|
||||||
stash_id
|
stash_id
|
||||||
endpoint
|
endpoint
|
||||||
|
updated_at
|
||||||
}
|
}
|
||||||
details
|
details
|
||||||
rating100
|
rating100
|
||||||
|
|||||||
@@ -282,7 +282,10 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
|
|||||||
formik.setFieldValue("penis_length", state.penis_length);
|
formik.setFieldValue("penis_length", state.penis_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
const remoteSiteID = state.remote_site_id;
|
updateStashIDs(state.remote_site_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateStashIDs(remoteSiteID: string | null | undefined) {
|
||||||
if (remoteSiteID && (scraper as IStashBox).endpoint) {
|
if (remoteSiteID && (scraper as IStashBox).endpoint) {
|
||||||
const newIDs =
|
const newIDs =
|
||||||
formik.values.stash_ids?.filter(
|
formik.values.stash_ids?.filter(
|
||||||
@@ -291,6 +294,7 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
|
|||||||
newIDs?.push({
|
newIDs?.push({
|
||||||
endpoint: (scraper as IStashBox).endpoint,
|
endpoint: (scraper as IStashBox).endpoint,
|
||||||
stash_id: remoteSiteID,
|
stash_id: remoteSiteID,
|
||||||
|
updated_at: new Date().toISOString(),
|
||||||
});
|
});
|
||||||
formik.setFieldValue("stash_ids", newIDs);
|
formik.setFieldValue("stash_ids", newIDs);
|
||||||
}
|
}
|
||||||
@@ -438,6 +442,7 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
|
|||||||
setScraper(undefined);
|
setScraper(undefined);
|
||||||
} else {
|
} else {
|
||||||
setScrapedPerformer(result);
|
setScrapedPerformer(result);
|
||||||
|
updateStashIDs(performerResult.remote_site_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -508,6 +508,7 @@ export const SceneEditPanel: React.FC<IProps> = ({
|
|||||||
return {
|
return {
|
||||||
endpoint,
|
endpoint,
|
||||||
stash_id: updatedScene.remote_site_id,
|
stash_id: updatedScene.remote_site_id,
|
||||||
|
updated_at: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -521,6 +522,7 @@ export const SceneEditPanel: React.FC<IProps> = ({
|
|||||||
formik.values.stash_ids.concat({
|
formik.values.stash_ids.concat({
|
||||||
endpoint,
|
endpoint,
|
||||||
stash_id: updatedScene.remote_site_id,
|
stash_id: updatedScene.remote_site_id,
|
||||||
|
updated_at: new Date().toISOString(),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { ExternalLink } from "./ExternalLink";
|
|||||||
export type LinkType = "performers" | "scenes" | "studios";
|
export type LinkType = "performers" | "scenes" | "studios";
|
||||||
|
|
||||||
export const StashIDPill: React.FC<{
|
export const StashIDPill: React.FC<{
|
||||||
stashID: StashId;
|
stashID: Pick<StashId, "endpoint" | "stash_id">;
|
||||||
linkType: LinkType;
|
linkType: LinkType;
|
||||||
}> = ({ stashID, linkType }) => {
|
}> = ({ stashID, linkType }) => {
|
||||||
const { configuration } = React.useContext(ConfigurationContext);
|
const { configuration } = React.useContext(ConfigurationContext);
|
||||||
|
|||||||
@@ -272,6 +272,7 @@ const PerformerModal: React.FC<IPerformerModalProps> = ({
|
|||||||
{
|
{
|
||||||
endpoint,
|
endpoint,
|
||||||
stash_id: remoteSiteID,
|
stash_id: remoteSiteID,
|
||||||
|
updated_at: new Date().toISOString(),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -613,12 +613,14 @@ export const TaggerContext: React.FC = ({ children }) => {
|
|||||||
return {
|
return {
|
||||||
endpoint: e.endpoint,
|
endpoint: e.endpoint,
|
||||||
stash_id: e.stash_id,
|
stash_id: e.stash_id,
|
||||||
|
updated_at: e.updated_at,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
stashIDs.push({
|
stashIDs.push({
|
||||||
stash_id: performer.remote_site_id,
|
stash_id: performer.remote_site_id,
|
||||||
endpoint: currentSource?.sourceInput.stash_box_endpoint,
|
endpoint: currentSource?.sourceInput.stash_box_endpoint,
|
||||||
|
updated_at: new Date().toISOString(),
|
||||||
});
|
});
|
||||||
|
|
||||||
await updatePerformer({
|
await updatePerformer({
|
||||||
@@ -770,12 +772,14 @@ export const TaggerContext: React.FC = ({ children }) => {
|
|||||||
return {
|
return {
|
||||||
endpoint: e.endpoint,
|
endpoint: e.endpoint,
|
||||||
stash_id: e.stash_id,
|
stash_id: e.stash_id,
|
||||||
|
updated_at: e.updated_at,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
stashIDs.push({
|
stashIDs.push({
|
||||||
stash_id: studio.remote_site_id,
|
stash_id: studio.remote_site_id,
|
||||||
endpoint: currentSource?.sourceInput.stash_box_endpoint,
|
endpoint: currentSource?.sourceInput.stash_box_endpoint,
|
||||||
|
updated_at: new Date().toISOString(),
|
||||||
});
|
});
|
||||||
|
|
||||||
await updateStudio({
|
await updateStudio({
|
||||||
|
|||||||
@@ -413,6 +413,7 @@ const StashSearchResult: React.FC<IStashSearchResultProps> = ({
|
|||||||
return {
|
return {
|
||||||
endpoint: s.endpoint,
|
endpoint: s.endpoint,
|
||||||
stash_id: s.stash_id,
|
stash_id: s.stash_id,
|
||||||
|
updated_at: s.updated_at,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter(
|
.filter(
|
||||||
@@ -421,6 +422,7 @@ const StashSearchResult: React.FC<IStashSearchResultProps> = ({
|
|||||||
{
|
{
|
||||||
endpoint: currentSource.sourceInput.stash_box_endpoint,
|
endpoint: currentSource.sourceInput.stash_box_endpoint,
|
||||||
stash_id: scene.remote_site_id,
|
stash_id: scene.remote_site_id,
|
||||||
|
updated_at: new Date().toISOString(),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -198,11 +198,13 @@ const StudioModal: React.FC<IStudioModalProps> = ({
|
|||||||
|
|
||||||
// stashid handling code
|
// stashid handling code
|
||||||
const remoteSiteID = studio.remote_site_id;
|
const remoteSiteID = studio.remote_site_id;
|
||||||
|
const timeNow = new Date().toISOString();
|
||||||
if (remoteSiteID && endpoint) {
|
if (remoteSiteID && endpoint) {
|
||||||
studioData.stash_ids = [
|
studioData.stash_ids = [
|
||||||
{
|
{
|
||||||
endpoint,
|
endpoint,
|
||||||
stash_id: remoteSiteID,
|
stash_id: remoteSiteID,
|
||||||
|
updated_at: timeNow,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -230,6 +232,7 @@ const StudioModal: React.FC<IStudioModalProps> = ({
|
|||||||
{
|
{
|
||||||
endpoint,
|
endpoint,
|
||||||
stash_id: parentRemoteSiteID,
|
stash_id: parentRemoteSiteID,
|
||||||
|
updated_at: timeNow,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
export const getStashIDs = (ids?: { stash_id: string; endpoint: string }[]) =>
|
export const getStashIDs = (
|
||||||
(ids ?? []).map(({ stash_id, endpoint }) => ({
|
ids?: { stash_id: string; endpoint: string; updated_at: string }[]
|
||||||
|
) =>
|
||||||
|
(ids ?? []).map(({ stash_id, endpoint, updated_at }) => ({
|
||||||
stash_id,
|
stash_id,
|
||||||
endpoint,
|
endpoint,
|
||||||
|
updated_at,
|
||||||
}));
|
}));
|
||||||
|
|||||||
Reference in New Issue
Block a user