2023-01-17 05:55:20 +01:00
|
|
|
package watcher_scanner
|
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/fsnotify/fsnotify"
|
|
|
|
"github.com/photoview/photoview/api/graphql/models"
|
|
|
|
"github.com/photoview/photoview/api/scanner/scanner_queue"
|
2023-01-23 05:50:29 +01:00
|
|
|
"github.com/photoview/photoview/api/utils"
|
2023-01-17 05:55:20 +01:00
|
|
|
"github.com/pkg/errors"
|
|
|
|
"gorm.io/gorm"
|
2023-01-23 05:36:03 +01:00
|
|
|
"gorm.io/gorm/clause"
|
2023-01-17 05:55:20 +01:00
|
|
|
"log"
|
2023-01-23 05:50:29 +01:00
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
"strconv"
|
2023-01-17 05:55:20 +01:00
|
|
|
"sync"
|
|
|
|
)
|
|
|
|
|
|
|
|
var mainWatcherScanner *watcherScanner = nil
|
|
|
|
|
|
|
|
type watcherScanner struct {
|
|
|
|
watcherChanged chan bool
|
|
|
|
watcher *fsnotify.Watcher
|
|
|
|
mutex *sync.Mutex
|
|
|
|
db *gorm.DB
|
|
|
|
}
|
|
|
|
|
|
|
|
func InitializeWatcherScanner(db *gorm.DB) error {
|
|
|
|
if mainWatcherScanner != nil {
|
|
|
|
panic("watcher scanner has already been initialized")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create new watcher
|
|
|
|
watcher, err := fsnotify.NewWatcher()
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
mainWatcherScanner = &watcherScanner{
|
|
|
|
db: db,
|
|
|
|
watcherChanged: make(chan bool),
|
|
|
|
watcher: watcher,
|
|
|
|
mutex: &sync.Mutex{},
|
|
|
|
}
|
|
|
|
|
|
|
|
success, errs := mainWatcherScanner.addPathsToWatch()
|
|
|
|
if len(errs) != 0 {
|
|
|
|
log.Println("watcher errors")
|
|
|
|
log.Println(errs)
|
|
|
|
if !success {
|
|
|
|
return errors.New("errors found during watcher scanner setup")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
go mainWatcherScanner.processWatchEvents()
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ws watcherScanner) addPathsToWatch() (bool, []error) {
|
|
|
|
var allAlbumPaths []*models.Album
|
|
|
|
|
|
|
|
if err := ws.db.Select("path").Find(&allAlbumPaths).Error; err != nil {
|
|
|
|
return false, []error{errors.Wrap(err, "watcher scanner find albums query")}
|
|
|
|
}
|
|
|
|
|
|
|
|
errs := make([]error, 0)
|
|
|
|
for _, album := range allAlbumPaths {
|
|
|
|
// log.Println("add path", album.Path)
|
|
|
|
err := ws.watcher.Add(album.Path)
|
|
|
|
if err != nil {
|
|
|
|
errs = append(errs, errors.Wrap(err, "add path watcher scanner"))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return len(allAlbumPaths) != len(errs), errs
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ws watcherScanner) processWatchEvents() {
|
|
|
|
log.Println("watching for events")
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case event, ok := <-ws.watcher.Events:
|
|
|
|
if !ok {
|
|
|
|
//log.Println("not ok", event)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
log.Println("event:", event)
|
|
|
|
var media *models.Media
|
2023-01-22 04:50:15 +01:00
|
|
|
if event.Has(fsnotify.Create) || event.Has(fsnotify.Write) {
|
2023-01-17 05:55:20 +01:00
|
|
|
scanner_queue.AddMediaToQueue(event.Name)
|
|
|
|
log.Println("create event ", event.Name, event.Op)
|
|
|
|
} else if event.Has(fsnotify.Remove) {
|
2023-01-23 05:36:03 +01:00
|
|
|
ws.db.Preload(clause.Associations).Where("path = ?", event.Name).Find(&media)
|
|
|
|
// todo: why doesnt exif cascade delete invoked ?
|
2023-01-23 05:50:29 +01:00
|
|
|
// todo: remove from media_cache
|
2023-01-23 05:36:03 +01:00
|
|
|
if media.Exif != nil {
|
|
|
|
ws.db.Delete(&media.Exif)
|
|
|
|
}
|
2023-01-23 05:50:29 +01:00
|
|
|
cachePath := path.Join(utils.MediaCachePath(), strconv.Itoa(int(media.AlbumID)), strconv.Itoa(int(media.ID)))
|
|
|
|
err := os.RemoveAll(cachePath)
|
|
|
|
if err != nil {
|
|
|
|
log.Println("delete media from cache", err)
|
|
|
|
}
|
2023-01-23 06:19:41 +01:00
|
|
|
if media != nil && media.ID != 0 {
|
|
|
|
ws.db.Select(clause.Associations).Delete(&media)
|
|
|
|
}
|
2023-01-17 05:55:20 +01:00
|
|
|
log.Println("remove event ", event.Name, event.Op)
|
|
|
|
} else if event.Has(fsnotify.Rename) {
|
|
|
|
log.Println("rename event ", event.Name, event.Op)
|
|
|
|
}
|
|
|
|
case err, ok := <-ws.watcher.Errors:
|
|
|
|
if !ok {
|
|
|
|
//log.Println("not ok, error", err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
log.Println("error:", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|