mirror of https://github.com/stashapp/stash.git
157 lines
3.3 KiB
Go
157 lines
3.3 KiB
Go
package jsonschema
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
jsoniter "github.com/json-iterator/go"
|
|
"github.com/stashapp/stash/pkg/hash/md5"
|
|
"github.com/stashapp/stash/pkg/models/json"
|
|
)
|
|
|
|
const (
|
|
DirEntryTypeFolder = "folder"
|
|
DirEntryTypeVideo = "video"
|
|
DirEntryTypeImage = "image"
|
|
DirEntryTypeFile = "file"
|
|
)
|
|
|
|
type DirEntry interface {
|
|
IsFile() bool
|
|
Filename() string
|
|
DirEntry() *BaseDirEntry
|
|
}
|
|
|
|
type BaseDirEntry struct {
|
|
ZipFile string `json:"zip_file,omitempty"`
|
|
ModTime json.JSONTime `json:"mod_time"`
|
|
|
|
Type string `json:"type,omitempty"`
|
|
|
|
Path string `json:"path,omitempty"`
|
|
|
|
CreatedAt json.JSONTime `json:"created_at,omitempty"`
|
|
UpdatedAt json.JSONTime `json:"updated_at,omitempty"`
|
|
}
|
|
|
|
func (f *BaseDirEntry) DirEntry() *BaseDirEntry {
|
|
return f
|
|
}
|
|
|
|
func (f *BaseDirEntry) IsFile() bool {
|
|
return false
|
|
}
|
|
|
|
func (f *BaseDirEntry) Filename() string {
|
|
// prefix with the path depth so that we can import lower-level files/folders first
|
|
depth := strings.Count(f.Path, string(filepath.Separator))
|
|
|
|
// hash the full path for a unique filename
|
|
hash := md5.FromString(f.Path)
|
|
|
|
basename := filepath.Base(f.Path)
|
|
|
|
return fmt.Sprintf("%02x.%s.%s.json", depth, basename, hash)
|
|
}
|
|
|
|
type BaseFile struct {
|
|
BaseDirEntry
|
|
|
|
Fingerprints []Fingerprint `json:"fingerprints,omitempty"`
|
|
Size int64 `json:"size"`
|
|
}
|
|
|
|
func (f *BaseFile) IsFile() bool {
|
|
return true
|
|
}
|
|
|
|
type Fingerprint struct {
|
|
Type string `json:"type,omitempty"`
|
|
Fingerprint interface{} `json:"fingerprint,omitempty"`
|
|
}
|
|
|
|
type VideoFile struct {
|
|
*BaseFile
|
|
Format string `json:"format,omitempty"`
|
|
Width int `json:"width,omitempty"`
|
|
Height int `json:"height,omitempty"`
|
|
Duration float64 `json:"duration,omitempty"`
|
|
VideoCodec string `json:"video_codec,omitempty"`
|
|
AudioCodec string `json:"audio_codec,omitempty"`
|
|
FrameRate float64 `json:"frame_rate,omitempty"`
|
|
BitRate int64 `json:"bitrate,omitempty"`
|
|
|
|
Interactive bool `json:"interactive,omitempty"`
|
|
InteractiveSpeed *int `json:"interactive_speed,omitempty"`
|
|
}
|
|
|
|
type ImageFile struct {
|
|
*BaseFile
|
|
Format string `json:"format,omitempty"`
|
|
Width int `json:"width,omitempty"`
|
|
Height int `json:"height,omitempty"`
|
|
}
|
|
|
|
func LoadFileFile(filePath string) (DirEntry, error) {
|
|
r, err := os.Open(filePath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer r.Close()
|
|
|
|
data, err := io.ReadAll(r)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
|
jsonParser := json.NewDecoder(bytes.NewReader(data))
|
|
|
|
var bf BaseDirEntry
|
|
if err := jsonParser.Decode(&bf); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
jsonParser = json.NewDecoder(bytes.NewReader(data))
|
|
|
|
switch bf.Type {
|
|
case DirEntryTypeFolder:
|
|
return &bf, nil
|
|
case DirEntryTypeVideo:
|
|
var vf VideoFile
|
|
if err := jsonParser.Decode(&vf); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &vf, nil
|
|
case DirEntryTypeImage:
|
|
var imf ImageFile
|
|
if err := jsonParser.Decode(&imf); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &imf, nil
|
|
case DirEntryTypeFile:
|
|
var bff BaseFile
|
|
if err := jsonParser.Decode(&bff); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &bff, nil
|
|
default:
|
|
return nil, errors.New("unknown file type")
|
|
}
|
|
}
|
|
|
|
func SaveFileFile(filePath string, file DirEntry) error {
|
|
if file == nil {
|
|
return fmt.Errorf("file must not be nil")
|
|
}
|
|
return marshalToFile(filePath, file)
|
|
}
|