1
Fork 0
photoview/api/scanner/scanner_media.go

123 lines
2.6 KiB
Go
Raw Normal View History

2020-02-23 18:00:08 +01:00
package scanner
import (
2020-11-16 21:57:34 +01:00
"crypto/md5"
"encoding/hex"
"io"
2020-02-23 18:00:08 +01:00
"log"
"os"
2020-02-23 18:00:08 +01:00
"path"
2020-02-26 19:44:47 +01:00
2020-07-10 18:57:27 +02:00
"github.com/pkg/errors"
2020-02-26 19:44:47 +01:00
"github.com/viktorstrate/photoview/api/graphql/models"
2020-11-23 19:59:01 +01:00
"gorm.io/gorm"
2020-02-23 18:00:08 +01:00
)
2020-11-16 21:57:34 +01:00
func scanForSideCarFile(path string) *string {
testPath := path + ".xmp"
_, err := os.Stat(testPath)
if os.IsNotExist(err) {
return nil
} else if err != nil {
// unexpected error logging
log.Printf("ERROR: %s", err)
return nil
}
return &testPath
}
func hashSideCarFile(path *string) *string {
if path == nil {
return nil
}
f, err := os.Open(*path)
if err != nil {
log.Printf("ERROR: %s", err)
}
defer f.Close()
h := md5.New()
if _, err := io.Copy(h, f); err != nil {
log.Printf("ERROR: %s", err)
}
hash := hex.EncodeToString(h.Sum(nil))
return &hash
}
func ScanMedia(tx *gorm.DB, mediaPath string, albumId int, cache *AlbumScannerCache) (*models.Media, bool, error) {
2020-07-10 18:57:27 +02:00
mediaName := path.Base(mediaPath)
2020-02-23 18:00:08 +01:00
2020-11-23 20:43:00 +01:00
// Check if media already exists
{
2020-11-23 20:43:00 +01:00
var media models.Media
if err := tx.Where("path_hash = MD5(?)", mediaPath).First(&media).Error; errors.Is(err, gorm.ErrRecordNotFound) {
if err == nil {
log.Printf("Media already scanned: %s\n", mediaPath)
2020-11-23 20:43:00 +01:00
return &media, false, nil
} else {
2020-07-10 18:57:27 +02:00
return nil, false, errors.Wrap(err, "scan media fetch from database")
}
2020-02-23 18:00:08 +01:00
}
}
2020-07-10 18:57:27 +02:00
log.Printf("Scanning media: %s\n", mediaPath)
mediaType, err := cache.GetMediaType(mediaPath)
if err != nil {
return nil, false, errors.Wrap(err, "could determine if media was photo or video")
}
2020-11-23 20:43:00 +01:00
var mediaTypeText models.MediaType
var sideCarPath *string = nil
var sideCarHash *string = nil
2020-11-16 21:57:34 +01:00
if mediaType.isVideo() {
2020-11-23 20:43:00 +01:00
mediaTypeText = models.MediaTypeVideo
} else {
2020-11-23 20:43:00 +01:00
mediaTypeText = models.MediaTypePhoto
2020-11-16 21:57:34 +01:00
// search for sidecar files
if mediaType.isRaw() {
sideCarPath = scanForSideCarFile(mediaPath)
if sideCarPath != nil {
sideCarHash = hashSideCarFile(sideCarPath)
}
}
}
stat, err := os.Stat(mediaPath)
if err != nil {
return nil, false, err
}
2020-11-23 20:43:00 +01:00
media := models.Media{
Title: mediaName,
Path: mediaPath,
SideCarPath: sideCarPath,
SideCarHash: sideCarHash,
AlbumID: albumId,
2020-11-23 20:43:00 +01:00
Type: mediaTypeText,
DateShot: stat.ModTime(),
2020-02-23 18:00:08 +01:00
}
2020-11-23 20:43:00 +01:00
if err := tx.Create(&media).Error; err != nil {
return nil, false, errors.Wrap(err, "could not insert media into database")
2020-02-23 18:00:08 +01:00
}
2020-11-23 20:43:00 +01:00
_, err = ScanEXIF(tx, &media)
2020-02-24 23:30:08 +01:00
if err != nil {
2020-07-10 18:57:27 +02:00
log.Printf("WARN: ScanEXIF for %s failed: %s\n", mediaName, err)
2020-02-24 23:30:08 +01:00
}
2020-07-12 14:17:49 +02:00
if media.Type == models.MediaTypeVideo {
2020-11-25 23:06:47 +01:00
if err = ScanVideoMetadata(tx, &media); err != nil {
2020-07-12 14:17:49 +02:00
log.Printf("WARN: ScanVideoMetadata for %s failed: %s\n", mediaName, err)
}
}
2020-11-23 20:43:00 +01:00
return &media, true, nil
2020-02-23 18:00:08 +01:00
}