Scan refactor (#1816)

* Add file scanner
* Scan scene changes
* Split scan files
* Generalise scan
* Refactor ffprobe
* Refactor ffmpeg encoder
* Move scene scan code to scene package
* Move matchExtension to utils
* Refactor gallery scanning
* Refactor image scanning
* Prevent race conditions on identical hashes
* Refactor image thumbnail generation
* Perform count concurrently
* Allow progress increment before total set
* Make progress updates more frequent
This commit is contained in:
WithoutPants
2021-10-15 10:39:48 +11:00
committed by GitHub
parent 3d5ee16e90
commit 39fdde273d
55 changed files with 2172 additions and 1429 deletions

View File

@@ -3,6 +3,7 @@ package models
import (
"database/sql"
"path/filepath"
"time"
)
// Scene stores the metadata for a single video scene.
@@ -35,6 +36,58 @@ type Scene struct {
Interactive bool `db:"interactive" json:"interactive"`
}
func (s *Scene) File() File {
ret := File{
Path: s.Path,
}
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
}
func (s *Scene) 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,
}
}
}
// ScenePartial represents part of a Scene object. It is used to update
// the database entry. Only non-nil fields will be updated.
type ScenePartial struct {
@@ -66,6 +119,37 @@ type ScenePartial struct {
Interactive *bool `db:"interactive" json:"interactive"`
}
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,
}
}
}
// GetTitle returns the title of the scene. If the Title field is empty,
// then the base filename is returned.
func (s Scene) GetTitle() string {
@@ -79,13 +163,7 @@ func (s Scene) GetTitle() string {
// 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 {
if hashAlgorithm == HashAlgorithmMd5 {
return s.Checksum.String
} else if hashAlgorithm == HashAlgorithmOshash {
return s.OSHash.String
}
panic("unknown hash algorithm")
return s.File().GetHash(hashAlgorithm)
}
func (s Scene) GetMinResolution() int64 {