Files
photoview/api/scanner/scanner_media.go
Kostiantyn 2b1240b88b Refactor API video route (#1202)
* Refactored code; temp disable workflows on push

* remove printf leftovers

* A better sanitizing code

* extend auth routes tests

* more tests, fix 2 bugs in token processing

* more refactoring and fixes

* optimize video mediaURLs DB query and make testCachePath in utils thread-safe

* fix always passing test

* and more refactoring; 1 more test, but cleanup still has to be fixed

* more debug code in the test

* fix the test

* Final commit

* Adding a defer function just in case of panic

* Address some of review comments

* Protect the shared var by mutex; implement correct context-aware scanning

* Better error; better initial func wrap/capture; better log messages in `photos.go`;

* Addressing a few more review comments

* Order the query results; a better error type catch; setting the MP4 content type header explicitly

* try to fix the cancelation detection condition

* Extract a function and call it by name

---------

Co-authored-by: Konstantin Koval
2025-06-18 20:38:19 +03:00

92 lines
2.3 KiB
Go

package scanner
import (
"context"
"log"
"os"
"path"
"github.com/photoview/photoview/api/graphql/models"
"github.com/photoview/photoview/api/scanner/media_encoding"
"github.com/photoview/photoview/api/scanner/scanner_cache"
"github.com/photoview/photoview/api/scanner/scanner_task"
"github.com/pkg/errors"
"gorm.io/gorm"
)
var ProcessSingleMediaFunc = ProcessSingleMedia
func ScanMedia(tx *gorm.DB, mediaPath string, albumId int, cache *scanner_cache.AlbumScannerCache) (*models.Media, bool, error) {
mediaName := path.Base(mediaPath)
// Check if media already exists
{
var media []*models.Media
result := tx.Where("path_hash = ?", models.MD5Hash(mediaPath)).Find(&media)
if result.Error != nil {
return nil, false, errors.Wrap(result.Error, "scan media fetch from database")
}
if result.RowsAffected > 0 {
// log.Printf("Media already scanned: %s\n", mediaPath)
return media[0], false, nil
}
}
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")
}
var mediaTypeText models.MediaType
if mediaType.IsVideo() {
mediaTypeText = models.MediaTypeVideo
} else {
mediaTypeText = models.MediaTypePhoto
}
stat, err := os.Stat(mediaPath)
if err != nil {
return nil, false, err
}
media := models.Media{
Title: mediaName,
Path: mediaPath,
AlbumID: albumId,
Type: mediaTypeText,
DateShot: stat.ModTime(),
}
if err := tx.Create(&media).Error; err != nil {
return nil, false, errors.Wrap(err, "could not insert media into database")
}
return &media, true, nil
}
// ProcessSingleMedia processes a single media, might be used to reprocess media with corrupted cache
// Function waits for processing to finish before returning.
func ProcessSingleMedia(ctx context.Context, db *gorm.DB, media *models.Media) error {
albumCache := scanner_cache.MakeAlbumCache()
var album models.Album
if err := db.Model(media).Association("Album").Find(&album); err != nil {
return err
}
mediaData := media_encoding.NewEncodeMediaData(media)
taskContext := scanner_task.NewTaskContext(ctx, db, &album, albumCache)
if err := scanMedia(taskContext, media, &mediaData, 0, 1); err != nil {
return errors.Wrap(err, "single media scan")
}
return nil
}