mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 20:34:37 +03:00
Add findFolder and findFolders queries to graphql schema (#5965)
* Add findFolder and findFolders queries to graphql schema * Add zip file criterion to file and folder queries
This commit is contained in:
@@ -24,6 +24,7 @@ type FileFilterType struct {
|
||||
Basename *StringCriterionInput `json:"basename"`
|
||||
Dir *StringCriterionInput `json:"dir"`
|
||||
ParentFolder *HierarchicalMultiCriterionInput `json:"parent_folder"`
|
||||
ZipFile *MultiCriterionInput `json:"zip_file"`
|
||||
ModTime *TimestampCriterionInput `json:"mod_time"`
|
||||
Duplicated *PHashDuplicationCriterionInput `json:"duplicated"`
|
||||
Hashes []*FingerprintFilterInput `json:"hashes"`
|
||||
|
||||
92
pkg/models/folder.go
Normal file
92
pkg/models/folder.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type FolderQueryOptions struct {
|
||||
QueryOptions
|
||||
FolderFilter *FolderFilterType
|
||||
|
||||
TotalDuration bool
|
||||
Megapixels bool
|
||||
TotalSize bool
|
||||
}
|
||||
|
||||
type FolderFilterType struct {
|
||||
OperatorFilter[FolderFilterType]
|
||||
|
||||
Path *StringCriterionInput `json:"path,omitempty"`
|
||||
Basename *StringCriterionInput `json:"basename,omitempty"`
|
||||
// Filter by parent directory path
|
||||
Dir *StringCriterionInput `json:"dir,omitempty"`
|
||||
ParentFolder *HierarchicalMultiCriterionInput `json:"parent_folder,omitempty"`
|
||||
ZipFile *MultiCriterionInput `json:"zip_file,omitempty"`
|
||||
// Filter by modification time
|
||||
ModTime *TimestampCriterionInput `json:"mod_time,omitempty"`
|
||||
GalleryCount *IntCriterionInput `json:"gallery_count,omitempty"`
|
||||
// Filter by files that meet this criteria
|
||||
FilesFilter *FileFilterType `json:"files_filter,omitempty"`
|
||||
// Filter by related galleries that meet this criteria
|
||||
GalleriesFilter *GalleryFilterType `json:"galleries_filter,omitempty"`
|
||||
// Filter by creation time
|
||||
CreatedAt *TimestampCriterionInput `json:"created_at,omitempty"`
|
||||
// Filter by last update time
|
||||
UpdatedAt *TimestampCriterionInput `json:"updated_at,omitempty"`
|
||||
}
|
||||
|
||||
func PathsFolderFilter(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 FolderQueryResult struct {
|
||||
QueryResult[FolderID]
|
||||
|
||||
getter FolderGetter
|
||||
folders []*Folder
|
||||
resolveErr error
|
||||
}
|
||||
|
||||
func NewFolderQueryResult(folderGetter FolderGetter) *FolderQueryResult {
|
||||
return &FolderQueryResult{
|
||||
getter: folderGetter,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *FolderQueryResult) Resolve(ctx context.Context) ([]*Folder, error) {
|
||||
// cache results
|
||||
if r.folders == nil && r.resolveErr == nil {
|
||||
r.folders, r.resolveErr = r.getter.FindMany(ctx, r.IDs)
|
||||
}
|
||||
return r.folders, r.resolveErr
|
||||
}
|
||||
@@ -201,6 +201,29 @@ func (_m *FolderReaderWriter) FindMany(ctx context.Context, id []models.FolderID
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// Query provides a mock function with given fields: ctx, options
|
||||
func (_m *FolderReaderWriter) Query(ctx context.Context, options models.FolderQueryOptions) (*models.FolderQueryResult, error) {
|
||||
ret := _m.Called(ctx, options)
|
||||
|
||||
var r0 *models.FolderQueryResult
|
||||
if rf, ok := ret.Get(0).(func(context.Context, models.FolderQueryOptions) *models.FolderQueryResult); ok {
|
||||
r0 = rf(ctx, options)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.FolderQueryResult)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, models.FolderQueryOptions) error); ok {
|
||||
r1 = rf(ctx, options)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// Update provides a mock function with given fields: ctx, f
|
||||
func (_m *FolderReaderWriter) Update(ctx context.Context, f *models.Folder) error {
|
||||
ret := _m.Called(ctx, f)
|
||||
|
||||
@@ -35,6 +35,14 @@ func (i FolderID) MarshalGQL(w io.Writer) {
|
||||
fmt.Fprint(w, strconv.Quote(i.String()))
|
||||
}
|
||||
|
||||
func FolderIDsFromInts(ids []int) []FolderID {
|
||||
ret := make([]FolderID, len(ids))
|
||||
for i, id := range ids {
|
||||
ret[i] = FolderID(id)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// Folder represents a folder in the file system.
|
||||
type Folder struct {
|
||||
ID FolderID `json:"id"`
|
||||
|
||||
@@ -17,6 +17,10 @@ type FolderFinder interface {
|
||||
FindByParentFolderID(ctx context.Context, parentFolderID FolderID) ([]*Folder, error)
|
||||
}
|
||||
|
||||
type FolderQueryer interface {
|
||||
Query(ctx context.Context, options FolderQueryOptions) (*FolderQueryResult, error)
|
||||
}
|
||||
|
||||
type FolderCounter interface {
|
||||
CountAllInPaths(ctx context.Context, p []string) (int, error)
|
||||
}
|
||||
@@ -48,6 +52,7 @@ type FolderFinderDestroyer interface {
|
||||
// FolderReader provides all methods to read folders.
|
||||
type FolderReader interface {
|
||||
FolderFinder
|
||||
FolderQueryer
|
||||
FolderCounter
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user