mirror of
https://github.com/stashapp/stash.git
synced 2025-12-06 08:26:00 +01:00
Add stash_ids to performer, scene, studio import/export (#1916)
* add stash_ids to performer, scene, studio import/export
This commit is contained in:
parent
87036a07bc
commit
c6a326ca64
13 changed files with 156 additions and 55 deletions
|
|
@ -9,32 +9,33 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Performer struct {
|
type Performer struct {
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
Gender string `json:"gender,omitempty"`
|
Gender string `json:"gender,omitempty"`
|
||||||
URL string `json:"url,omitempty"`
|
URL string `json:"url,omitempty"`
|
||||||
Twitter string `json:"twitter,omitempty"`
|
Twitter string `json:"twitter,omitempty"`
|
||||||
Instagram string `json:"instagram,omitempty"`
|
Instagram string `json:"instagram,omitempty"`
|
||||||
Birthdate string `json:"birthdate,omitempty"`
|
Birthdate string `json:"birthdate,omitempty"`
|
||||||
Ethnicity string `json:"ethnicity,omitempty"`
|
Ethnicity string `json:"ethnicity,omitempty"`
|
||||||
Country string `json:"country,omitempty"`
|
Country string `json:"country,omitempty"`
|
||||||
EyeColor string `json:"eye_color,omitempty"`
|
EyeColor string `json:"eye_color,omitempty"`
|
||||||
Height string `json:"height,omitempty"`
|
Height string `json:"height,omitempty"`
|
||||||
Measurements string `json:"measurements,omitempty"`
|
Measurements string `json:"measurements,omitempty"`
|
||||||
FakeTits string `json:"fake_tits,omitempty"`
|
FakeTits string `json:"fake_tits,omitempty"`
|
||||||
CareerLength string `json:"career_length,omitempty"`
|
CareerLength string `json:"career_length,omitempty"`
|
||||||
Tattoos string `json:"tattoos,omitempty"`
|
Tattoos string `json:"tattoos,omitempty"`
|
||||||
Piercings string `json:"piercings,omitempty"`
|
Piercings string `json:"piercings,omitempty"`
|
||||||
Aliases string `json:"aliases,omitempty"`
|
Aliases string `json:"aliases,omitempty"`
|
||||||
Favorite bool `json:"favorite,omitempty"`
|
Favorite bool `json:"favorite,omitempty"`
|
||||||
Tags []string `json:"tags,omitempty"`
|
Tags []string `json:"tags,omitempty"`
|
||||||
Image string `json:"image,omitempty"`
|
Image string `json:"image,omitempty"`
|
||||||
CreatedAt models.JSONTime `json:"created_at,omitempty"`
|
CreatedAt models.JSONTime `json:"created_at,omitempty"`
|
||||||
UpdatedAt models.JSONTime `json:"updated_at,omitempty"`
|
UpdatedAt models.JSONTime `json:"updated_at,omitempty"`
|
||||||
Rating int `json:"rating,omitempty"`
|
Rating int `json:"rating,omitempty"`
|
||||||
Details string `json:"details,omitempty"`
|
Details string `json:"details,omitempty"`
|
||||||
DeathDate string `json:"death_date,omitempty"`
|
DeathDate string `json:"death_date,omitempty"`
|
||||||
HairColor string `json:"hair_color,omitempty"`
|
HairColor string `json:"hair_color,omitempty"`
|
||||||
Weight int `json:"weight,omitempty"`
|
Weight int `json:"weight,omitempty"`
|
||||||
|
StashIDs []models.StashID `json:"stash_ids,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadPerformerFile(filePath string) (*Performer, error) {
|
func LoadPerformerFile(filePath string) (*Performer, error) {
|
||||||
|
|
|
||||||
|
|
@ -36,26 +36,27 @@ type SceneMovie struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Scene struct {
|
type Scene struct {
|
||||||
Title string `json:"title,omitempty"`
|
Title string `json:"title,omitempty"`
|
||||||
Checksum string `json:"checksum,omitempty"`
|
Checksum string `json:"checksum,omitempty"`
|
||||||
OSHash string `json:"oshash,omitempty"`
|
OSHash string `json:"oshash,omitempty"`
|
||||||
Phash string `json:"phash,omitempty"`
|
Phash string `json:"phash,omitempty"`
|
||||||
Studio string `json:"studio,omitempty"`
|
Studio string `json:"studio,omitempty"`
|
||||||
URL string `json:"url,omitempty"`
|
URL string `json:"url,omitempty"`
|
||||||
Date string `json:"date,omitempty"`
|
Date string `json:"date,omitempty"`
|
||||||
Rating int `json:"rating,omitempty"`
|
Rating int `json:"rating,omitempty"`
|
||||||
Organized bool `json:"organized,omitempty"`
|
Organized bool `json:"organized,omitempty"`
|
||||||
OCounter int `json:"o_counter,omitempty"`
|
OCounter int `json:"o_counter,omitempty"`
|
||||||
Details string `json:"details,omitempty"`
|
Details string `json:"details,omitempty"`
|
||||||
Galleries []string `json:"galleries,omitempty"`
|
Galleries []string `json:"galleries,omitempty"`
|
||||||
Performers []string `json:"performers,omitempty"`
|
Performers []string `json:"performers,omitempty"`
|
||||||
Movies []SceneMovie `json:"movies,omitempty"`
|
Movies []SceneMovie `json:"movies,omitempty"`
|
||||||
Tags []string `json:"tags,omitempty"`
|
Tags []string `json:"tags,omitempty"`
|
||||||
Markers []SceneMarker `json:"markers,omitempty"`
|
Markers []SceneMarker `json:"markers,omitempty"`
|
||||||
File *SceneFile `json:"file,omitempty"`
|
File *SceneFile `json:"file,omitempty"`
|
||||||
Cover string `json:"cover,omitempty"`
|
Cover string `json:"cover,omitempty"`
|
||||||
CreatedAt models.JSONTime `json:"created_at,omitempty"`
|
CreatedAt models.JSONTime `json:"created_at,omitempty"`
|
||||||
UpdatedAt models.JSONTime `json:"updated_at,omitempty"`
|
UpdatedAt models.JSONTime `json:"updated_at,omitempty"`
|
||||||
|
StashIDs []models.StashID `json:"stash_ids,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadSceneFile(filePath string) (*Scene, error) {
|
func LoadSceneFile(filePath string) (*Scene, error) {
|
||||||
|
|
|
||||||
|
|
@ -9,15 +9,16 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Studio struct {
|
type Studio struct {
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
URL string `json:"url,omitempty"`
|
URL string `json:"url,omitempty"`
|
||||||
ParentStudio string `json:"parent_studio,omitempty"`
|
ParentStudio string `json:"parent_studio,omitempty"`
|
||||||
Image string `json:"image,omitempty"`
|
Image string `json:"image,omitempty"`
|
||||||
CreatedAt models.JSONTime `json:"created_at,omitempty"`
|
CreatedAt models.JSONTime `json:"created_at,omitempty"`
|
||||||
UpdatedAt models.JSONTime `json:"updated_at,omitempty"`
|
UpdatedAt models.JSONTime `json:"updated_at,omitempty"`
|
||||||
Rating int `json:"rating,omitempty"`
|
Rating int `json:"rating,omitempty"`
|
||||||
Details string `json:"details,omitempty"`
|
Details string `json:"details,omitempty"`
|
||||||
Aliases []string `json:"aliases,omitempty"`
|
Aliases []string `json:"aliases,omitempty"`
|
||||||
|
StashIDs []models.StashID `json:"stash_ids,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadStudioFile(filePath string) (*Studio, error) {
|
func LoadStudioFile(filePath string) (*Studio, error) {
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,18 @@ func ToJSON(reader models.PerformerReader, performer *models.Performer) (*jsonsc
|
||||||
newPerformerJSON.Image = utils.GetBase64StringFromData(image)
|
newPerformerJSON.Image = utils.GetBase64StringFromData(image)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stashIDs, _ := reader.GetStashIDs(performer.ID)
|
||||||
|
var ret []models.StashID
|
||||||
|
for _, stashID := range stashIDs {
|
||||||
|
newJoin := models.StashID{
|
||||||
|
StashID: stashID.StashID,
|
||||||
|
Endpoint: stashID.Endpoint,
|
||||||
|
}
|
||||||
|
ret = append(ret, newJoin)
|
||||||
|
}
|
||||||
|
|
||||||
|
newPerformerJSON.StashIDs = ret
|
||||||
|
|
||||||
return &newPerformerJSON, nil
|
return &newPerformerJSON, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,14 @@ const (
|
||||||
|
|
||||||
var imageBytes = []byte("imageBytes")
|
var imageBytes = []byte("imageBytes")
|
||||||
|
|
||||||
|
var stashID = models.StashID{
|
||||||
|
StashID: "StashID",
|
||||||
|
Endpoint: "Endpoint",
|
||||||
|
}
|
||||||
|
var stashIDs = []*models.StashID{
|
||||||
|
&stashID,
|
||||||
|
}
|
||||||
|
|
||||||
const image = "aW1hZ2VCeXRlcw=="
|
const image = "aW1hZ2VCeXRlcw=="
|
||||||
|
|
||||||
var birthDate = models.SQLiteDate{
|
var birthDate = models.SQLiteDate{
|
||||||
|
|
@ -144,6 +152,9 @@ func createFullJSONPerformer(name string, image string) *jsonschema.Performer {
|
||||||
DeathDate: deathDate.String,
|
DeathDate: deathDate.String,
|
||||||
HairColor: hairColor,
|
HairColor: hairColor,
|
||||||
Weight: weight,
|
Weight: weight,
|
||||||
|
StashIDs: []models.StashID{
|
||||||
|
stashID,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -197,6 +208,9 @@ func TestToJSON(t *testing.T) {
|
||||||
mockPerformerReader.On("GetImage", noImageID).Return(nil, nil).Once()
|
mockPerformerReader.On("GetImage", noImageID).Return(nil, nil).Once()
|
||||||
mockPerformerReader.On("GetImage", errImageID).Return(nil, imageErr).Once()
|
mockPerformerReader.On("GetImage", errImageID).Return(nil, imageErr).Once()
|
||||||
|
|
||||||
|
mockPerformerReader.On("GetStashIDs", performerID).Return(stashIDs, nil).Once()
|
||||||
|
mockPerformerReader.On("GetStashIDs", noImageID).Return(nil, nil).Once()
|
||||||
|
|
||||||
for i, s := range scenarios {
|
for i, s := range scenarios {
|
||||||
tag := s.input
|
tag := s.input
|
||||||
json, err := ToJSON(mockPerformerReader, &tag)
|
json, err := ToJSON(mockPerformerReader, &tag)
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,12 @@ func (i *Importer) PostImport(id int) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(i.Input.StashIDs) > 0 {
|
||||||
|
if err := i.ReaderWriter.UpdateStashIDs(id, i.Input.StashIDs); err != nil {
|
||||||
|
return fmt.Errorf("error setting stash id: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,18 @@ func ToBasicJSON(reader models.SceneReader, scene *models.Scene) (*jsonschema.Sc
|
||||||
newSceneJSON.Cover = utils.GetBase64StringFromData(cover)
|
newSceneJSON.Cover = utils.GetBase64StringFromData(cover)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stashIDs, _ := reader.GetStashIDs(scene.ID)
|
||||||
|
var ret []models.StashID
|
||||||
|
for _, stashID := range stashIDs {
|
||||||
|
newJoin := models.StashID{
|
||||||
|
StashID: stashID.StashID,
|
||||||
|
Endpoint: stashID.Endpoint,
|
||||||
|
}
|
||||||
|
ret = append(ret, newJoin)
|
||||||
|
}
|
||||||
|
|
||||||
|
newSceneJSON.StashIDs = ret
|
||||||
|
|
||||||
return &newSceneJSON, nil
|
return &newSceneJSON, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,14 @@ var names = []string{
|
||||||
|
|
||||||
var imageBytes = []byte("imageBytes")
|
var imageBytes = []byte("imageBytes")
|
||||||
|
|
||||||
|
var stashID = models.StashID{
|
||||||
|
StashID: "StashID",
|
||||||
|
Endpoint: "Endpoint",
|
||||||
|
}
|
||||||
|
var stashIDs = []*models.StashID{
|
||||||
|
&stashID,
|
||||||
|
}
|
||||||
|
|
||||||
const imageBase64 = "aW1hZ2VCeXRlcw=="
|
const imageBase64 = "aW1hZ2VCeXRlcw=="
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -174,6 +182,9 @@ func createFullJSONScene(image string) *jsonschema.Scene {
|
||||||
Time: updateTime,
|
Time: updateTime,
|
||||||
},
|
},
|
||||||
Cover: image,
|
Cover: image,
|
||||||
|
StashIDs: []models.StashID{
|
||||||
|
stashID,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -222,6 +233,9 @@ func TestToJSON(t *testing.T) {
|
||||||
mockSceneReader.On("GetCover", noImageID).Return(nil, nil).Once()
|
mockSceneReader.On("GetCover", noImageID).Return(nil, nil).Once()
|
||||||
mockSceneReader.On("GetCover", errImageID).Return(nil, imageErr).Once()
|
mockSceneReader.On("GetCover", errImageID).Return(nil, imageErr).Once()
|
||||||
|
|
||||||
|
mockSceneReader.On("GetStashIDs", sceneID).Return(stashIDs, nil).Once()
|
||||||
|
mockSceneReader.On("GetStashIDs", noImageID).Return(nil, nil).Once()
|
||||||
|
|
||||||
for i, s := range scenarios {
|
for i, s := range scenarios {
|
||||||
scene := s.input
|
scene := s.input
|
||||||
json, err := ToBasicJSON(mockSceneReader, &scene)
|
json, err := ToBasicJSON(mockSceneReader, &scene)
|
||||||
|
|
|
||||||
|
|
@ -386,6 +386,12 @@ func (i *Importer) PostImport(id int) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(i.Input.StashIDs) > 0 {
|
||||||
|
if err := i.ReaderWriter.UpdateStashIDs(id, i.Input.StashIDs); err != nil {
|
||||||
|
return fmt.Errorf("error setting stash id: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,5 +58,17 @@ func ToJSON(reader models.StudioReader, studio *models.Studio) (*jsonschema.Stud
|
||||||
newStudioJSON.Image = utils.GetBase64StringFromData(image)
|
newStudioJSON.Image = utils.GetBase64StringFromData(image)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stashIDs, _ := reader.GetStashIDs(studio.ID)
|
||||||
|
var ret []models.StashID
|
||||||
|
for _, stashID := range stashIDs {
|
||||||
|
newJoin := models.StashID{
|
||||||
|
StashID: stashID.StashID,
|
||||||
|
Endpoint: stashID.Endpoint,
|
||||||
|
}
|
||||||
|
ret = append(ret, newJoin)
|
||||||
|
}
|
||||||
|
|
||||||
|
newStudioJSON.StashIDs = ret
|
||||||
|
|
||||||
return &newStudioJSON, nil
|
return &newStudioJSON, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,14 @@ var parentStudio models.Studio = models.Studio{
|
||||||
|
|
||||||
var imageBytes = []byte("imageBytes")
|
var imageBytes = []byte("imageBytes")
|
||||||
|
|
||||||
|
var stashID = models.StashID{
|
||||||
|
StashID: "StashID",
|
||||||
|
Endpoint: "Endpoint",
|
||||||
|
}
|
||||||
|
var stashIDs = []*models.StashID{
|
||||||
|
&stashID,
|
||||||
|
}
|
||||||
|
|
||||||
const image = "aW1hZ2VCeXRlcw=="
|
const image = "aW1hZ2VCeXRlcw=="
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -95,6 +103,9 @@ func createFullJSONStudio(parentStudio, image string, aliases []string) *jsonsch
|
||||||
Image: image,
|
Image: image,
|
||||||
Rating: rating,
|
Rating: rating,
|
||||||
Aliases: aliases,
|
Aliases: aliases,
|
||||||
|
StashIDs: []models.StashID{
|
||||||
|
stashID,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -180,6 +191,10 @@ func TestToJSON(t *testing.T) {
|
||||||
mockStudioReader.On("GetAliases", missingParentStudioID).Return(nil, nil).Once()
|
mockStudioReader.On("GetAliases", missingParentStudioID).Return(nil, nil).Once()
|
||||||
mockStudioReader.On("GetAliases", errAliasID).Return(nil, aliasErr).Once()
|
mockStudioReader.On("GetAliases", errAliasID).Return(nil, aliasErr).Once()
|
||||||
|
|
||||||
|
mockStudioReader.On("GetStashIDs", studioID).Return(stashIDs, nil).Once()
|
||||||
|
mockStudioReader.On("GetStashIDs", noImageID).Return(nil, nil).Once()
|
||||||
|
mockStudioReader.On("GetStashIDs", missingParentStudioID).Return(stashIDs, nil).Once()
|
||||||
|
|
||||||
for i, s := range scenarios {
|
for i, s := range scenarios {
|
||||||
studio := s.input
|
studio := s.input
|
||||||
json, err := ToJSON(mockStudioReader, &studio)
|
json, err := ToJSON(mockStudioReader, &studio)
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,12 @@ func (i *Importer) PostImport(id int) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(i.Input.StashIDs) > 0 {
|
||||||
|
if err := i.ReaderWriter.UpdateStashIDs(id, i.Input.StashIDs); err != nil {
|
||||||
|
return fmt.Errorf("error setting stash id: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := i.ReaderWriter.UpdateAliases(id, i.Input.Aliases); err != nil {
|
if err := i.ReaderWriter.UpdateAliases(id, i.Input.Aliases); err != nil {
|
||||||
return fmt.Errorf("error setting tag aliases: %v", err)
|
return fmt.Errorf("error setting tag aliases: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
* Optimised scanning process. ([#1816](https://github.com/stashapp/stash/pull/1816))
|
* Optimised scanning process. ([#1816](https://github.com/stashapp/stash/pull/1816))
|
||||||
|
|
||||||
### 🐛 Bug fixes
|
### 🐛 Bug fixes
|
||||||
|
* Include stash ids in import/export. ([#1916](https://github.com/stashapp/stash/pull/1916))
|
||||||
* Fix tiny menu items in scrape menu when a stash-box instance has no name. ([#1889](https://github.com/stashapp/stash/pull/1889))
|
* Fix tiny menu items in scrape menu when a stash-box instance has no name. ([#1889](https://github.com/stashapp/stash/pull/1889))
|
||||||
* Fix creating missing entities removing the incorrect entry from the missing list in the scrape dialog. ([#1890](https://github.com/stashapp/stash/pull/1890))
|
* Fix creating missing entities removing the incorrect entry from the missing list in the scrape dialog. ([#1890](https://github.com/stashapp/stash/pull/1890))
|
||||||
* Allow creating missing Studio during movie scrape. ([#1899](https://github.com/stashapp/stash/pull/1899))
|
* Allow creating missing Studio during movie scrape. ([#1899](https://github.com/stashapp/stash/pull/1899))
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue