mirror of
https://github.com/stashapp/stash.git
synced 2025-12-18 04:44:37 +03:00
File storage rewrite (#2676)
* Restructure data layer part 2 (#2599) * Refactor and separate image model * Refactor image query builder * Handle relationships in image query builder * Remove relationship management methods * Refactor gallery model/query builder * Add scenes to gallery model * Convert scene model * Refactor scene models * Remove unused methods * Add unit tests for gallery * Add image tests * Add scene tests * Convert unnecessary scene value pointers to values * Convert unnecessary pointer values to values * Refactor scene partial * Add scene partial tests * Refactor ImagePartial * Add image partial tests * Refactor gallery partial update * Add partial gallery update tests * Use zero/null package for null values * Add files and scan system * Add sqlite implementation for files/folders * Add unit tests for files/folders * Image refactors * Update image data layer * Refactor gallery model and creation * Refactor scene model * Refactor scenes * Don't set title from filename * Allow galleries to freely add/remove images * Add multiple scene file support to graphql and UI * Add multiple file support for images in graphql/UI * Add multiple file for galleries in graphql/UI * Remove use of some deprecated fields * Remove scene path usage * Remove gallery path usage * Remove path from image * Move funscript to video file * Refactor caption detection * Migrate existing data * Add post commit/rollback hook system * Lint. Comment out import/export tests * Add WithDatabase read only wrapper * Prepend tasks to list * Add 32 pre-migration * Add warnings in release and migration notes
This commit is contained in:
19
pkg/models/date.go
Normal file
19
pkg/models/date.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
// Date wraps a time.Time with a format of "YYYY-MM-DD"
|
||||
type Date struct {
|
||||
time.Time
|
||||
}
|
||||
|
||||
const dateFormat = "2006-01-02"
|
||||
|
||||
func (d Date) String() string {
|
||||
return d.Format(dateFormat)
|
||||
}
|
||||
|
||||
func NewDate(s string) Date {
|
||||
t, _ := time.Parse(dateFormat, s)
|
||||
return Date{t}
|
||||
}
|
||||
80
pkg/models/file.go
Normal file
80
pkg/models/file.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/stashapp/stash/pkg/file"
|
||||
)
|
||||
|
||||
type FileQueryOptions struct {
|
||||
QueryOptions
|
||||
FileFilter *FileFilterType
|
||||
}
|
||||
|
||||
type FileFilterType struct {
|
||||
And *FileFilterType `json:"AND"`
|
||||
Or *FileFilterType `json:"OR"`
|
||||
Not *FileFilterType `json:"NOT"`
|
||||
|
||||
// Filter by path
|
||||
Path *StringCriterionInput `json:"path"`
|
||||
}
|
||||
|
||||
func PathsFileFilter(paths []string) *FileFilterType {
|
||||
if paths == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
sep := string(filepath.Separator)
|
||||
|
||||
var ret *FileFilterType
|
||||
var or *FileFilterType
|
||||
for _, p := range paths {
|
||||
newOr := &FileFilterType{}
|
||||
if or != nil {
|
||||
or.Or = newOr
|
||||
} else {
|
||||
ret = newOr
|
||||
}
|
||||
|
||||
or = newOr
|
||||
|
||||
if !strings.HasSuffix(p, sep) {
|
||||
p += sep
|
||||
}
|
||||
|
||||
or.Path = &StringCriterionInput{
|
||||
Modifier: CriterionModifierEquals,
|
||||
Value: p + "%",
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
type FileQueryResult struct {
|
||||
// can't use QueryResult because id type is wrong
|
||||
|
||||
IDs []file.ID
|
||||
Count int
|
||||
|
||||
finder file.Finder
|
||||
files []file.File
|
||||
resolveErr error
|
||||
}
|
||||
|
||||
func NewFileQueryResult(finder file.Finder) *FileQueryResult {
|
||||
return &FileQueryResult{
|
||||
finder: finder,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *FileQueryResult) Resolve(ctx context.Context) ([]file.File, error) {
|
||||
// cache results
|
||||
if r.files == nil && r.resolveErr == nil {
|
||||
r.files, r.resolveErr = r.finder.Find(ctx, r.IDs...)
|
||||
}
|
||||
return r.files, r.resolveErr
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
package models
|
||||
|
||||
import "context"
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/stashapp/stash/pkg/file"
|
||||
)
|
||||
|
||||
type GalleryFilterType struct {
|
||||
And *GalleryFilterType `json:"AND"`
|
||||
@@ -71,30 +75,23 @@ type GalleryDestroyInput struct {
|
||||
type GalleryReader interface {
|
||||
Find(ctx context.Context, id int) (*Gallery, error)
|
||||
FindMany(ctx context.Context, ids []int) ([]*Gallery, error)
|
||||
FindByChecksum(ctx context.Context, checksum string) (*Gallery, error)
|
||||
FindByChecksum(ctx context.Context, checksum string) ([]*Gallery, error)
|
||||
FindByChecksums(ctx context.Context, checksums []string) ([]*Gallery, error)
|
||||
FindByPath(ctx context.Context, path string) (*Gallery, error)
|
||||
FindByPath(ctx context.Context, path string) ([]*Gallery, error)
|
||||
FindBySceneID(ctx context.Context, sceneID int) ([]*Gallery, error)
|
||||
FindByImageID(ctx context.Context, imageID int) ([]*Gallery, error)
|
||||
Count(ctx context.Context) (int, error)
|
||||
All(ctx context.Context) ([]*Gallery, error)
|
||||
Query(ctx context.Context, galleryFilter *GalleryFilterType, findFilter *FindFilterType) ([]*Gallery, int, error)
|
||||
QueryCount(ctx context.Context, galleryFilter *GalleryFilterType, findFilter *FindFilterType) (int, error)
|
||||
GetPerformerIDs(ctx context.Context, galleryID int) ([]int, error)
|
||||
GetTagIDs(ctx context.Context, galleryID int) ([]int, error)
|
||||
GetSceneIDs(ctx context.Context, galleryID int) ([]int, error)
|
||||
GetImageIDs(ctx context.Context, galleryID int) ([]int, error)
|
||||
}
|
||||
|
||||
type GalleryWriter interface {
|
||||
Create(ctx context.Context, newGallery Gallery) (*Gallery, error)
|
||||
Update(ctx context.Context, updatedGallery Gallery) (*Gallery, error)
|
||||
UpdatePartial(ctx context.Context, updatedGallery GalleryPartial) (*Gallery, error)
|
||||
UpdateFileModTime(ctx context.Context, id int, modTime NullSQLiteTimestamp) error
|
||||
Create(ctx context.Context, newGallery *Gallery, fileIDs []file.ID) error
|
||||
Update(ctx context.Context, updatedGallery *Gallery) error
|
||||
UpdatePartial(ctx context.Context, id int, updatedGallery GalleryPartial) (*Gallery, error)
|
||||
Destroy(ctx context.Context, id int) error
|
||||
UpdatePerformers(ctx context.Context, galleryID int, performerIDs []int) error
|
||||
UpdateTags(ctx context.Context, galleryID int, tagIDs []int) error
|
||||
UpdateScenes(ctx context.Context, galleryID int, sceneIDs []int) error
|
||||
UpdateImages(ctx context.Context, galleryID int, imageIDs []int) error
|
||||
}
|
||||
|
||||
|
||||
@@ -92,37 +92,25 @@ type ImageReader interface {
|
||||
ImageFinder
|
||||
// TODO - remove this in another PR
|
||||
Find(ctx context.Context, id int) (*Image, error)
|
||||
FindByChecksum(ctx context.Context, checksum string) (*Image, error)
|
||||
FindByChecksum(ctx context.Context, checksum string) ([]*Image, error)
|
||||
FindByGalleryID(ctx context.Context, galleryID int) ([]*Image, error)
|
||||
CountByGalleryID(ctx context.Context, galleryID int) (int, error)
|
||||
FindByPath(ctx context.Context, path string) (*Image, error)
|
||||
// FindByPerformerID(performerID int) ([]*Image, error)
|
||||
// CountByPerformerID(performerID int) (int, error)
|
||||
// FindByStudioID(studioID int) ([]*Image, error)
|
||||
FindByPath(ctx context.Context, path string) ([]*Image, error)
|
||||
Count(ctx context.Context) (int, error)
|
||||
Size(ctx context.Context) (float64, error)
|
||||
// SizeCount() (string, error)
|
||||
// CountByStudioID(studioID int) (int, error)
|
||||
// CountByTagID(tagID int) (int, error)
|
||||
All(ctx context.Context) ([]*Image, error)
|
||||
Query(ctx context.Context, options ImageQueryOptions) (*ImageQueryResult, error)
|
||||
QueryCount(ctx context.Context, imageFilter *ImageFilterType, findFilter *FindFilterType) (int, error)
|
||||
GetGalleryIDs(ctx context.Context, imageID int) ([]int, error)
|
||||
GetTagIDs(ctx context.Context, imageID int) ([]int, error)
|
||||
GetPerformerIDs(ctx context.Context, imageID int) ([]int, error)
|
||||
}
|
||||
|
||||
type ImageWriter interface {
|
||||
Create(ctx context.Context, newImage Image) (*Image, error)
|
||||
Update(ctx context.Context, updatedImage ImagePartial) (*Image, error)
|
||||
UpdateFull(ctx context.Context, updatedImage Image) (*Image, error)
|
||||
Create(ctx context.Context, newImage *ImageCreateInput) error
|
||||
Update(ctx context.Context, updatedImage *Image) error
|
||||
UpdatePartial(ctx context.Context, id int, partial ImagePartial) (*Image, error)
|
||||
IncrementOCounter(ctx context.Context, id int) (int, error)
|
||||
DecrementOCounter(ctx context.Context, id int) (int, error)
|
||||
ResetOCounter(ctx context.Context, id int) (int, error)
|
||||
Destroy(ctx context.Context, id int) error
|
||||
UpdateGalleries(ctx context.Context, imageID int, galleryIDs []int) error
|
||||
UpdatePerformers(ctx context.Context, imageID int, performerIDs []int) error
|
||||
UpdateTags(ctx context.Context, imageID int, tagIDs []int) error
|
||||
}
|
||||
|
||||
type ImageReaderWriter interface {
|
||||
|
||||
39
pkg/models/int64.go
Normal file
39
pkg/models/int64.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
"github.com/stashapp/stash/pkg/logger"
|
||||
)
|
||||
|
||||
var ErrInt64 = errors.New("cannot parse Int64")
|
||||
|
||||
func MarshalInt64(v int64) graphql.Marshaler {
|
||||
return graphql.WriterFunc(func(w io.Writer) {
|
||||
_, err := io.WriteString(w, strconv.FormatInt(v, 10))
|
||||
if err != nil {
|
||||
logger.Warnf("could not marshal int64: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func UnmarshalInt64(v interface{}) (int64, error) {
|
||||
if tmpStr, ok := v.(string); ok {
|
||||
if len(tmpStr) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
ret, err := strconv.ParseInt(tmpStr, 10, 64)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot parse %v as Int64: %w", tmpStr, err)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf("%w: not a string", ErrInt64)
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
type ImageFile struct {
|
||||
ModTime json.JSONTime `json:"mod_time,omitempty"`
|
||||
Size int `json:"size"`
|
||||
Size int64 `json:"size"`
|
||||
Width int `json:"width"`
|
||||
Height int `json:"height"`
|
||||
}
|
||||
|
||||
@@ -10,34 +10,34 @@ import (
|
||||
)
|
||||
|
||||
type Performer struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Gender string `json:"gender,omitempty"`
|
||||
URL string `json:"url,omitempty"`
|
||||
Twitter string `json:"twitter,omitempty"`
|
||||
Instagram string `json:"instagram,omitempty"`
|
||||
Birthdate string `json:"birthdate,omitempty"`
|
||||
Ethnicity string `json:"ethnicity,omitempty"`
|
||||
Country string `json:"country,omitempty"`
|
||||
EyeColor string `json:"eye_color,omitempty"`
|
||||
Height string `json:"height,omitempty"`
|
||||
Measurements string `json:"measurements,omitempty"`
|
||||
FakeTits string `json:"fake_tits,omitempty"`
|
||||
CareerLength string `json:"career_length,omitempty"`
|
||||
Tattoos string `json:"tattoos,omitempty"`
|
||||
Piercings string `json:"piercings,omitempty"`
|
||||
Aliases string `json:"aliases,omitempty"`
|
||||
Favorite bool `json:"favorite,omitempty"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
Image string `json:"image,omitempty"`
|
||||
CreatedAt json.JSONTime `json:"created_at,omitempty"`
|
||||
UpdatedAt json.JSONTime `json:"updated_at,omitempty"`
|
||||
Rating int `json:"rating,omitempty"`
|
||||
Details string `json:"details,omitempty"`
|
||||
DeathDate string `json:"death_date,omitempty"`
|
||||
HairColor string `json:"hair_color,omitempty"`
|
||||
Weight int `json:"weight,omitempty"`
|
||||
StashIDs []models.StashID `json:"stash_ids,omitempty"`
|
||||
IgnoreAutoTag bool `json:"ignore_auto_tag,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Gender string `json:"gender,omitempty"`
|
||||
URL string `json:"url,omitempty"`
|
||||
Twitter string `json:"twitter,omitempty"`
|
||||
Instagram string `json:"instagram,omitempty"`
|
||||
Birthdate string `json:"birthdate,omitempty"`
|
||||
Ethnicity string `json:"ethnicity,omitempty"`
|
||||
Country string `json:"country,omitempty"`
|
||||
EyeColor string `json:"eye_color,omitempty"`
|
||||
Height string `json:"height,omitempty"`
|
||||
Measurements string `json:"measurements,omitempty"`
|
||||
FakeTits string `json:"fake_tits,omitempty"`
|
||||
CareerLength string `json:"career_length,omitempty"`
|
||||
Tattoos string `json:"tattoos,omitempty"`
|
||||
Piercings string `json:"piercings,omitempty"`
|
||||
Aliases string `json:"aliases,omitempty"`
|
||||
Favorite bool `json:"favorite,omitempty"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
Image string `json:"image,omitempty"`
|
||||
CreatedAt json.JSONTime `json:"created_at,omitempty"`
|
||||
UpdatedAt json.JSONTime `json:"updated_at,omitempty"`
|
||||
Rating int `json:"rating,omitempty"`
|
||||
Details string `json:"details,omitempty"`
|
||||
DeathDate string `json:"death_date,omitempty"`
|
||||
HairColor string `json:"hair_color,omitempty"`
|
||||
Weight int `json:"weight,omitempty"`
|
||||
StashIDs []*models.StashID `json:"stash_ids,omitempty"`
|
||||
IgnoreAutoTag bool `json:"ignore_auto_tag,omitempty"`
|
||||
}
|
||||
|
||||
func LoadPerformerFile(filePath string) (*Performer, error) {
|
||||
|
||||
@@ -10,17 +10,17 @@ import (
|
||||
)
|
||||
|
||||
type Studio struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
URL string `json:"url,omitempty"`
|
||||
ParentStudio string `json:"parent_studio,omitempty"`
|
||||
Image string `json:"image,omitempty"`
|
||||
CreatedAt json.JSONTime `json:"created_at,omitempty"`
|
||||
UpdatedAt json.JSONTime `json:"updated_at,omitempty"`
|
||||
Rating int `json:"rating,omitempty"`
|
||||
Details string `json:"details,omitempty"`
|
||||
Aliases []string `json:"aliases,omitempty"`
|
||||
StashIDs []models.StashID `json:"stash_ids,omitempty"`
|
||||
IgnoreAutoTag bool `json:"ignore_auto_tag,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
URL string `json:"url,omitempty"`
|
||||
ParentStudio string `json:"parent_studio,omitempty"`
|
||||
Image string `json:"image,omitempty"`
|
||||
CreatedAt json.JSONTime `json:"created_at,omitempty"`
|
||||
UpdatedAt json.JSONTime `json:"updated_at,omitempty"`
|
||||
Rating int `json:"rating,omitempty"`
|
||||
Details string `json:"details,omitempty"`
|
||||
Aliases []string `json:"aliases,omitempty"`
|
||||
StashIDs []*models.StashID `json:"stash_ids,omitempty"`
|
||||
IgnoreAutoTag bool `json:"ignore_auto_tag,omitempty"`
|
||||
}
|
||||
|
||||
func LoadStudioFile(filePath string) (*Studio, error) {
|
||||
|
||||
@@ -5,8 +5,10 @@ package mocks
|
||||
import (
|
||||
context "context"
|
||||
|
||||
models "github.com/stashapp/stash/pkg/models"
|
||||
file "github.com/stashapp/stash/pkg/file"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
models "github.com/stashapp/stash/pkg/models"
|
||||
)
|
||||
|
||||
// GalleryReaderWriter is an autogenerated mock type for the GalleryReaderWriter type
|
||||
@@ -58,27 +60,18 @@ func (_m *GalleryReaderWriter) Count(ctx context.Context) (int, error) {
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// Create provides a mock function with given fields: ctx, newGallery
|
||||
func (_m *GalleryReaderWriter) Create(ctx context.Context, newGallery models.Gallery) (*models.Gallery, error) {
|
||||
ret := _m.Called(ctx, newGallery)
|
||||
// Create provides a mock function with given fields: ctx, newGallery, fileIDs
|
||||
func (_m *GalleryReaderWriter) Create(ctx context.Context, newGallery *models.Gallery, fileIDs []file.ID) error {
|
||||
ret := _m.Called(ctx, newGallery, fileIDs)
|
||||
|
||||
var r0 *models.Gallery
|
||||
if rf, ok := ret.Get(0).(func(context.Context, models.Gallery) *models.Gallery); ok {
|
||||
r0 = rf(ctx, newGallery)
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *models.Gallery, []file.ID) error); ok {
|
||||
r0 = rf(ctx, newGallery, fileIDs)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Gallery)
|
||||
}
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, models.Gallery) error); ok {
|
||||
r1 = rf(ctx, newGallery)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
return r0
|
||||
}
|
||||
|
||||
// Destroy provides a mock function with given fields: ctx, id
|
||||
@@ -119,15 +112,15 @@ func (_m *GalleryReaderWriter) Find(ctx context.Context, id int) (*models.Galler
|
||||
}
|
||||
|
||||
// FindByChecksum provides a mock function with given fields: ctx, checksum
|
||||
func (_m *GalleryReaderWriter) FindByChecksum(ctx context.Context, checksum string) (*models.Gallery, error) {
|
||||
func (_m *GalleryReaderWriter) FindByChecksum(ctx context.Context, checksum string) ([]*models.Gallery, error) {
|
||||
ret := _m.Called(ctx, checksum)
|
||||
|
||||
var r0 *models.Gallery
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *models.Gallery); ok {
|
||||
var r0 []*models.Gallery
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) []*models.Gallery); ok {
|
||||
r0 = rf(ctx, checksum)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Gallery)
|
||||
r0 = ret.Get(0).([]*models.Gallery)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,15 +181,15 @@ func (_m *GalleryReaderWriter) FindByImageID(ctx context.Context, imageID int) (
|
||||
}
|
||||
|
||||
// FindByPath provides a mock function with given fields: ctx, path
|
||||
func (_m *GalleryReaderWriter) FindByPath(ctx context.Context, path string) (*models.Gallery, error) {
|
||||
func (_m *GalleryReaderWriter) FindByPath(ctx context.Context, path string) ([]*models.Gallery, error) {
|
||||
ret := _m.Called(ctx, path)
|
||||
|
||||
var r0 *models.Gallery
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *models.Gallery); ok {
|
||||
var r0 []*models.Gallery
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) []*models.Gallery); ok {
|
||||
r0 = rf(ctx, path)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Gallery)
|
||||
r0 = ret.Get(0).([]*models.Gallery)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,75 +272,6 @@ func (_m *GalleryReaderWriter) GetImageIDs(ctx context.Context, galleryID int) (
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetPerformerIDs provides a mock function with given fields: ctx, galleryID
|
||||
func (_m *GalleryReaderWriter) GetPerformerIDs(ctx context.Context, galleryID int) ([]int, error) {
|
||||
ret := _m.Called(ctx, galleryID)
|
||||
|
||||
var r0 []int
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int) []int); ok {
|
||||
r0 = rf(ctx, galleryID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]int)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, int) error); ok {
|
||||
r1 = rf(ctx, galleryID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetSceneIDs provides a mock function with given fields: ctx, galleryID
|
||||
func (_m *GalleryReaderWriter) GetSceneIDs(ctx context.Context, galleryID int) ([]int, error) {
|
||||
ret := _m.Called(ctx, galleryID)
|
||||
|
||||
var r0 []int
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int) []int); ok {
|
||||
r0 = rf(ctx, galleryID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]int)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, int) error); ok {
|
||||
r1 = rf(ctx, galleryID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetTagIDs provides a mock function with given fields: ctx, galleryID
|
||||
func (_m *GalleryReaderWriter) GetTagIDs(ctx context.Context, galleryID int) ([]int, error) {
|
||||
ret := _m.Called(ctx, galleryID)
|
||||
|
||||
var r0 []int
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int) []int); ok {
|
||||
r0 = rf(ctx, galleryID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]int)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, int) error); ok {
|
||||
r1 = rf(ctx, galleryID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// Query provides a mock function with given fields: ctx, galleryFilter, findFilter
|
||||
func (_m *GalleryReaderWriter) Query(ctx context.Context, galleryFilter *models.GalleryFilterType, findFilter *models.FindFilterType) ([]*models.Gallery, int, error) {
|
||||
ret := _m.Called(ctx, galleryFilter, findFilter)
|
||||
@@ -400,35 +324,12 @@ func (_m *GalleryReaderWriter) QueryCount(ctx context.Context, galleryFilter *mo
|
||||
}
|
||||
|
||||
// Update provides a mock function with given fields: ctx, updatedGallery
|
||||
func (_m *GalleryReaderWriter) Update(ctx context.Context, updatedGallery models.Gallery) (*models.Gallery, error) {
|
||||
func (_m *GalleryReaderWriter) Update(ctx context.Context, updatedGallery *models.Gallery) error {
|
||||
ret := _m.Called(ctx, updatedGallery)
|
||||
|
||||
var r0 *models.Gallery
|
||||
if rf, ok := ret.Get(0).(func(context.Context, models.Gallery) *models.Gallery); ok {
|
||||
r0 = rf(ctx, updatedGallery)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Gallery)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, models.Gallery) error); ok {
|
||||
r1 = rf(ctx, updatedGallery)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// UpdateFileModTime provides a mock function with given fields: ctx, id, modTime
|
||||
func (_m *GalleryReaderWriter) UpdateFileModTime(ctx context.Context, id int, modTime models.NullSQLiteTimestamp) error {
|
||||
ret := _m.Called(ctx, id, modTime)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int, models.NullSQLiteTimestamp) error); ok {
|
||||
r0 = rf(ctx, id, modTime)
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *models.Gallery) error); ok {
|
||||
r0 = rf(ctx, updatedGallery)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
@@ -450,13 +351,13 @@ func (_m *GalleryReaderWriter) UpdateImages(ctx context.Context, galleryID int,
|
||||
return r0
|
||||
}
|
||||
|
||||
// UpdatePartial provides a mock function with given fields: ctx, updatedGallery
|
||||
func (_m *GalleryReaderWriter) UpdatePartial(ctx context.Context, updatedGallery models.GalleryPartial) (*models.Gallery, error) {
|
||||
ret := _m.Called(ctx, updatedGallery)
|
||||
// UpdatePartial provides a mock function with given fields: ctx, id, updatedGallery
|
||||
func (_m *GalleryReaderWriter) UpdatePartial(ctx context.Context, id int, updatedGallery models.GalleryPartial) (*models.Gallery, error) {
|
||||
ret := _m.Called(ctx, id, updatedGallery)
|
||||
|
||||
var r0 *models.Gallery
|
||||
if rf, ok := ret.Get(0).(func(context.Context, models.GalleryPartial) *models.Gallery); ok {
|
||||
r0 = rf(ctx, updatedGallery)
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int, models.GalleryPartial) *models.Gallery); ok {
|
||||
r0 = rf(ctx, id, updatedGallery)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Gallery)
|
||||
@@ -464,53 +365,11 @@ func (_m *GalleryReaderWriter) UpdatePartial(ctx context.Context, updatedGallery
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, models.GalleryPartial) error); ok {
|
||||
r1 = rf(ctx, updatedGallery)
|
||||
if rf, ok := ret.Get(1).(func(context.Context, int, models.GalleryPartial) error); ok {
|
||||
r1 = rf(ctx, id, updatedGallery)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// UpdatePerformers provides a mock function with given fields: ctx, galleryID, performerIDs
|
||||
func (_m *GalleryReaderWriter) UpdatePerformers(ctx context.Context, galleryID int, performerIDs []int) error {
|
||||
ret := _m.Called(ctx, galleryID, performerIDs)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int, []int) error); ok {
|
||||
r0 = rf(ctx, galleryID, performerIDs)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// UpdateScenes provides a mock function with given fields: ctx, galleryID, sceneIDs
|
||||
func (_m *GalleryReaderWriter) UpdateScenes(ctx context.Context, galleryID int, sceneIDs []int) error {
|
||||
ret := _m.Called(ctx, galleryID, sceneIDs)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int, []int) error); ok {
|
||||
r0 = rf(ctx, galleryID, sceneIDs)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// UpdateTags provides a mock function with given fields: ctx, galleryID, tagIDs
|
||||
func (_m *GalleryReaderWriter) UpdateTags(ctx context.Context, galleryID int, tagIDs []int) error {
|
||||
ret := _m.Called(ctx, galleryID, tagIDs)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int, []int) error); ok {
|
||||
r0 = rf(ctx, galleryID, tagIDs)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
@@ -80,26 +80,17 @@ func (_m *ImageReaderWriter) CountByGalleryID(ctx context.Context, galleryID int
|
||||
}
|
||||
|
||||
// Create provides a mock function with given fields: ctx, newImage
|
||||
func (_m *ImageReaderWriter) Create(ctx context.Context, newImage models.Image) (*models.Image, error) {
|
||||
func (_m *ImageReaderWriter) Create(ctx context.Context, newImage *models.ImageCreateInput) error {
|
||||
ret := _m.Called(ctx, newImage)
|
||||
|
||||
var r0 *models.Image
|
||||
if rf, ok := ret.Get(0).(func(context.Context, models.Image) *models.Image); ok {
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *models.ImageCreateInput) error); ok {
|
||||
r0 = rf(ctx, newImage)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Image)
|
||||
}
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, models.Image) error); ok {
|
||||
r1 = rf(ctx, newImage)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
return r0
|
||||
}
|
||||
|
||||
// DecrementOCounter provides a mock function with given fields: ctx, id
|
||||
@@ -161,15 +152,15 @@ func (_m *ImageReaderWriter) Find(ctx context.Context, id int) (*models.Image, e
|
||||
}
|
||||
|
||||
// FindByChecksum provides a mock function with given fields: ctx, checksum
|
||||
func (_m *ImageReaderWriter) FindByChecksum(ctx context.Context, checksum string) (*models.Image, error) {
|
||||
func (_m *ImageReaderWriter) FindByChecksum(ctx context.Context, checksum string) ([]*models.Image, error) {
|
||||
ret := _m.Called(ctx, checksum)
|
||||
|
||||
var r0 *models.Image
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *models.Image); ok {
|
||||
var r0 []*models.Image
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) []*models.Image); ok {
|
||||
r0 = rf(ctx, checksum)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Image)
|
||||
r0 = ret.Get(0).([]*models.Image)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,15 +198,15 @@ func (_m *ImageReaderWriter) FindByGalleryID(ctx context.Context, galleryID int)
|
||||
}
|
||||
|
||||
// FindByPath provides a mock function with given fields: ctx, path
|
||||
func (_m *ImageReaderWriter) FindByPath(ctx context.Context, path string) (*models.Image, error) {
|
||||
func (_m *ImageReaderWriter) FindByPath(ctx context.Context, path string) ([]*models.Image, error) {
|
||||
ret := _m.Called(ctx, path)
|
||||
|
||||
var r0 *models.Image
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *models.Image); ok {
|
||||
var r0 []*models.Image
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) []*models.Image); ok {
|
||||
r0 = rf(ctx, path)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Image)
|
||||
r0 = ret.Get(0).([]*models.Image)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,75 +243,6 @@ func (_m *ImageReaderWriter) FindMany(ctx context.Context, ids []int) ([]*models
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetGalleryIDs provides a mock function with given fields: ctx, imageID
|
||||
func (_m *ImageReaderWriter) GetGalleryIDs(ctx context.Context, imageID int) ([]int, error) {
|
||||
ret := _m.Called(ctx, imageID)
|
||||
|
||||
var r0 []int
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int) []int); ok {
|
||||
r0 = rf(ctx, imageID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]int)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, int) error); ok {
|
||||
r1 = rf(ctx, imageID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetPerformerIDs provides a mock function with given fields: ctx, imageID
|
||||
func (_m *ImageReaderWriter) GetPerformerIDs(ctx context.Context, imageID int) ([]int, error) {
|
||||
ret := _m.Called(ctx, imageID)
|
||||
|
||||
var r0 []int
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int) []int); ok {
|
||||
r0 = rf(ctx, imageID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]int)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, int) error); ok {
|
||||
r1 = rf(ctx, imageID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetTagIDs provides a mock function with given fields: ctx, imageID
|
||||
func (_m *ImageReaderWriter) GetTagIDs(ctx context.Context, imageID int) ([]int, error) {
|
||||
ret := _m.Called(ctx, imageID)
|
||||
|
||||
var r0 []int
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int) []int); ok {
|
||||
r0 = rf(ctx, imageID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]int)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, int) error); ok {
|
||||
r1 = rf(ctx, imageID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// IncrementOCounter provides a mock function with given fields: ctx, id
|
||||
func (_m *ImageReaderWriter) IncrementOCounter(ctx context.Context, id int) (int, error) {
|
||||
ret := _m.Called(ctx, id)
|
||||
@@ -429,12 +351,26 @@ func (_m *ImageReaderWriter) Size(ctx context.Context) (float64, error) {
|
||||
}
|
||||
|
||||
// Update provides a mock function with given fields: ctx, updatedImage
|
||||
func (_m *ImageReaderWriter) Update(ctx context.Context, updatedImage models.ImagePartial) (*models.Image, error) {
|
||||
func (_m *ImageReaderWriter) Update(ctx context.Context, updatedImage *models.Image) error {
|
||||
ret := _m.Called(ctx, updatedImage)
|
||||
|
||||
var r0 *models.Image
|
||||
if rf, ok := ret.Get(0).(func(context.Context, models.ImagePartial) *models.Image); ok {
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *models.Image) error); ok {
|
||||
r0 = rf(ctx, updatedImage)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// UpdatePartial provides a mock function with given fields: ctx, id, partial
|
||||
func (_m *ImageReaderWriter) UpdatePartial(ctx context.Context, id int, partial models.ImagePartial) (*models.Image, error) {
|
||||
ret := _m.Called(ctx, id, partial)
|
||||
|
||||
var r0 *models.Image
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int, models.ImagePartial) *models.Image); ok {
|
||||
r0 = rf(ctx, id, partial)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Image)
|
||||
@@ -442,76 +378,11 @@ func (_m *ImageReaderWriter) Update(ctx context.Context, updatedImage models.Ima
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, models.ImagePartial) error); ok {
|
||||
r1 = rf(ctx, updatedImage)
|
||||
if rf, ok := ret.Get(1).(func(context.Context, int, models.ImagePartial) error); ok {
|
||||
r1 = rf(ctx, id, partial)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// UpdateFull provides a mock function with given fields: ctx, updatedImage
|
||||
func (_m *ImageReaderWriter) UpdateFull(ctx context.Context, updatedImage models.Image) (*models.Image, error) {
|
||||
ret := _m.Called(ctx, updatedImage)
|
||||
|
||||
var r0 *models.Image
|
||||
if rf, ok := ret.Get(0).(func(context.Context, models.Image) *models.Image); ok {
|
||||
r0 = rf(ctx, updatedImage)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Image)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, models.Image) error); ok {
|
||||
r1 = rf(ctx, updatedImage)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// UpdateGalleries provides a mock function with given fields: ctx, imageID, galleryIDs
|
||||
func (_m *ImageReaderWriter) UpdateGalleries(ctx context.Context, imageID int, galleryIDs []int) error {
|
||||
ret := _m.Called(ctx, imageID, galleryIDs)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int, []int) error); ok {
|
||||
r0 = rf(ctx, imageID, galleryIDs)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// UpdatePerformers provides a mock function with given fields: ctx, imageID, performerIDs
|
||||
func (_m *ImageReaderWriter) UpdatePerformers(ctx context.Context, imageID int, performerIDs []int) error {
|
||||
ret := _m.Called(ctx, imageID, performerIDs)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int, []int) error); ok {
|
||||
r0 = rf(ctx, imageID, performerIDs)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// UpdateTags provides a mock function with given fields: ctx, imageID, tagIDs
|
||||
func (_m *ImageReaderWriter) UpdateTags(ctx context.Context, imageID int, tagIDs []int) error {
|
||||
ret := _m.Called(ctx, imageID, tagIDs)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int, []int) error); ok {
|
||||
r0 = rf(ctx, imageID, tagIDs)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
@@ -520,11 +520,11 @@ func (_m *PerformerReaderWriter) UpdateImage(ctx context.Context, performerID in
|
||||
}
|
||||
|
||||
// UpdateStashIDs provides a mock function with given fields: ctx, performerID, stashIDs
|
||||
func (_m *PerformerReaderWriter) UpdateStashIDs(ctx context.Context, performerID int, stashIDs []models.StashID) error {
|
||||
func (_m *PerformerReaderWriter) UpdateStashIDs(ctx context.Context, performerID int, stashIDs []*models.StashID) error {
|
||||
ret := _m.Called(ctx, performerID, stashIDs)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int, []models.StashID) error); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int, []*models.StashID) error); ok {
|
||||
r0 = rf(ctx, performerID, stashIDs)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
|
||||
@@ -5,8 +5,10 @@ package mocks
|
||||
import (
|
||||
context "context"
|
||||
|
||||
models "github.com/stashapp/stash/pkg/models"
|
||||
file "github.com/stashapp/stash/pkg/file"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
models "github.com/stashapp/stash/pkg/models"
|
||||
)
|
||||
|
||||
// SceneReaderWriter is an autogenerated mock type for the SceneReaderWriter type
|
||||
@@ -184,27 +186,18 @@ func (_m *SceneReaderWriter) CountMissingOSHash(ctx context.Context) (int, error
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// Create provides a mock function with given fields: ctx, newScene
|
||||
func (_m *SceneReaderWriter) Create(ctx context.Context, newScene models.Scene) (*models.Scene, error) {
|
||||
ret := _m.Called(ctx, newScene)
|
||||
// Create provides a mock function with given fields: ctx, newScene, fileIDs
|
||||
func (_m *SceneReaderWriter) Create(ctx context.Context, newScene *models.Scene, fileIDs []file.ID) error {
|
||||
ret := _m.Called(ctx, newScene, fileIDs)
|
||||
|
||||
var r0 *models.Scene
|
||||
if rf, ok := ret.Get(0).(func(context.Context, models.Scene) *models.Scene); ok {
|
||||
r0 = rf(ctx, newScene)
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *models.Scene, []file.ID) error); ok {
|
||||
r0 = rf(ctx, newScene, fileIDs)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Scene)
|
||||
}
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, models.Scene) error); ok {
|
||||
r1 = rf(ctx, newScene)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
return r0
|
||||
}
|
||||
|
||||
// DecrementOCounter provides a mock function with given fields: ctx, id
|
||||
@@ -301,15 +294,15 @@ func (_m *SceneReaderWriter) Find(ctx context.Context, id int) (*models.Scene, e
|
||||
}
|
||||
|
||||
// FindByChecksum provides a mock function with given fields: ctx, checksum
|
||||
func (_m *SceneReaderWriter) FindByChecksum(ctx context.Context, checksum string) (*models.Scene, error) {
|
||||
func (_m *SceneReaderWriter) FindByChecksum(ctx context.Context, checksum string) ([]*models.Scene, error) {
|
||||
ret := _m.Called(ctx, checksum)
|
||||
|
||||
var r0 *models.Scene
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *models.Scene); ok {
|
||||
var r0 []*models.Scene
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) []*models.Scene); ok {
|
||||
r0 = rf(ctx, checksum)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Scene)
|
||||
r0 = ret.Get(0).([]*models.Scene)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,15 +363,15 @@ func (_m *SceneReaderWriter) FindByMovieID(ctx context.Context, movieID int) ([]
|
||||
}
|
||||
|
||||
// FindByOSHash provides a mock function with given fields: ctx, oshash
|
||||
func (_m *SceneReaderWriter) FindByOSHash(ctx context.Context, oshash string) (*models.Scene, error) {
|
||||
func (_m *SceneReaderWriter) FindByOSHash(ctx context.Context, oshash string) ([]*models.Scene, error) {
|
||||
ret := _m.Called(ctx, oshash)
|
||||
|
||||
var r0 *models.Scene
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *models.Scene); ok {
|
||||
var r0 []*models.Scene
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) []*models.Scene); ok {
|
||||
r0 = rf(ctx, oshash)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Scene)
|
||||
r0 = ret.Get(0).([]*models.Scene)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -393,15 +386,15 @@ func (_m *SceneReaderWriter) FindByOSHash(ctx context.Context, oshash string) (*
|
||||
}
|
||||
|
||||
// FindByPath provides a mock function with given fields: ctx, path
|
||||
func (_m *SceneReaderWriter) FindByPath(ctx context.Context, path string) (*models.Scene, error) {
|
||||
func (_m *SceneReaderWriter) FindByPath(ctx context.Context, path string) ([]*models.Scene, error) {
|
||||
ret := _m.Called(ctx, path)
|
||||
|
||||
var r0 *models.Scene
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *models.Scene); ok {
|
||||
var r0 []*models.Scene
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) []*models.Scene); ok {
|
||||
r0 = rf(ctx, path)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Scene)
|
||||
r0 = ret.Get(0).([]*models.Scene)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,29 +477,6 @@ func (_m *SceneReaderWriter) FindMany(ctx context.Context, ids []int) ([]*models
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetCaptions provides a mock function with given fields: ctx, sceneID
|
||||
func (_m *SceneReaderWriter) GetCaptions(ctx context.Context, sceneID int) ([]*models.SceneCaption, error) {
|
||||
ret := _m.Called(ctx, sceneID)
|
||||
|
||||
var r0 []*models.SceneCaption
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int) []*models.SceneCaption); ok {
|
||||
r0 = rf(ctx, sceneID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*models.SceneCaption)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, int) error); ok {
|
||||
r1 = rf(ctx, sceneID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetCover provides a mock function with given fields: ctx, sceneID
|
||||
func (_m *SceneReaderWriter) GetCover(ctx context.Context, sceneID int) ([]byte, error) {
|
||||
ret := _m.Called(ctx, sceneID)
|
||||
@@ -530,121 +500,6 @@ func (_m *SceneReaderWriter) GetCover(ctx context.Context, sceneID int) ([]byte,
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetGalleryIDs provides a mock function with given fields: ctx, sceneID
|
||||
func (_m *SceneReaderWriter) GetGalleryIDs(ctx context.Context, sceneID int) ([]int, error) {
|
||||
ret := _m.Called(ctx, sceneID)
|
||||
|
||||
var r0 []int
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int) []int); ok {
|
||||
r0 = rf(ctx, sceneID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]int)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, int) error); ok {
|
||||
r1 = rf(ctx, sceneID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetMovies provides a mock function with given fields: ctx, sceneID
|
||||
func (_m *SceneReaderWriter) GetMovies(ctx context.Context, sceneID int) ([]models.MoviesScenes, error) {
|
||||
ret := _m.Called(ctx, sceneID)
|
||||
|
||||
var r0 []models.MoviesScenes
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int) []models.MoviesScenes); ok {
|
||||
r0 = rf(ctx, sceneID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]models.MoviesScenes)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, int) error); ok {
|
||||
r1 = rf(ctx, sceneID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetPerformerIDs provides a mock function with given fields: ctx, sceneID
|
||||
func (_m *SceneReaderWriter) GetPerformerIDs(ctx context.Context, sceneID int) ([]int, error) {
|
||||
ret := _m.Called(ctx, sceneID)
|
||||
|
||||
var r0 []int
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int) []int); ok {
|
||||
r0 = rf(ctx, sceneID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]int)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, int) error); ok {
|
||||
r1 = rf(ctx, sceneID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetStashIDs provides a mock function with given fields: ctx, sceneID
|
||||
func (_m *SceneReaderWriter) GetStashIDs(ctx context.Context, sceneID int) ([]*models.StashID, error) {
|
||||
ret := _m.Called(ctx, sceneID)
|
||||
|
||||
var r0 []*models.StashID
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int) []*models.StashID); ok {
|
||||
r0 = rf(ctx, sceneID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*models.StashID)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, int) error); ok {
|
||||
r1 = rf(ctx, sceneID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetTagIDs provides a mock function with given fields: ctx, sceneID
|
||||
func (_m *SceneReaderWriter) GetTagIDs(ctx context.Context, sceneID int) ([]int, error) {
|
||||
ret := _m.Called(ctx, sceneID)
|
||||
|
||||
var r0 []int
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int) []int); ok {
|
||||
r0 = rf(ctx, sceneID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]int)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, int) error); ok {
|
||||
r1 = rf(ctx, sceneID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// IncrementOCounter provides a mock function with given fields: ctx, id
|
||||
func (_m *SceneReaderWriter) IncrementOCounter(ctx context.Context, id int) (int, error) {
|
||||
ret := _m.Called(ctx, id)
|
||||
@@ -732,35 +587,12 @@ func (_m *SceneReaderWriter) Size(ctx context.Context) (float64, error) {
|
||||
}
|
||||
|
||||
// Update provides a mock function with given fields: ctx, updatedScene
|
||||
func (_m *SceneReaderWriter) Update(ctx context.Context, updatedScene models.ScenePartial) (*models.Scene, error) {
|
||||
func (_m *SceneReaderWriter) Update(ctx context.Context, updatedScene *models.Scene) error {
|
||||
ret := _m.Called(ctx, updatedScene)
|
||||
|
||||
var r0 *models.Scene
|
||||
if rf, ok := ret.Get(0).(func(context.Context, models.ScenePartial) *models.Scene); ok {
|
||||
r0 = rf(ctx, updatedScene)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Scene)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, models.ScenePartial) error); ok {
|
||||
r1 = rf(ctx, updatedScene)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// UpdateCaptions provides a mock function with given fields: ctx, id, captions
|
||||
func (_m *SceneReaderWriter) UpdateCaptions(ctx context.Context, id int, captions []*models.SceneCaption) error {
|
||||
ret := _m.Called(ctx, id, captions)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int, []*models.SceneCaption) error); ok {
|
||||
r0 = rf(ctx, id, captions)
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *models.Scene) error); ok {
|
||||
r0 = rf(ctx, updatedScene)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
@@ -782,27 +614,13 @@ func (_m *SceneReaderWriter) UpdateCover(ctx context.Context, sceneID int, cover
|
||||
return r0
|
||||
}
|
||||
|
||||
// UpdateFileModTime provides a mock function with given fields: ctx, id, modTime
|
||||
func (_m *SceneReaderWriter) UpdateFileModTime(ctx context.Context, id int, modTime models.NullSQLiteTimestamp) error {
|
||||
ret := _m.Called(ctx, id, modTime)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int, models.NullSQLiteTimestamp) error); ok {
|
||||
r0 = rf(ctx, id, modTime)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// UpdateFull provides a mock function with given fields: ctx, updatedScene
|
||||
func (_m *SceneReaderWriter) UpdateFull(ctx context.Context, updatedScene models.Scene) (*models.Scene, error) {
|
||||
ret := _m.Called(ctx, updatedScene)
|
||||
// UpdatePartial provides a mock function with given fields: ctx, id, updatedScene
|
||||
func (_m *SceneReaderWriter) UpdatePartial(ctx context.Context, id int, updatedScene models.ScenePartial) (*models.Scene, error) {
|
||||
ret := _m.Called(ctx, id, updatedScene)
|
||||
|
||||
var r0 *models.Scene
|
||||
if rf, ok := ret.Get(0).(func(context.Context, models.Scene) *models.Scene); ok {
|
||||
r0 = rf(ctx, updatedScene)
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int, models.ScenePartial) *models.Scene); ok {
|
||||
r0 = rf(ctx, id, updatedScene)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Scene)
|
||||
@@ -810,8 +628,8 @@ func (_m *SceneReaderWriter) UpdateFull(ctx context.Context, updatedScene models
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, models.Scene) error); ok {
|
||||
r1 = rf(ctx, updatedScene)
|
||||
if rf, ok := ret.Get(1).(func(context.Context, int, models.ScenePartial) error); ok {
|
||||
r1 = rf(ctx, id, updatedScene)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
@@ -819,76 +637,6 @@ func (_m *SceneReaderWriter) UpdateFull(ctx context.Context, updatedScene models
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// UpdateGalleries provides a mock function with given fields: ctx, sceneID, galleryIDs
|
||||
func (_m *SceneReaderWriter) UpdateGalleries(ctx context.Context, sceneID int, galleryIDs []int) error {
|
||||
ret := _m.Called(ctx, sceneID, galleryIDs)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int, []int) error); ok {
|
||||
r0 = rf(ctx, sceneID, galleryIDs)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// UpdateMovies provides a mock function with given fields: ctx, sceneID, movies
|
||||
func (_m *SceneReaderWriter) UpdateMovies(ctx context.Context, sceneID int, movies []models.MoviesScenes) error {
|
||||
ret := _m.Called(ctx, sceneID, movies)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int, []models.MoviesScenes) error); ok {
|
||||
r0 = rf(ctx, sceneID, movies)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// UpdatePerformers provides a mock function with given fields: ctx, sceneID, performerIDs
|
||||
func (_m *SceneReaderWriter) UpdatePerformers(ctx context.Context, sceneID int, performerIDs []int) error {
|
||||
ret := _m.Called(ctx, sceneID, performerIDs)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int, []int) error); ok {
|
||||
r0 = rf(ctx, sceneID, performerIDs)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// UpdateStashIDs provides a mock function with given fields: ctx, sceneID, stashIDs
|
||||
func (_m *SceneReaderWriter) UpdateStashIDs(ctx context.Context, sceneID int, stashIDs []models.StashID) error {
|
||||
ret := _m.Called(ctx, sceneID, stashIDs)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int, []models.StashID) error); ok {
|
||||
r0 = rf(ctx, sceneID, stashIDs)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// UpdateTags provides a mock function with given fields: ctx, sceneID, tagIDs
|
||||
func (_m *SceneReaderWriter) UpdateTags(ctx context.Context, sceneID int, tagIDs []int) error {
|
||||
ret := _m.Called(ctx, sceneID, tagIDs)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int, []int) error); ok {
|
||||
r0 = rf(ctx, sceneID, tagIDs)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Wall provides a mock function with given fields: ctx, q
|
||||
func (_m *SceneReaderWriter) Wall(ctx context.Context, q *string) ([]*models.Scene, error) {
|
||||
ret := _m.Called(ctx, q)
|
||||
|
||||
@@ -442,11 +442,11 @@ func (_m *StudioReaderWriter) UpdateImage(ctx context.Context, studioID int, ima
|
||||
}
|
||||
|
||||
// UpdateStashIDs provides a mock function with given fields: ctx, studioID, stashIDs
|
||||
func (_m *StudioReaderWriter) UpdateStashIDs(ctx context.Context, studioID int, stashIDs []models.StashID) error {
|
||||
func (_m *StudioReaderWriter) UpdateStashIDs(ctx context.Context, studioID int, stashIDs []*models.StashID) error {
|
||||
ret := _m.Called(ctx, studioID, stashIDs)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int, []models.StashID) error); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int, []*models.StashID) error); ok {
|
||||
r0 = rf(ctx, studioID, stashIDs)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
context "context"
|
||||
|
||||
"github.com/stashapp/stash/pkg/models"
|
||||
"github.com/stashapp/stash/pkg/txn"
|
||||
)
|
||||
|
||||
type TxnManager struct{}
|
||||
@@ -12,6 +13,10 @@ func (*TxnManager) Begin(ctx context.Context) (context.Context, error) {
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (*TxnManager) WithDatabase(ctx context.Context) (context.Context, error) {
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (*TxnManager) Commit(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
@@ -20,6 +25,12 @@ func (*TxnManager) Rollback(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*TxnManager) AddPostCommitHook(ctx context.Context, hook txn.TxnFunc) {
|
||||
}
|
||||
|
||||
func (*TxnManager) AddPostRollbackHook(ctx context.Context, hook txn.TxnFunc) {
|
||||
}
|
||||
|
||||
func (*TxnManager) Reset() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,89 +1,115 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/stashapp/stash/pkg/file"
|
||||
)
|
||||
|
||||
type Gallery struct {
|
||||
ID int `db:"id" json:"id"`
|
||||
Path sql.NullString `db:"path" json:"path"`
|
||||
Checksum string `db:"checksum" json:"checksum"`
|
||||
Zip bool `db:"zip" json:"zip"`
|
||||
Title sql.NullString `db:"title" json:"title"`
|
||||
URL sql.NullString `db:"url" json:"url"`
|
||||
Date SQLiteDate `db:"date" json:"date"`
|
||||
Details sql.NullString `db:"details" json:"details"`
|
||||
Rating sql.NullInt64 `db:"rating" json:"rating"`
|
||||
Organized bool `db:"organized" json:"organized"`
|
||||
StudioID sql.NullInt64 `db:"studio_id,omitempty" json:"studio_id"`
|
||||
FileModTime NullSQLiteTimestamp `db:"file_mod_time" json:"file_mod_time"`
|
||||
CreatedAt SQLiteTimestamp `db:"created_at" json:"created_at"`
|
||||
UpdatedAt SQLiteTimestamp `db:"updated_at" json:"updated_at"`
|
||||
ID int `json:"id"`
|
||||
|
||||
// Path *string `json:"path"`
|
||||
// Checksum string `json:"checksum"`
|
||||
// Zip bool `json:"zip"`
|
||||
|
||||
Title string `json:"title"`
|
||||
URL string `json:"url"`
|
||||
Date *Date `json:"date"`
|
||||
Details string `json:"details"`
|
||||
Rating *int `json:"rating"`
|
||||
Organized bool `json:"organized"`
|
||||
StudioID *int `json:"studio_id"`
|
||||
|
||||
// FileModTime *time.Time `json:"file_mod_time"`
|
||||
|
||||
// transient - not persisted
|
||||
Files []file.File
|
||||
|
||||
FolderID *file.FolderID `json:"folder_id"`
|
||||
|
||||
// transient - not persisted
|
||||
FolderPath string `json:"folder_path"`
|
||||
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
SceneIDs []int `json:"scene_ids"`
|
||||
TagIDs []int `json:"tag_ids"`
|
||||
PerformerIDs []int `json:"performer_ids"`
|
||||
}
|
||||
|
||||
func (g Gallery) PrimaryFile() file.File {
|
||||
if len(g.Files) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return g.Files[0]
|
||||
}
|
||||
|
||||
func (g Gallery) Path() string {
|
||||
if p := g.PrimaryFile(); p != nil {
|
||||
return p.Base().Path
|
||||
}
|
||||
|
||||
return g.FolderPath
|
||||
}
|
||||
|
||||
func (g Gallery) Checksum() string {
|
||||
if p := g.PrimaryFile(); p != nil {
|
||||
v := p.Base().Fingerprints.Get(file.FingerprintTypeMD5)
|
||||
if v == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return v.(string)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// GalleryPartial represents part of a Gallery object. It is used to update
|
||||
// the database entry. Only non-nil fields will be updated.
|
||||
type GalleryPartial struct {
|
||||
ID int `db:"id" json:"id"`
|
||||
Path *sql.NullString `db:"path" json:"path"`
|
||||
Checksum *string `db:"checksum" json:"checksum"`
|
||||
Title *sql.NullString `db:"title" json:"title"`
|
||||
URL *sql.NullString `db:"url" json:"url"`
|
||||
Date *SQLiteDate `db:"date" json:"date"`
|
||||
Details *sql.NullString `db:"details" json:"details"`
|
||||
Rating *sql.NullInt64 `db:"rating" json:"rating"`
|
||||
Organized *bool `db:"organized" json:"organized"`
|
||||
StudioID *sql.NullInt64 `db:"studio_id,omitempty" json:"studio_id"`
|
||||
FileModTime *NullSQLiteTimestamp `db:"file_mod_time" json:"file_mod_time"`
|
||||
CreatedAt *SQLiteTimestamp `db:"created_at" json:"created_at"`
|
||||
UpdatedAt *SQLiteTimestamp `db:"updated_at" json:"updated_at"`
|
||||
// Path OptionalString
|
||||
// Checksum OptionalString
|
||||
// Zip OptionalBool
|
||||
Title OptionalString
|
||||
URL OptionalString
|
||||
Date OptionalDate
|
||||
Details OptionalString
|
||||
Rating OptionalInt
|
||||
Organized OptionalBool
|
||||
StudioID OptionalInt
|
||||
// FileModTime OptionalTime
|
||||
CreatedAt OptionalTime
|
||||
UpdatedAt OptionalTime
|
||||
|
||||
SceneIDs *UpdateIDs
|
||||
TagIDs *UpdateIDs
|
||||
PerformerIDs *UpdateIDs
|
||||
}
|
||||
|
||||
func (s *Gallery) File() File {
|
||||
ret := File{
|
||||
Path: s.Path.String,
|
||||
}
|
||||
|
||||
ret.Checksum = s.Checksum
|
||||
|
||||
if s.FileModTime.Valid {
|
||||
ret.FileModTime = s.FileModTime.Timestamp
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (s *Gallery) SetFile(f File) {
|
||||
path := f.Path
|
||||
s.Path = sql.NullString{
|
||||
String: path,
|
||||
Valid: true,
|
||||
}
|
||||
|
||||
if f.Checksum != "" {
|
||||
s.Checksum = f.Checksum
|
||||
}
|
||||
|
||||
zeroTime := time.Time{}
|
||||
if f.FileModTime != zeroTime {
|
||||
s.FileModTime = NullSQLiteTimestamp{
|
||||
Timestamp: f.FileModTime,
|
||||
Valid: true,
|
||||
}
|
||||
func NewGalleryPartial() GalleryPartial {
|
||||
updatedTime := time.Now()
|
||||
return GalleryPartial{
|
||||
UpdatedAt: NewOptionalTime(updatedTime),
|
||||
}
|
||||
}
|
||||
|
||||
// GetTitle returns the title of the scene. If the Title field is empty,
|
||||
// then the base filename is returned.
|
||||
func (s Gallery) GetTitle() string {
|
||||
if s.Title.String != "" {
|
||||
return s.Title.String
|
||||
func (g Gallery) GetTitle() string {
|
||||
if g.Title != "" {
|
||||
return g.Title
|
||||
}
|
||||
|
||||
if s.Path.Valid {
|
||||
return filepath.Base(s.Path.String)
|
||||
if len(g.Files) > 0 {
|
||||
return filepath.Base(g.Path())
|
||||
}
|
||||
|
||||
if g.FolderPath != "" {
|
||||
return g.FolderPath
|
||||
}
|
||||
|
||||
return ""
|
||||
|
||||
@@ -1,104 +1,98 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/stashapp/stash/pkg/file"
|
||||
)
|
||||
|
||||
// Image stores the metadata for a single image.
|
||||
type Image struct {
|
||||
ID int `db:"id" json:"id"`
|
||||
Checksum string `db:"checksum" json:"checksum"`
|
||||
Path string `db:"path" json:"path"`
|
||||
Title sql.NullString `db:"title" json:"title"`
|
||||
Rating sql.NullInt64 `db:"rating" json:"rating"`
|
||||
Organized bool `db:"organized" json:"organized"`
|
||||
OCounter int `db:"o_counter" json:"o_counter"`
|
||||
Size sql.NullInt64 `db:"size" json:"size"`
|
||||
Width sql.NullInt64 `db:"width" json:"width"`
|
||||
Height sql.NullInt64 `db:"height" json:"height"`
|
||||
StudioID sql.NullInt64 `db:"studio_id,omitempty" json:"studio_id"`
|
||||
FileModTime NullSQLiteTimestamp `db:"file_mod_time" json:"file_mod_time"`
|
||||
CreatedAt SQLiteTimestamp `db:"created_at" json:"created_at"`
|
||||
UpdatedAt SQLiteTimestamp `db:"updated_at" json:"updated_at"`
|
||||
ID int `json:"id"`
|
||||
|
||||
Title string `json:"title"`
|
||||
Rating *int `json:"rating"`
|
||||
Organized bool `json:"organized"`
|
||||
OCounter int `json:"o_counter"`
|
||||
StudioID *int `json:"studio_id"`
|
||||
|
||||
// transient - not persisted
|
||||
Files []*file.ImageFile
|
||||
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
GalleryIDs []int `json:"gallery_ids"`
|
||||
TagIDs []int `json:"tag_ids"`
|
||||
PerformerIDs []int `json:"performer_ids"`
|
||||
}
|
||||
|
||||
// ImagePartial represents part of a Image object. It is used to update
|
||||
// the database entry. Only non-nil fields will be updated.
|
||||
type ImagePartial struct {
|
||||
ID int `db:"id" json:"id"`
|
||||
Checksum *string `db:"checksum" json:"checksum"`
|
||||
Path *string `db:"path" json:"path"`
|
||||
Title *sql.NullString `db:"title" json:"title"`
|
||||
Rating *sql.NullInt64 `db:"rating" json:"rating"`
|
||||
Organized *bool `db:"organized" json:"organized"`
|
||||
Size *sql.NullInt64 `db:"size" json:"size"`
|
||||
Width *sql.NullInt64 `db:"width" json:"width"`
|
||||
Height *sql.NullInt64 `db:"height" json:"height"`
|
||||
StudioID *sql.NullInt64 `db:"studio_id,omitempty" json:"studio_id"`
|
||||
FileModTime *NullSQLiteTimestamp `db:"file_mod_time" json:"file_mod_time"`
|
||||
CreatedAt *SQLiteTimestamp `db:"created_at" json:"created_at"`
|
||||
UpdatedAt *SQLiteTimestamp `db:"updated_at" json:"updated_at"`
|
||||
func (i Image) PrimaryFile() *file.ImageFile {
|
||||
if len(i.Files) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return i.Files[0]
|
||||
}
|
||||
|
||||
func (i *Image) File() File {
|
||||
ret := File{
|
||||
Path: i.Path,
|
||||
func (i Image) Path() string {
|
||||
if p := i.PrimaryFile(); p != nil {
|
||||
return p.Path
|
||||
}
|
||||
|
||||
ret.Checksum = i.Checksum
|
||||
if i.FileModTime.Valid {
|
||||
ret.FileModTime = i.FileModTime.Timestamp
|
||||
}
|
||||
if i.Size.Valid {
|
||||
ret.Size = strconv.FormatInt(i.Size.Int64, 10)
|
||||
}
|
||||
|
||||
return ret
|
||||
return ""
|
||||
}
|
||||
|
||||
func (i *Image) SetFile(f File) {
|
||||
path := f.Path
|
||||
i.Path = path
|
||||
|
||||
if f.Checksum != "" {
|
||||
i.Checksum = f.Checksum
|
||||
}
|
||||
zeroTime := time.Time{}
|
||||
if f.FileModTime != zeroTime {
|
||||
i.FileModTime = NullSQLiteTimestamp{
|
||||
Timestamp: f.FileModTime,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
if f.Size != "" {
|
||||
size, err := strconv.ParseInt(f.Size, 10, 64)
|
||||
if err == nil {
|
||||
i.Size = sql.NullInt64{
|
||||
Int64: size,
|
||||
Valid: true,
|
||||
}
|
||||
func (i Image) Checksum() string {
|
||||
if p := i.PrimaryFile(); p != nil {
|
||||
v := p.Fingerprints.Get(file.FingerprintTypeMD5)
|
||||
if v == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return v.(string)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetTitle returns the title of the image. If the Title field is empty,
|
||||
// then the base filename is returned.
|
||||
func (i *Image) GetTitle() string {
|
||||
if i.Title.String != "" {
|
||||
return i.Title.String
|
||||
func (i Image) GetTitle() string {
|
||||
if i.Title != "" {
|
||||
return i.Title
|
||||
}
|
||||
|
||||
return filepath.Base(i.Path)
|
||||
if p := i.PrimaryFile(); p != nil {
|
||||
return p.Basename
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// ImageFileType represents the file metadata for an image.
|
||||
type ImageFileType struct {
|
||||
Size *int `graphql:"size" json:"size"`
|
||||
Width *int `graphql:"width" json:"width"`
|
||||
Height *int `graphql:"height" json:"height"`
|
||||
type ImageCreateInput struct {
|
||||
*Image
|
||||
FileIDs []file.ID
|
||||
}
|
||||
|
||||
type ImagePartial struct {
|
||||
Title OptionalString
|
||||
Rating OptionalInt
|
||||
Organized OptionalBool
|
||||
OCounter OptionalInt
|
||||
StudioID OptionalInt
|
||||
CreatedAt OptionalTime
|
||||
UpdatedAt OptionalTime
|
||||
|
||||
GalleryIDs *UpdateIDs
|
||||
TagIDs *UpdateIDs
|
||||
PerformerIDs *UpdateIDs
|
||||
}
|
||||
|
||||
func NewImagePartial() ImagePartial {
|
||||
updatedTime := time.Now()
|
||||
return ImagePartial{
|
||||
UpdatedAt: NewOptionalTime(updatedTime),
|
||||
}
|
||||
}
|
||||
|
||||
type Images []*Image
|
||||
|
||||
@@ -1,21 +1,62 @@
|
||||
package models
|
||||
|
||||
import "database/sql"
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type MoviesScenes struct {
|
||||
MovieID int `db:"movie_id" json:"movie_id"`
|
||||
SceneID int `db:"scene_id" json:"scene_id"`
|
||||
SceneIndex sql.NullInt64 `db:"scene_index" json:"scene_index"`
|
||||
MovieID int `json:"movie_id"`
|
||||
// SceneID int `json:"scene_id"`
|
||||
SceneIndex *int `json:"scene_index"`
|
||||
}
|
||||
|
||||
type StashID struct {
|
||||
StashID string `db:"stash_id" json:"stash_id"`
|
||||
Endpoint string `db:"endpoint" json:"endpoint"`
|
||||
}
|
||||
|
||||
func (s StashID) StashIDInput() StashIDInput {
|
||||
return StashIDInput{
|
||||
Endpoint: s.Endpoint,
|
||||
StashID: s.StashID,
|
||||
func (s MoviesScenes) SceneMovieInput() *SceneMovieInput {
|
||||
return &SceneMovieInput{
|
||||
MovieID: strconv.Itoa(s.MovieID),
|
||||
SceneIndex: s.SceneIndex,
|
||||
}
|
||||
}
|
||||
|
||||
func (s MoviesScenes) Equal(o MoviesScenes) bool {
|
||||
return o.MovieID == s.MovieID && ((o.SceneIndex == nil && s.SceneIndex == nil) ||
|
||||
(o.SceneIndex != nil && s.SceneIndex != nil && *o.SceneIndex == *s.SceneIndex))
|
||||
}
|
||||
|
||||
type UpdateMovieIDs struct {
|
||||
Movies []MoviesScenes `json:"movies"`
|
||||
Mode RelationshipUpdateMode `json:"mode"`
|
||||
}
|
||||
|
||||
func (u *UpdateMovieIDs) SceneMovieInputs() []*SceneMovieInput {
|
||||
if u == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
ret := make([]*SceneMovieInput, len(u.Movies))
|
||||
for _, id := range u.Movies {
|
||||
ret = append(ret, id.SceneMovieInput())
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func UpdateMovieIDsFromInput(i []*SceneMovieInput) (*UpdateMovieIDs, error) {
|
||||
ret := &UpdateMovieIDs{
|
||||
Mode: RelationshipUpdateModeSet,
|
||||
}
|
||||
|
||||
for _, v := range i {
|
||||
mID, err := strconv.Atoi(v.MovieID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid movie ID: %s", v.MovieID)
|
||||
}
|
||||
|
||||
ret.Movies = append(ret.Movies, MoviesScenes{
|
||||
MovieID: mID,
|
||||
SceneIndex: v.SceneIndex,
|
||||
})
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
@@ -1,125 +1,144 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/stashapp/stash/pkg/file"
|
||||
)
|
||||
|
||||
// Scene stores the metadata for a single video scene.
|
||||
type Scene struct {
|
||||
ID int `db:"id" json:"id"`
|
||||
Checksum sql.NullString `db:"checksum" json:"checksum"`
|
||||
OSHash sql.NullString `db:"oshash" json:"oshash"`
|
||||
Path string `db:"path" json:"path"`
|
||||
Title sql.NullString `db:"title" json:"title"`
|
||||
Details sql.NullString `db:"details" json:"details"`
|
||||
URL sql.NullString `db:"url" json:"url"`
|
||||
Date SQLiteDate `db:"date" json:"date"`
|
||||
Rating sql.NullInt64 `db:"rating" json:"rating"`
|
||||
Organized bool `db:"organized" json:"organized"`
|
||||
OCounter int `db:"o_counter" json:"o_counter"`
|
||||
Size sql.NullString `db:"size" json:"size"`
|
||||
Duration sql.NullFloat64 `db:"duration" json:"duration"`
|
||||
VideoCodec sql.NullString `db:"video_codec" json:"video_codec"`
|
||||
Format sql.NullString `db:"format" json:"format_name"`
|
||||
AudioCodec sql.NullString `db:"audio_codec" json:"audio_codec"`
|
||||
Width sql.NullInt64 `db:"width" json:"width"`
|
||||
Height sql.NullInt64 `db:"height" json:"height"`
|
||||
Framerate sql.NullFloat64 `db:"framerate" json:"framerate"`
|
||||
Bitrate sql.NullInt64 `db:"bitrate" json:"bitrate"`
|
||||
StudioID sql.NullInt64 `db:"studio_id,omitempty" json:"studio_id"`
|
||||
FileModTime NullSQLiteTimestamp `db:"file_mod_time" json:"file_mod_time"`
|
||||
Phash sql.NullInt64 `db:"phash,omitempty" json:"phash"`
|
||||
CreatedAt SQLiteTimestamp `db:"created_at" json:"created_at"`
|
||||
UpdatedAt SQLiteTimestamp `db:"updated_at" json:"updated_at"`
|
||||
Interactive bool `db:"interactive" json:"interactive"`
|
||||
InteractiveSpeed sql.NullInt64 `db:"interactive_speed" json:"interactive_speed"`
|
||||
ID int `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Details string `json:"details"`
|
||||
URL string `json:"url"`
|
||||
Date *Date `json:"date"`
|
||||
Rating *int `json:"rating"`
|
||||
Organized bool `json:"organized"`
|
||||
OCounter int `json:"o_counter"`
|
||||
StudioID *int `json:"studio_id"`
|
||||
|
||||
// transient - not persisted
|
||||
Files []*file.VideoFile
|
||||
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
GalleryIDs []int `json:"gallery_ids"`
|
||||
TagIDs []int `json:"tag_ids"`
|
||||
PerformerIDs []int `json:"performer_ids"`
|
||||
Movies []MoviesScenes `json:"movies"`
|
||||
StashIDs []StashID `json:"stash_ids"`
|
||||
}
|
||||
|
||||
func (s *Scene) File() File {
|
||||
ret := File{
|
||||
Path: s.Path,
|
||||
func (s Scene) PrimaryFile() *file.VideoFile {
|
||||
if len(s.Files) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if s.Checksum.Valid {
|
||||
ret.Checksum = s.Checksum.String
|
||||
}
|
||||
if s.OSHash.Valid {
|
||||
ret.OSHash = s.OSHash.String
|
||||
}
|
||||
if s.FileModTime.Valid {
|
||||
ret.FileModTime = s.FileModTime.Timestamp
|
||||
}
|
||||
if s.Size.Valid {
|
||||
ret.Size = s.Size.String
|
||||
}
|
||||
|
||||
return ret
|
||||
return s.Files[0]
|
||||
}
|
||||
|
||||
func (s *Scene) SetFile(f File) {
|
||||
path := f.Path
|
||||
s.Path = path
|
||||
func (s Scene) Path() string {
|
||||
if p := s.PrimaryFile(); p != nil {
|
||||
return p.Base().Path
|
||||
}
|
||||
|
||||
if f.Checksum != "" {
|
||||
s.Checksum = sql.NullString{
|
||||
String: f.Checksum,
|
||||
Valid: true,
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s Scene) getHash(type_ string) string {
|
||||
if p := s.PrimaryFile(); p != nil {
|
||||
v := p.Base().Fingerprints.Get(type_)
|
||||
if v == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return v.(string)
|
||||
}
|
||||
if f.OSHash != "" {
|
||||
s.OSHash = sql.NullString{
|
||||
String: f.OSHash,
|
||||
Valid: true,
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s Scene) Checksum() string {
|
||||
return s.getHash(file.FingerprintTypeMD5)
|
||||
}
|
||||
|
||||
func (s Scene) OSHash() string {
|
||||
return s.getHash(file.FingerprintTypeOshash)
|
||||
}
|
||||
|
||||
func (s Scene) Phash() int64 {
|
||||
if p := s.PrimaryFile(); p != nil {
|
||||
v := p.Base().Fingerprints.Get(file.FingerprintTypePhash)
|
||||
if v == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return v.(int64)
|
||||
}
|
||||
zeroTime := time.Time{}
|
||||
if f.FileModTime != zeroTime {
|
||||
s.FileModTime = NullSQLiteTimestamp{
|
||||
Timestamp: f.FileModTime,
|
||||
Valid: true,
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (s Scene) Duration() float64 {
|
||||
if p := s.PrimaryFile(); p != nil {
|
||||
return p.Duration
|
||||
}
|
||||
if f.Size != "" {
|
||||
s.Size = sql.NullString{
|
||||
String: f.Size,
|
||||
Valid: true,
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (s Scene) Format() string {
|
||||
if p := s.PrimaryFile(); p != nil {
|
||||
return p.Format
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s Scene) VideoCodec() string {
|
||||
if p := s.PrimaryFile(); p != nil {
|
||||
return p.VideoCodec
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s Scene) AudioCodec() string {
|
||||
if p := s.PrimaryFile(); p != nil {
|
||||
return p.AudioCodec
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// ScenePartial represents part of a Scene object. It is used to update
|
||||
// the database entry. Only non-nil fields will be updated.
|
||||
// the database entry.
|
||||
type ScenePartial struct {
|
||||
ID int `db:"id" json:"id"`
|
||||
Checksum *sql.NullString `db:"checksum" json:"checksum"`
|
||||
OSHash *sql.NullString `db:"oshash" json:"oshash"`
|
||||
Path *string `db:"path" json:"path"`
|
||||
Title *sql.NullString `db:"title" json:"title"`
|
||||
Details *sql.NullString `db:"details" json:"details"`
|
||||
URL *sql.NullString `db:"url" json:"url"`
|
||||
Date *SQLiteDate `db:"date" json:"date"`
|
||||
Rating *sql.NullInt64 `db:"rating" json:"rating"`
|
||||
Organized *bool `db:"organized" json:"organized"`
|
||||
Size *sql.NullString `db:"size" json:"size"`
|
||||
Duration *sql.NullFloat64 `db:"duration" json:"duration"`
|
||||
VideoCodec *sql.NullString `db:"video_codec" json:"video_codec"`
|
||||
Format *sql.NullString `db:"format" json:"format_name"`
|
||||
AudioCodec *sql.NullString `db:"audio_codec" json:"audio_codec"`
|
||||
Width *sql.NullInt64 `db:"width" json:"width"`
|
||||
Height *sql.NullInt64 `db:"height" json:"height"`
|
||||
Framerate *sql.NullFloat64 `db:"framerate" json:"framerate"`
|
||||
Bitrate *sql.NullInt64 `db:"bitrate" json:"bitrate"`
|
||||
StudioID *sql.NullInt64 `db:"studio_id,omitempty" json:"studio_id"`
|
||||
MovieID *sql.NullInt64 `db:"movie_id,omitempty" json:"movie_id"`
|
||||
FileModTime *NullSQLiteTimestamp `db:"file_mod_time" json:"file_mod_time"`
|
||||
Phash *sql.NullInt64 `db:"phash,omitempty" json:"phash"`
|
||||
CreatedAt *SQLiteTimestamp `db:"created_at" json:"created_at"`
|
||||
UpdatedAt *SQLiteTimestamp `db:"updated_at" json:"updated_at"`
|
||||
Interactive *bool `db:"interactive" json:"interactive"`
|
||||
InteractiveSpeed *sql.NullInt64 `db:"interactive_speed" json:"interactive_speed"`
|
||||
Title OptionalString
|
||||
Details OptionalString
|
||||
URL OptionalString
|
||||
Date OptionalDate
|
||||
Rating OptionalInt
|
||||
Organized OptionalBool
|
||||
OCounter OptionalInt
|
||||
StudioID OptionalInt
|
||||
CreatedAt OptionalTime
|
||||
UpdatedAt OptionalTime
|
||||
|
||||
GalleryIDs *UpdateIDs
|
||||
TagIDs *UpdateIDs
|
||||
PerformerIDs *UpdateIDs
|
||||
MovieIDs *UpdateMovieIDs
|
||||
StashIDs *UpdateStashIDs
|
||||
}
|
||||
|
||||
func NewScenePartial() ScenePartial {
|
||||
updatedTime := time.Now()
|
||||
return ScenePartial{
|
||||
UpdatedAt: NewOptionalTime(updatedTime),
|
||||
}
|
||||
}
|
||||
|
||||
type SceneMovieInput struct {
|
||||
@@ -142,86 +161,83 @@ type SceneUpdateInput struct {
|
||||
Movies []*SceneMovieInput `json:"movies"`
|
||||
TagIds []string `json:"tag_ids"`
|
||||
// This should be a URL or a base64 encoded data URL
|
||||
CoverImage *string `json:"cover_image"`
|
||||
StashIds []*StashIDInput `json:"stash_ids"`
|
||||
CoverImage *string `json:"cover_image"`
|
||||
StashIds []StashID `json:"stash_ids"`
|
||||
}
|
||||
|
||||
// UpdateInput constructs a SceneUpdateInput using the populated fields in the ScenePartial object.
|
||||
func (s ScenePartial) UpdateInput() SceneUpdateInput {
|
||||
boolPtrCopy := func(v *bool) *bool {
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
func (s ScenePartial) UpdateInput(id int) SceneUpdateInput {
|
||||
var dateStr *string
|
||||
if s.Date.Set {
|
||||
d := s.Date.Value
|
||||
v := d.String()
|
||||
dateStr = &v
|
||||
}
|
||||
|
||||
vv := *v
|
||||
return &vv
|
||||
var stashIDs []StashID
|
||||
if s.StashIDs != nil {
|
||||
stashIDs = s.StashIDs.StashIDs
|
||||
}
|
||||
|
||||
return SceneUpdateInput{
|
||||
ID: strconv.Itoa(s.ID),
|
||||
Title: nullStringPtrToStringPtr(s.Title),
|
||||
Details: nullStringPtrToStringPtr(s.Details),
|
||||
URL: nullStringPtrToStringPtr(s.URL),
|
||||
Date: s.Date.StringPtr(),
|
||||
Rating: nullInt64PtrToIntPtr(s.Rating),
|
||||
Organized: boolPtrCopy(s.Organized),
|
||||
StudioID: nullInt64PtrToStringPtr(s.StudioID),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ScenePartial) SetFile(f File) {
|
||||
path := f.Path
|
||||
s.Path = &path
|
||||
|
||||
if f.Checksum != "" {
|
||||
s.Checksum = &sql.NullString{
|
||||
String: f.Checksum,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
if f.OSHash != "" {
|
||||
s.OSHash = &sql.NullString{
|
||||
String: f.OSHash,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
zeroTime := time.Time{}
|
||||
if f.FileModTime != zeroTime {
|
||||
s.FileModTime = &NullSQLiteTimestamp{
|
||||
Timestamp: f.FileModTime,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
if f.Size != "" {
|
||||
s.Size = &sql.NullString{
|
||||
String: f.Size,
|
||||
Valid: true,
|
||||
}
|
||||
ID: strconv.Itoa(id),
|
||||
Title: s.Title.Ptr(),
|
||||
Details: s.Details.Ptr(),
|
||||
URL: s.URL.Ptr(),
|
||||
Date: dateStr,
|
||||
Rating: s.Rating.Ptr(),
|
||||
Organized: s.Organized.Ptr(),
|
||||
StudioID: s.StudioID.StringPtr(),
|
||||
GalleryIds: s.GalleryIDs.IDStrings(),
|
||||
PerformerIds: s.PerformerIDs.IDStrings(),
|
||||
Movies: s.MovieIDs.SceneMovieInputs(),
|
||||
TagIds: s.TagIDs.IDStrings(),
|
||||
StashIds: stashIDs,
|
||||
}
|
||||
}
|
||||
|
||||
// GetTitle returns the title of the scene. If the Title field is empty,
|
||||
// then the base filename is returned.
|
||||
func (s Scene) GetTitle() string {
|
||||
if s.Title.String != "" {
|
||||
return s.Title.String
|
||||
if s.Title != "" {
|
||||
return s.Title
|
||||
}
|
||||
|
||||
return filepath.Base(s.Path)
|
||||
return filepath.Base(s.Path())
|
||||
}
|
||||
|
||||
// GetHash returns the hash of the scene, based on the hash algorithm provided. If
|
||||
// hash algorithm is MD5, then Checksum is returned. Otherwise, OSHash is returned.
|
||||
func (s Scene) GetHash(hashAlgorithm HashAlgorithm) string {
|
||||
return s.File().GetHash(hashAlgorithm)
|
||||
}
|
||||
|
||||
func (s Scene) GetMinResolution() int64 {
|
||||
if s.Width.Int64 < s.Height.Int64 {
|
||||
return s.Width.Int64
|
||||
f := s.PrimaryFile()
|
||||
if f == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return s.Height.Int64
|
||||
switch hashAlgorithm {
|
||||
case HashAlgorithmMd5:
|
||||
return f.Base().Fingerprints.Get(file.FingerprintTypeMD5).(string)
|
||||
case HashAlgorithmOshash:
|
||||
return f.Base().Fingerprints.Get(file.FingerprintTypeOshash).(string)
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s Scene) GetMinResolution() int {
|
||||
f := s.PrimaryFile()
|
||||
if f == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
w := f.Width
|
||||
h := f.Height
|
||||
|
||||
if w < h {
|
||||
return w
|
||||
}
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
// SceneFileType represents the file metadata for a scene.
|
||||
@@ -246,12 +262,12 @@ func (s *Scenes) New() interface{} {
|
||||
return &Scene{}
|
||||
}
|
||||
|
||||
type SceneCaption struct {
|
||||
type VideoCaption struct {
|
||||
LanguageCode string `json:"language_code"`
|
||||
Filename string `json:"filename"`
|
||||
CaptionType string `json:"caption_type"`
|
||||
}
|
||||
|
||||
func (c SceneCaption) Path(scenePath string) string {
|
||||
return filepath.Join(filepath.Dir(scenePath), c.Filename)
|
||||
func (c VideoCaption) Path(filePath string) string {
|
||||
return filepath.Join(filepath.Dir(filePath), c.Filename)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
@@ -23,31 +22,25 @@ func TestScenePartial_UpdateInput(t *testing.T) {
|
||||
studioIDStr = "2"
|
||||
)
|
||||
|
||||
dateObj := NewDate(date)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
id int
|
||||
s ScenePartial
|
||||
want SceneUpdateInput
|
||||
}{
|
||||
{
|
||||
"full",
|
||||
id,
|
||||
ScenePartial{
|
||||
ID: id,
|
||||
Title: NullStringPtr(title),
|
||||
Details: NullStringPtr(details),
|
||||
URL: NullStringPtr(url),
|
||||
Date: &SQLiteDate{
|
||||
String: date,
|
||||
Valid: true,
|
||||
},
|
||||
Rating: &sql.NullInt64{
|
||||
Int64: int64(rating),
|
||||
Valid: true,
|
||||
},
|
||||
Organized: &organized,
|
||||
StudioID: &sql.NullInt64{
|
||||
Int64: int64(studioID),
|
||||
Valid: true,
|
||||
},
|
||||
Title: NewOptionalString(title),
|
||||
Details: NewOptionalString(details),
|
||||
URL: NewOptionalString(url),
|
||||
Date: NewOptionalDate(dateObj),
|
||||
Rating: NewOptionalInt(rating),
|
||||
Organized: NewOptionalBool(organized),
|
||||
StudioID: NewOptionalInt(studioID),
|
||||
},
|
||||
SceneUpdateInput{
|
||||
ID: idStr,
|
||||
@@ -62,9 +55,8 @@ func TestScenePartial_UpdateInput(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"empty",
|
||||
ScenePartial{
|
||||
ID: id,
|
||||
},
|
||||
id,
|
||||
ScenePartial{},
|
||||
SceneUpdateInput{
|
||||
ID: idStr,
|
||||
},
|
||||
@@ -72,7 +64,7 @@ func TestScenePartial_UpdateInput(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := tt.s.UpdateInput(); !reflect.DeepEqual(got, tt.want) {
|
||||
if got := tt.s.UpdateInput(tt.id); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("ScenePartial.UpdateInput() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -154,7 +154,7 @@ type PerformerWriter interface {
|
||||
Destroy(ctx context.Context, id int) error
|
||||
UpdateImage(ctx context.Context, performerID int, image []byte) error
|
||||
DestroyImage(ctx context.Context, performerID int) error
|
||||
UpdateStashIDs(ctx context.Context, performerID int, stashIDs []StashID) error
|
||||
UpdateStashIDs(ctx context.Context, performerID int, stashIDs []*StashID) error
|
||||
UpdateTags(ctx context.Context, performerID int, tagIDs []int) error
|
||||
}
|
||||
|
||||
|
||||
@@ -3,17 +3,21 @@ package models
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/stashapp/stash/pkg/file"
|
||||
"github.com/stashapp/stash/pkg/txn"
|
||||
)
|
||||
|
||||
type TxnManager interface {
|
||||
txn.Manager
|
||||
txn.DatabaseProvider
|
||||
Reset() error
|
||||
}
|
||||
|
||||
type Repository struct {
|
||||
TxnManager
|
||||
|
||||
File file.Store
|
||||
Folder file.FolderStore
|
||||
Gallery GalleryReaderWriter
|
||||
Image ImageReaderWriter
|
||||
Movie MovieReaderWriter
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package models
|
||||
|
||||
import "context"
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/stashapp/stash/pkg/file"
|
||||
)
|
||||
|
||||
type PHashDuplicationCriterionInput struct {
|
||||
Duplicated *bool `json:"duplicated"`
|
||||
@@ -121,9 +125,9 @@ type SceneReader interface {
|
||||
SceneFinder
|
||||
// TODO - remove this in another PR
|
||||
Find(ctx context.Context, id int) (*Scene, error)
|
||||
FindByChecksum(ctx context.Context, checksum string) (*Scene, error)
|
||||
FindByOSHash(ctx context.Context, oshash string) (*Scene, error)
|
||||
FindByPath(ctx context.Context, path string) (*Scene, error)
|
||||
FindByChecksum(ctx context.Context, checksum string) ([]*Scene, error)
|
||||
FindByOSHash(ctx context.Context, oshash string) ([]*Scene, error)
|
||||
FindByPath(ctx context.Context, path string) ([]*Scene, error)
|
||||
FindByPerformerID(ctx context.Context, performerID int) ([]*Scene, error)
|
||||
FindByGalleryID(ctx context.Context, performerID int) ([]*Scene, error)
|
||||
FindDuplicates(ctx context.Context, distance int) ([][]*Scene, error)
|
||||
@@ -142,32 +146,19 @@ type SceneReader interface {
|
||||
Wall(ctx context.Context, q *string) ([]*Scene, error)
|
||||
All(ctx context.Context) ([]*Scene, error)
|
||||
Query(ctx context.Context, options SceneQueryOptions) (*SceneQueryResult, error)
|
||||
GetCaptions(ctx context.Context, sceneID int) ([]*SceneCaption, error)
|
||||
GetCover(ctx context.Context, sceneID int) ([]byte, error)
|
||||
GetMovies(ctx context.Context, sceneID int) ([]MoviesScenes, error)
|
||||
GetTagIDs(ctx context.Context, sceneID int) ([]int, error)
|
||||
GetGalleryIDs(ctx context.Context, sceneID int) ([]int, error)
|
||||
GetPerformerIDs(ctx context.Context, sceneID int) ([]int, error)
|
||||
GetStashIDs(ctx context.Context, sceneID int) ([]*StashID, error)
|
||||
}
|
||||
|
||||
type SceneWriter interface {
|
||||
Create(ctx context.Context, newScene Scene) (*Scene, error)
|
||||
Update(ctx context.Context, updatedScene ScenePartial) (*Scene, error)
|
||||
UpdateFull(ctx context.Context, updatedScene Scene) (*Scene, error)
|
||||
Create(ctx context.Context, newScene *Scene, fileIDs []file.ID) error
|
||||
Update(ctx context.Context, updatedScene *Scene) error
|
||||
UpdatePartial(ctx context.Context, id int, updatedScene ScenePartial) (*Scene, error)
|
||||
IncrementOCounter(ctx context.Context, id int) (int, error)
|
||||
DecrementOCounter(ctx context.Context, id int) (int, error)
|
||||
ResetOCounter(ctx context.Context, id int) (int, error)
|
||||
UpdateFileModTime(ctx context.Context, id int, modTime NullSQLiteTimestamp) error
|
||||
Destroy(ctx context.Context, id int) error
|
||||
UpdateCaptions(ctx context.Context, id int, captions []*SceneCaption) error
|
||||
UpdateCover(ctx context.Context, sceneID int, cover []byte) error
|
||||
DestroyCover(ctx context.Context, sceneID int) error
|
||||
UpdatePerformers(ctx context.Context, sceneID int, performerIDs []int) error
|
||||
UpdateTags(ctx context.Context, sceneID int, tagIDs []int) error
|
||||
UpdateGalleries(ctx context.Context, sceneID int, galleryIDs []int) error
|
||||
UpdateMovies(ctx context.Context, sceneID int, movies []MoviesScenes) error
|
||||
UpdateStashIDs(ctx context.Context, sceneID int, stashIDs []StashID) error
|
||||
}
|
||||
|
||||
type SceneReaderWriter interface {
|
||||
|
||||
@@ -2,7 +2,6 @@ package models
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func NullString(v string) sql.NullString {
|
||||
@@ -12,43 +11,9 @@ func NullString(v string) sql.NullString {
|
||||
}
|
||||
}
|
||||
|
||||
func NullStringPtr(v string) *sql.NullString {
|
||||
return &sql.NullString{
|
||||
String: v,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
func NullInt64(v int64) sql.NullInt64 {
|
||||
return sql.NullInt64{
|
||||
Int64: v,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
func nullStringPtrToStringPtr(v *sql.NullString) *string {
|
||||
if v == nil || !v.Valid {
|
||||
return nil
|
||||
}
|
||||
|
||||
vv := v.String
|
||||
return &vv
|
||||
}
|
||||
|
||||
func nullInt64PtrToIntPtr(v *sql.NullInt64) *int {
|
||||
if v == nil || !v.Valid {
|
||||
return nil
|
||||
}
|
||||
|
||||
vv := int(v.Int64)
|
||||
return &vv
|
||||
}
|
||||
|
||||
func nullInt64PtrToStringPtr(v *sql.NullInt64) *string {
|
||||
if v == nil || !v.Valid {
|
||||
return nil
|
||||
}
|
||||
|
||||
vv := strconv.FormatInt(v.Int64, 10)
|
||||
return &vv
|
||||
}
|
||||
|
||||
@@ -9,11 +9,14 @@ import (
|
||||
"github.com/stashapp/stash/pkg/utils"
|
||||
)
|
||||
|
||||
// TODO - this should be moved to sqlite
|
||||
type SQLiteDate struct {
|
||||
String string
|
||||
Valid bool
|
||||
}
|
||||
|
||||
const sqliteDateLayout = "2006-01-02"
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (t *SQLiteDate) Scan(value interface{}) error {
|
||||
dateTime, ok := value.(time.Time)
|
||||
@@ -23,7 +26,7 @@ func (t *SQLiteDate) Scan(value interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
t.String = dateTime.Format("2006-01-02")
|
||||
t.String = dateTime.Format(sqliteDateLayout)
|
||||
if t.String != "" && t.String != "0001-01-01" {
|
||||
t.Valid = true
|
||||
} else {
|
||||
@@ -44,7 +47,7 @@ func (t SQLiteDate) Value() (driver.Value, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
result, err := utils.ParseDateStringAsFormat(s, "2006-01-02")
|
||||
result, err := utils.ParseDateStringAsFormat(s, sqliteDateLayout)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("converting sqlite date %q: %w", s, err)
|
||||
}
|
||||
@@ -59,3 +62,21 @@ func (t *SQLiteDate) StringPtr() *string {
|
||||
vv := t.String
|
||||
return &vv
|
||||
}
|
||||
|
||||
func (t *SQLiteDate) TimePtr() *time.Time {
|
||||
if t == nil || !t.Valid {
|
||||
return nil
|
||||
}
|
||||
|
||||
ret, _ := time.Parse(sqliteDateLayout, t.String)
|
||||
return &ret
|
||||
}
|
||||
|
||||
func (t *SQLiteDate) DatePtr() *Date {
|
||||
if t == nil || !t.Valid {
|
||||
return nil
|
||||
}
|
||||
|
||||
ret := NewDate(t.String)
|
||||
return &ret
|
||||
}
|
||||
|
||||
@@ -1,19 +1,11 @@
|
||||
package models
|
||||
|
||||
type StashIDInput struct {
|
||||
Endpoint string `json:"endpoint"`
|
||||
StashID string `json:"stash_id"`
|
||||
type StashID struct {
|
||||
StashID string `db:"stash_id" json:"stash_id"`
|
||||
Endpoint string `db:"endpoint" json:"endpoint"`
|
||||
}
|
||||
|
||||
func StashIDsFromInput(i []*StashIDInput) []StashID {
|
||||
var ret []StashID
|
||||
for _, stashID := range i {
|
||||
newJoin := StashID{
|
||||
StashID: stashID.StashID,
|
||||
Endpoint: stashID.Endpoint,
|
||||
}
|
||||
ret = append(ret, newJoin)
|
||||
}
|
||||
|
||||
return ret
|
||||
type UpdateStashIDs struct {
|
||||
StashIDs []StashID `json:"stash_ids"`
|
||||
Mode RelationshipUpdateMode `json:"mode"`
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ type StudioWriter interface {
|
||||
Destroy(ctx context.Context, id int) error
|
||||
UpdateImage(ctx context.Context, studioID int, image []byte) error
|
||||
DestroyImage(ctx context.Context, studioID int) error
|
||||
UpdateStashIDs(ctx context.Context, studioID int, stashIDs []StashID) error
|
||||
UpdateStashIDs(ctx context.Context, studioID int, stashIDs []*StashID) error
|
||||
UpdateAliases(ctx context.Context, studioID int, aliases []string) error
|
||||
}
|
||||
|
||||
|
||||
65
pkg/models/update.go
Normal file
65
pkg/models/update.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
|
||||
"github.com/stashapp/stash/pkg/sliceutil/intslice"
|
||||
)
|
||||
|
||||
type RelationshipUpdateMode string
|
||||
|
||||
const (
|
||||
RelationshipUpdateModeSet RelationshipUpdateMode = "SET"
|
||||
RelationshipUpdateModeAdd RelationshipUpdateMode = "ADD"
|
||||
RelationshipUpdateModeRemove RelationshipUpdateMode = "REMOVE"
|
||||
)
|
||||
|
||||
var AllRelationshipUpdateMode = []RelationshipUpdateMode{
|
||||
RelationshipUpdateModeSet,
|
||||
RelationshipUpdateModeAdd,
|
||||
RelationshipUpdateModeRemove,
|
||||
}
|
||||
|
||||
func (e RelationshipUpdateMode) IsValid() bool {
|
||||
switch e {
|
||||
case RelationshipUpdateModeSet, RelationshipUpdateModeAdd, RelationshipUpdateModeRemove:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (e RelationshipUpdateMode) String() string {
|
||||
return string(e)
|
||||
}
|
||||
|
||||
func (e *RelationshipUpdateMode) UnmarshalGQL(v interface{}) error {
|
||||
str, ok := v.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("enums must be strings")
|
||||
}
|
||||
|
||||
*e = RelationshipUpdateMode(str)
|
||||
if !e.IsValid() {
|
||||
return fmt.Errorf("%s is not a valid RelationshipUpdateMode", str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e RelationshipUpdateMode) MarshalGQL(w io.Writer) {
|
||||
fmt.Fprint(w, strconv.Quote(e.String()))
|
||||
}
|
||||
|
||||
type UpdateIDs struct {
|
||||
IDs []int `json:"ids"`
|
||||
Mode RelationshipUpdateMode `json:"mode"`
|
||||
}
|
||||
|
||||
func (u *UpdateIDs) IDStrings() []string {
|
||||
if u == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return intslice.IntSliceToStringSlice(u.IDs)
|
||||
}
|
||||
249
pkg/models/value.go
Normal file
249
pkg/models/value.go
Normal file
@@ -0,0 +1,249 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// OptionalString represents an optional string argument that may be null.
|
||||
// A value is only considered null if both Set and Null is true.
|
||||
type OptionalString struct {
|
||||
Value string
|
||||
Null bool
|
||||
Set bool
|
||||
}
|
||||
|
||||
// Ptr returns a pointer to the underlying value. Returns nil if Set is false or Null is true.
|
||||
func (o *OptionalString) Ptr() *string {
|
||||
if !o.Set || o.Null {
|
||||
return nil
|
||||
}
|
||||
|
||||
v := o.Value
|
||||
return &v
|
||||
}
|
||||
|
||||
// NewOptionalString returns a new OptionalString with the given value.
|
||||
func NewOptionalString(v string) OptionalString {
|
||||
return OptionalString{v, false, true}
|
||||
}
|
||||
|
||||
// NewOptionalStringPtr returns a new OptionalString with the given value.
|
||||
// If the value is nil, the returned OptionalString will be set and null.
|
||||
func NewOptionalStringPtr(v *string) OptionalString {
|
||||
if v == nil {
|
||||
return OptionalString{
|
||||
Null: true,
|
||||
Set: true,
|
||||
}
|
||||
}
|
||||
|
||||
return OptionalString{*v, false, true}
|
||||
}
|
||||
|
||||
// OptionalInt represents an optional int argument that may be null. See OptionalString.
|
||||
type OptionalInt struct {
|
||||
Value int
|
||||
Null bool
|
||||
Set bool
|
||||
}
|
||||
|
||||
// Ptr returns a pointer to the underlying value. Returns nil if Set is false or Null is true.
|
||||
func (o *OptionalInt) Ptr() *int {
|
||||
if !o.Set || o.Null {
|
||||
return nil
|
||||
}
|
||||
|
||||
v := o.Value
|
||||
return &v
|
||||
}
|
||||
|
||||
// NewOptionalInt returns a new OptionalInt with the given value.
|
||||
func NewOptionalInt(v int) OptionalInt {
|
||||
return OptionalInt{v, false, true}
|
||||
}
|
||||
|
||||
// NewOptionalIntPtr returns a new OptionalInt with the given value.
|
||||
// If the value is nil, the returned OptionalInt will be set and null.
|
||||
func NewOptionalIntPtr(v *int) OptionalInt {
|
||||
if v == nil {
|
||||
return OptionalInt{
|
||||
Null: true,
|
||||
Set: true,
|
||||
}
|
||||
}
|
||||
|
||||
return OptionalInt{*v, false, true}
|
||||
}
|
||||
|
||||
// StringPtr returns a pointer to a string representation of the value.
|
||||
// Returns nil if Set is false or null is true.
|
||||
func (o *OptionalInt) StringPtr() *string {
|
||||
if !o.Set || o.Null {
|
||||
return nil
|
||||
}
|
||||
|
||||
v := strconv.Itoa(o.Value)
|
||||
return &v
|
||||
}
|
||||
|
||||
// OptionalInt64 represents an optional int64 argument that may be null. See OptionalString.
|
||||
type OptionalInt64 struct {
|
||||
Value int64
|
||||
Null bool
|
||||
Set bool
|
||||
}
|
||||
|
||||
// Ptr returns a pointer to the underlying value. Returns nil if Set is false or Null is true.
|
||||
func (o *OptionalInt64) Ptr() *int64 {
|
||||
if !o.Set || o.Null {
|
||||
return nil
|
||||
}
|
||||
|
||||
v := o.Value
|
||||
return &v
|
||||
}
|
||||
|
||||
// NewOptionalInt64 returns a new OptionalInt64 with the given value.
|
||||
func NewOptionalInt64(v int64) OptionalInt64 {
|
||||
return OptionalInt64{v, false, true}
|
||||
}
|
||||
|
||||
// NewOptionalInt64Ptr returns a new OptionalInt64 with the given value.
|
||||
// If the value is nil, the returned OptionalInt64 will be set and null.
|
||||
func NewOptionalInt64Ptr(v *int64) OptionalInt64 {
|
||||
if v == nil {
|
||||
return OptionalInt64{
|
||||
Null: true,
|
||||
Set: true,
|
||||
}
|
||||
}
|
||||
|
||||
return OptionalInt64{*v, false, true}
|
||||
}
|
||||
|
||||
// OptionalBool represents an optional int64 argument that may be null. See OptionalString.
|
||||
type OptionalBool struct {
|
||||
Value bool
|
||||
Null bool
|
||||
Set bool
|
||||
}
|
||||
|
||||
func (o *OptionalBool) Ptr() *bool {
|
||||
if !o.Set || o.Null {
|
||||
return nil
|
||||
}
|
||||
|
||||
v := o.Value
|
||||
return &v
|
||||
}
|
||||
|
||||
// NewOptionalBool returns a new OptionalBool with the given value.
|
||||
func NewOptionalBool(v bool) OptionalBool {
|
||||
return OptionalBool{v, false, true}
|
||||
}
|
||||
|
||||
// NewOptionalBoolPtr returns a new OptionalBool with the given value.
|
||||
// If the value is nil, the returned OptionalBool will be set and null.
|
||||
func NewOptionalBoolPtr(v *bool) OptionalBool {
|
||||
if v == nil {
|
||||
return OptionalBool{
|
||||
Null: true,
|
||||
Set: true,
|
||||
}
|
||||
}
|
||||
|
||||
return OptionalBool{*v, false, true}
|
||||
}
|
||||
|
||||
// OptionalBool represents an optional float64 argument that may be null. See OptionalString.
|
||||
type OptionalFloat64 struct {
|
||||
Value float64
|
||||
Null bool
|
||||
Set bool
|
||||
}
|
||||
|
||||
// Ptr returns a pointer to the underlying value. Returns nil if Set is false or Null is true.
|
||||
func (o *OptionalFloat64) Ptr() *float64 {
|
||||
if !o.Set || o.Null {
|
||||
return nil
|
||||
}
|
||||
|
||||
v := o.Value
|
||||
return &v
|
||||
}
|
||||
|
||||
// NewOptionalFloat64 returns a new OptionalFloat64 with the given value.
|
||||
func NewOptionalFloat64(v float64) OptionalFloat64 {
|
||||
return OptionalFloat64{v, false, true}
|
||||
}
|
||||
|
||||
// OptionalDate represents an optional date argument that may be null. See OptionalString.
|
||||
type OptionalDate struct {
|
||||
Value Date
|
||||
Null bool
|
||||
Set bool
|
||||
}
|
||||
|
||||
// Ptr returns a pointer to the underlying value. Returns nil if Set is false or Null is true.
|
||||
func (o *OptionalDate) Ptr() *Date {
|
||||
if !o.Set || o.Null {
|
||||
return nil
|
||||
}
|
||||
|
||||
v := o.Value
|
||||
return &v
|
||||
}
|
||||
|
||||
// NewOptionalDate returns a new OptionalDate with the given value.
|
||||
func NewOptionalDate(v Date) OptionalDate {
|
||||
return OptionalDate{v, false, true}
|
||||
}
|
||||
|
||||
// NewOptionalBoolPtr returns a new OptionalDate with the given value.
|
||||
// If the value is nil, the returned OptionalDate will be set and null.
|
||||
func NewOptionalDatePtr(v *Date) OptionalDate {
|
||||
if v == nil {
|
||||
return OptionalDate{
|
||||
Null: true,
|
||||
Set: true,
|
||||
}
|
||||
}
|
||||
|
||||
return OptionalDate{*v, false, true}
|
||||
}
|
||||
|
||||
// OptionalTime represents an optional time argument that may be null. See OptionalString.
|
||||
type OptionalTime struct {
|
||||
Value time.Time
|
||||
Null bool
|
||||
Set bool
|
||||
}
|
||||
|
||||
// NewOptionalTime returns a new OptionalTime with the given value.
|
||||
func NewOptionalTime(v time.Time) OptionalTime {
|
||||
return OptionalTime{v, false, true}
|
||||
}
|
||||
|
||||
// NewOptionalTimePtr returns a new OptionalTime with the given value.
|
||||
// If the value is nil, the returned OptionalTime will be set and null.
|
||||
func NewOptionalTimePtr(v *time.Time) OptionalTime {
|
||||
if v == nil {
|
||||
return OptionalTime{
|
||||
Null: true,
|
||||
Set: true,
|
||||
}
|
||||
}
|
||||
|
||||
return OptionalTime{*v, false, true}
|
||||
}
|
||||
|
||||
// Ptr returns a pointer to the underlying value. Returns nil if Set is false or Null is true.
|
||||
func (o *OptionalTime) Ptr() *time.Time {
|
||||
if !o.Set || o.Null {
|
||||
return nil
|
||||
}
|
||||
|
||||
v := o.Value
|
||||
return &v
|
||||
}
|
||||
Reference in New Issue
Block a user