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:
WithoutPants
2023-07-12 11:51:52 +10:00
committed by GitHub
parent 76a4bfa49a
commit 67d4f9729a
50 changed files with 978 additions and 205 deletions

View File

@@ -39,10 +39,12 @@ type SceneMovie struct {
}
type Scene struct {
Title string `json:"title,omitempty"`
Code string `json:"code,omitempty"`
Studio string `json:"studio,omitempty"`
Title string `json:"title,omitempty"`
Code string `json:"code,omitempty"`
Studio string `json:"studio,omitempty"`
// deprecated - for import only
URL string `json:"url,omitempty"`
URLs []string `json:"urls,omitempty"`
Date string `json:"date,omitempty"`
Rating int `json:"rating,omitempty"`
Organized bool `json:"organized,omitempty"`

View File

@@ -624,6 +624,29 @@ func (_m *SceneReaderWriter) GetTagIDs(ctx context.Context, relatedID int) ([]in
return r0, r1
}
// GetURLs provides a mock function with given fields: ctx, relatedID
func (_m *SceneReaderWriter) GetURLs(ctx context.Context, relatedID int) ([]string, error) {
ret := _m.Called(ctx, relatedID)
var r0 []string
if rf, ok := ret.Get(0).(func(context.Context, int) []string); ok {
r0 = rf(ctx, relatedID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]string)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, int) error); ok {
r1 = rf(ctx, relatedID)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// HasCover provides a mock function with given fields: ctx, sceneID
func (_m *SceneReaderWriter) HasCover(ctx context.Context, sceneID int) (bool, error) {
ret := _m.Called(ctx, sceneID)

View File

@@ -17,7 +17,6 @@ type Scene struct {
Code string `json:"code"`
Details string `json:"details"`
Director string `json:"director"`
URL string `json:"url"`
Date *Date `json:"date"`
// Rating expressed in 1-100 scale
Rating *int `json:"rating"`
@@ -43,6 +42,7 @@ type Scene struct {
PlayDuration float64 `json:"play_duration"`
PlayCount int `json:"play_count"`
URLs RelatedStrings `json:"urls"`
GalleryIDs RelatedIDs `json:"gallery_ids"`
TagIDs RelatedIDs `json:"tag_ids"`
PerformerIDs RelatedIDs `json:"performer_ids"`
@@ -50,6 +50,12 @@ type Scene struct {
StashIDs RelatedStashIDs `json:"stash_ids"`
}
func (s *Scene) LoadURLs(ctx context.Context, l URLLoader) error {
return s.URLs.load(func() ([]string, error) {
return l.GetURLs(ctx, s.ID)
})
}
func (s *Scene) LoadFiles(ctx context.Context, l VideoFileLoader) error {
return s.Files.load(func() ([]*file.VideoFile, error) {
return l.GetFiles(ctx, s.ID)
@@ -110,6 +116,10 @@ func (s *Scene) LoadStashIDs(ctx context.Context, l StashIDLoader) error {
}
func (s *Scene) LoadRelationships(ctx context.Context, l SceneReader) error {
if err := s.LoadURLs(ctx, l); err != nil {
return err
}
if err := s.LoadGalleryIDs(ctx, l); err != nil {
return err
}
@@ -144,7 +154,6 @@ type ScenePartial struct {
Code OptionalString
Details OptionalString
Director OptionalString
URL OptionalString
Date OptionalDate
// Rating expressed in 1-100 scale
Rating OptionalInt
@@ -158,6 +167,7 @@ type ScenePartial struct {
PlayCount OptionalInt
LastPlayedAt OptionalTime
URLs *UpdateStrings
GalleryIDs *UpdateIDs
TagIDs *UpdateIDs
PerformerIDs *UpdateIDs
@@ -193,6 +203,7 @@ type SceneUpdateInput struct {
Rating100 *int `json:"rating100"`
OCounter *int `json:"o_counter"`
Organized *bool `json:"organized"`
Urls []string `json:"urls"`
StudioID *string `json:"studio_id"`
GalleryIds []string `json:"gallery_ids"`
PerformerIds []string `json:"performer_ids"`
@@ -227,7 +238,7 @@ func (s ScenePartial) UpdateInput(id int) SceneUpdateInput {
Code: s.Code.Ptr(),
Details: s.Details.Ptr(),
Director: s.Director.Ptr(),
URL: s.URL.Ptr(),
Urls: s.URLs.Strings(),
Date: dateStr,
Rating100: s.Rating.Ptr(),
Organized: s.Organized.Ptr(),

View File

@@ -37,11 +37,14 @@ func TestScenePartial_UpdateInput(t *testing.T) {
"full",
id,
ScenePartial{
Title: NewOptionalString(title),
Code: NewOptionalString(code),
Details: NewOptionalString(details),
Director: NewOptionalString(director),
URL: NewOptionalString(url),
Title: NewOptionalString(title),
Code: NewOptionalString(code),
Details: NewOptionalString(details),
Director: NewOptionalString(director),
URLs: &UpdateStrings{
Values: []string{url},
Mode: RelationshipUpdateModeSet,
},
Date: NewOptionalDate(dateObj),
Rating: NewOptionalInt(rating100),
Organized: NewOptionalBool(organized),
@@ -53,7 +56,7 @@ func TestScenePartial_UpdateInput(t *testing.T) {
Code: &code,
Details: &details,
Director: &director,
URL: &url,
Urls: []string{url},
Date: &date,
Rating: &ratingLegacy,
Rating100: &rating100,

View File

@@ -42,6 +42,10 @@ type AliasLoader interface {
GetAliases(ctx context.Context, relatedID int) ([]string, error)
}
type URLLoader interface {
GetURLs(ctx context.Context, relatedID int) ([]string, error)
}
// RelatedIDs represents a list of related IDs.
// TODO - this can be made generic
type RelatedIDs struct {

View File

@@ -159,6 +159,7 @@ type SceneReader interface {
FindByGalleryID(ctx context.Context, performerID int) ([]*Scene, error)
FindDuplicates(ctx context.Context, distance int, durationDiff float64) ([][]*Scene, error)
URLLoader
GalleryIDLoader
PerformerIDLoader
TagIDLoader

View File

@@ -110,3 +110,11 @@ type UpdateStrings struct {
Values []string `json:"values"`
Mode RelationshipUpdateMode `json:"mode"`
}
func (u *UpdateStrings) Strings() []string {
if u == nil {
return nil
}
return u.Values
}