mirror of https://github.com/stashapp/stash.git
Add fingerprint resolver (#4287)
* Refactor into internal/api/models.go * Add file fingerprint resolver
This commit is contained in:
parent
a0f33e3dab
commit
049a1b15c3
18
gqlgen.yml
18
gqlgen.yml
|
@ -14,6 +14,7 @@ resolver:
|
|||
struct_tag: gqlgen
|
||||
|
||||
autobind:
|
||||
- github.com/stashapp/stash/internal/api
|
||||
- github.com/stashapp/stash/pkg/models
|
||||
- github.com/stashapp/stash/pkg/plugin
|
||||
- github.com/stashapp/stash/pkg/scraper
|
||||
|
@ -41,30 +42,13 @@ models:
|
|||
fields:
|
||||
title:
|
||||
resolver: true
|
||||
# override models, from internal/api/models.go
|
||||
BaseFile:
|
||||
model: github.com/stashapp/stash/internal/api.BaseFile
|
||||
GalleryFile:
|
||||
model: github.com/stashapp/stash/internal/api.GalleryFile
|
||||
fields:
|
||||
# override fingerprint field
|
||||
fingerprints:
|
||||
fieldName: FingerprintSlice
|
||||
VideoFile:
|
||||
fields:
|
||||
# override fingerprint field
|
||||
fingerprints:
|
||||
fieldName: FingerprintSlice
|
||||
# override float fields - #1572
|
||||
duration:
|
||||
fieldName: DurationFinite
|
||||
frame_rate:
|
||||
fieldName: FrameRateFinite
|
||||
ImageFile:
|
||||
fields:
|
||||
# override fingerprint field
|
||||
fingerprints:
|
||||
fieldName: FingerprintSlice
|
||||
# autobind on config causes generation issues
|
||||
BlobsStorageType:
|
||||
model: github.com/stashapp/stash/internal/manager/config.BlobsStorageType
|
||||
|
|
|
@ -27,6 +27,7 @@ interface BaseFile {
|
|||
mod_time: Time!
|
||||
size: Int64!
|
||||
|
||||
fingerprint(type: String!): String
|
||||
fingerprints: [Fingerprint!]!
|
||||
|
||||
created_at: Time!
|
||||
|
@ -44,6 +45,7 @@ type VideoFile implements BaseFile {
|
|||
mod_time: Time!
|
||||
size: Int64!
|
||||
|
||||
fingerprint(type: String!): String
|
||||
fingerprints: [Fingerprint!]!
|
||||
|
||||
format: String!
|
||||
|
@ -70,6 +72,7 @@ type ImageFile implements BaseFile {
|
|||
mod_time: Time!
|
||||
size: Int64!
|
||||
|
||||
fingerprint(type: String!): String
|
||||
fingerprints: [Fingerprint!]!
|
||||
|
||||
width: Int!
|
||||
|
@ -92,6 +95,7 @@ type GalleryFile implements BaseFile {
|
|||
mod_time: Time!
|
||||
size: Int64!
|
||||
|
||||
fingerprint(type: String!): String
|
||||
fingerprints: [Fingerprint!]!
|
||||
|
||||
created_at: Time!
|
||||
|
|
|
@ -1,11 +1,64 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/stashapp/stash/pkg/models"
|
||||
)
|
||||
|
||||
type BaseFile interface{}
|
||||
type BaseFile interface {
|
||||
IsBaseFile()
|
||||
}
|
||||
|
||||
type VisualFile interface {
|
||||
IsVisualFile()
|
||||
}
|
||||
|
||||
func convertVisualFile(f models.File) (VisualFile, error) {
|
||||
switch f := f.(type) {
|
||||
case VisualFile:
|
||||
return f, nil
|
||||
case *models.VideoFile:
|
||||
return &VideoFile{VideoFile: f}, nil
|
||||
case *models.ImageFile:
|
||||
return &ImageFile{ImageFile: f}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("file %s is not a visual file", f.Base().Path)
|
||||
}
|
||||
}
|
||||
|
||||
type GalleryFile struct {
|
||||
*models.BaseFile
|
||||
}
|
||||
|
||||
func (GalleryFile) IsBaseFile() {}
|
||||
|
||||
func (GalleryFile) IsVisualFile() {}
|
||||
|
||||
func (f *GalleryFile) Fingerprints() []models.Fingerprint {
|
||||
return f.BaseFile.Fingerprints
|
||||
}
|
||||
|
||||
type VideoFile struct {
|
||||
*models.VideoFile
|
||||
}
|
||||
|
||||
func (VideoFile) IsBaseFile() {}
|
||||
|
||||
func (VideoFile) IsVisualFile() {}
|
||||
|
||||
func (f *VideoFile) Fingerprints() []models.Fingerprint {
|
||||
return f.VideoFile.Fingerprints
|
||||
}
|
||||
|
||||
type ImageFile struct {
|
||||
*models.ImageFile
|
||||
}
|
||||
|
||||
func (ImageFile) IsBaseFile() {}
|
||||
|
||||
func (ImageFile) IsVisualFile() {}
|
||||
|
||||
func (f *ImageFile) Fingerprints() []models.Fingerprint {
|
||||
return f.ImageFile.Fingerprints
|
||||
}
|
||||
|
|
|
@ -81,6 +81,15 @@ func (r *Resolver) Subscription() SubscriptionResolver {
|
|||
func (r *Resolver) Tag() TagResolver {
|
||||
return &tagResolver{r}
|
||||
}
|
||||
func (r *Resolver) GalleryFile() GalleryFileResolver {
|
||||
return &galleryFileResolver{r}
|
||||
}
|
||||
func (r *Resolver) VideoFile() VideoFileResolver {
|
||||
return &videoFileResolver{r}
|
||||
}
|
||||
func (r *Resolver) ImageFile() ImageFileResolver {
|
||||
return &imageFileResolver{r}
|
||||
}
|
||||
func (r *Resolver) SavedFilter() SavedFilterResolver {
|
||||
return &savedFilterResolver{r}
|
||||
}
|
||||
|
@ -104,6 +113,9 @@ type imageResolver struct{ *Resolver }
|
|||
type studioResolver struct{ *Resolver }
|
||||
type movieResolver struct{ *Resolver }
|
||||
type tagResolver struct{ *Resolver }
|
||||
type galleryFileResolver struct{ *Resolver }
|
||||
type videoFileResolver struct{ *Resolver }
|
||||
type imageFileResolver struct{ *Resolver }
|
||||
type savedFilterResolver struct{ *Resolver }
|
||||
type pluginResolver struct{ *Resolver }
|
||||
type configResultResolver struct{ *Resolver }
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
package api
|
||||
|
||||
import "context"
|
||||
|
||||
func (r *galleryFileResolver) Fingerprint(ctx context.Context, obj *GalleryFile, type_ string) (*string, error) {
|
||||
fp := obj.BaseFile.Fingerprints.For(type_)
|
||||
if fp != nil {
|
||||
v := fp.Value()
|
||||
return &v, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *imageFileResolver) Fingerprint(ctx context.Context, obj *ImageFile, type_ string) (*string, error) {
|
||||
fp := obj.ImageFile.Fingerprints.For(type_)
|
||||
if fp != nil {
|
||||
v := fp.Value()
|
||||
return &v, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *videoFileResolver) Fingerprint(ctx context.Context, obj *VideoFile, type_ string) (*string, error) {
|
||||
fp := obj.VideoFile.Fingerprints.For(type_)
|
||||
if fp != nil {
|
||||
v := fp.Value()
|
||||
return &v, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
|
@ -2,21 +2,12 @@ package api
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/stashapp/stash/internal/api/loaders"
|
||||
"github.com/stashapp/stash/internal/api/urlbuilders"
|
||||
"github.com/stashapp/stash/pkg/models"
|
||||
)
|
||||
|
||||
func convertVisualFile(f models.File) (models.VisualFile, error) {
|
||||
vf, ok := f.(models.VisualFile)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("file %s is not a visual file", f.Base().Path)
|
||||
}
|
||||
return vf, nil
|
||||
}
|
||||
|
||||
func (r *imageResolver) getFiles(ctx context.Context, obj *models.Image) ([]models.File, error) {
|
||||
fileIDs, err := loaders.From(ctx).ImageFiles.Load(obj.ID)
|
||||
if err != nil {
|
||||
|
@ -32,13 +23,13 @@ func (r *imageResolver) Title(ctx context.Context, obj *models.Image) (*string,
|
|||
return &ret, nil
|
||||
}
|
||||
|
||||
func (r *imageResolver) VisualFiles(ctx context.Context, obj *models.Image) ([]models.VisualFile, error) {
|
||||
func (r *imageResolver) VisualFiles(ctx context.Context, obj *models.Image) ([]VisualFile, error) {
|
||||
files, err := r.getFiles(ctx, obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := make([]models.VisualFile, len(files))
|
||||
ret := make([]VisualFile, len(files))
|
||||
for i, f := range files {
|
||||
ret[i], err = convertVisualFile(f)
|
||||
if err != nil {
|
||||
|
@ -57,13 +48,13 @@ func (r *imageResolver) Date(ctx context.Context, obj *models.Image) (*string, e
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *imageResolver) Files(ctx context.Context, obj *models.Image) ([]*models.ImageFile, error) {
|
||||
func (r *imageResolver) Files(ctx context.Context, obj *models.Image) ([]*ImageFile, error) {
|
||||
files, err := r.getFiles(ctx, obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ret []*models.ImageFile
|
||||
var ret []*ImageFile
|
||||
|
||||
for _, f := range files {
|
||||
// filter out non-image files
|
||||
|
@ -72,7 +63,9 @@ func (r *imageResolver) Files(ctx context.Context, obj *models.Image) ([]*models
|
|||
continue
|
||||
}
|
||||
|
||||
ret = append(ret, imageFile)
|
||||
ret = append(ret, &ImageFile{
|
||||
ImageFile: imageFile,
|
||||
})
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
|
|
|
@ -73,13 +73,21 @@ func (r *sceneResolver) Date(ctx context.Context, obj *models.Scene) (*string, e
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *sceneResolver) Files(ctx context.Context, obj *models.Scene) ([]*models.VideoFile, error) {
|
||||
func (r *sceneResolver) Files(ctx context.Context, obj *models.Scene) ([]*VideoFile, error) {
|
||||
files, err := r.getFiles(ctx, obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return files, nil
|
||||
ret := make([]*VideoFile, len(files))
|
||||
|
||||
for i, f := range files {
|
||||
ret[i] = &VideoFile{
|
||||
VideoFile: f,
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (r *sceneResolver) Rating(ctx context.Context, obj *models.Scene) (*int, error) {
|
||||
|
|
|
@ -133,10 +133,6 @@ type BaseFile struct {
|
|||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
func (f *BaseFile) FingerprintSlice() []Fingerprint {
|
||||
return f.Fingerprints
|
||||
}
|
||||
|
||||
// SetFingerprints sets the fingerprints of the file.
|
||||
// If a fingerprint of the same type already exists, it is overwritten.
|
||||
func (f *BaseFile) SetFingerprints(fp Fingerprints) {
|
||||
|
|
Loading…
Reference in New Issue