package trigger import ( "context" "encoding/json" "os" "sync" "time" . "github.com/mickael-kerjean/filestash/server/common" "github.com/mickael-kerjean/filestash/server/model" ) var ( filewatch_event = make(chan ITriggerEvent, 1) filewatch_name = "watch" filewatch_state sync.Map ) func init() { Hooks.Register.WorkflowTrigger(&WatchTrigger{}) } type WatchTrigger struct{} func (this *WatchTrigger) Manifest() WorkflowSpecs { return WorkflowSpecs{ Name: "watch", Title: "When the Filesystem Changes", Icon: ``, Specs: Form{ Elmnts: []FormElement{ { Name: "token", Type: "text", }, { Name: "path", Type: "text", }, }, }, Order: 4, } } func (this *WatchTrigger) Init() (chan ITriggerEvent, error) { go func() { for { if err := triggerEvents(filewatch_event, filewatch_name, filewatchCallback); err != nil { Log.Error("[workflow] trigger=watch step=triggerEvents err=%s", err.Error()) } time.Sleep(10 * time.Second) } }() return filewatch_event, nil } func filewatchCallback(params map[string]string) (map[string]string, bool) { out := map[string]string{"path": params["path"]} backend, session, err := createBackend(params["token"]) if err != nil { Log.Error("[workflow] trigger=filewatch step=callback::init err=%s", err.Error()) return out, false } files, err := backend.Ls(params["path"]) if err != nil { Log.Error("[workflow] trigger=filewatch step=callback::ls err=%s", err.Error()) return out, false } key := GenerateID(session) + params["path"] fincache, exists := filewatch_state.Load(key) if !exists { filewatch_state.Store(key, files) return out, false } prevFiles := fincache.([]os.FileInfo) if len(files) != len(prevFiles) { filewatch_state.Store(key, files) return out, true } changes := []string{} for i := 0; i < len(files); i++ { hasChange := false if files[i].Name() != prevFiles[i].Name() { hasChange = true } else if files[i].Size() != prevFiles[i].Size() { hasChange = true } else if files[i].ModTime() != prevFiles[i].ModTime() { hasChange = true } if hasChange { p := JoinPath(params["path"], files[i].Name()) if files[i].IsDir() { p = EnforceDirectory(p) } changes = append(changes, p) } } if len(changes) > 0 { filewatch_state.Store(key, files) return out, true } return out, false } func createBackend(token string) (IBackend, map[string]string, error) { session := map[string]string{} str, err := DecryptString(SECRET_KEY_DERIVATE_FOR_USER, token) if err != nil { return nil, session, err } if err = json.Unmarshal([]byte(str), &session); err != nil { return nil, session, err } backend, err := model.NewBackend( &App{Context: context.Background()}, session, ) return backend, session, err }