Explorar o código

feature: onfileindir (#161)

* feature: onfileindir

* fmt: ActionButton.js
James Read %!s(int64=2) %!d(string=hai) anos
pai
achega
43ceb33b53
Modificáronse 3 ficheiros con 101 adicións e 12 borrados
  1. 2 0
      cmd/OliveTin/main.go
  2. 14 12
      internal/config/config.go
  3. 85 0
      internal/onfileindir/fileindir.go

+ 2 - 0
cmd/OliveTin/main.go

@@ -9,6 +9,7 @@ import (
 	grpcapi "github.com/OliveTin/OliveTin/internal/grpcapi"
 	"github.com/OliveTin/OliveTin/internal/installationinfo"
 	"github.com/OliveTin/OliveTin/internal/oncron"
+	"github.com/OliveTin/OliveTin/internal/onfileindir"
 	"github.com/OliveTin/OliveTin/internal/onstartup"
 	updatecheck "github.com/OliveTin/OliveTin/internal/updatecheck"
 	"github.com/OliveTin/OliveTin/internal/websocket"
@@ -115,6 +116,7 @@ func main() {
 
 	go onstartup.Execute(cfg, executor)
 	go oncron.Schedule(cfg, executor)
+	go onfileindir.WatchFilesInDirectory(cfg, executor)
 
 	go updatecheck.StartUpdateChecker(version, commit, cfg, configDir)
 

+ 14 - 12
internal/config/config.go

@@ -3,18 +3,20 @@ package config
 // Action represents the core functionality of OliveTin - commands that show up
 // as buttons in the UI.
 type Action struct {
-	ID            string
-	Title         string
-	Icon          string
-	Shell         string
-	CSS           map[string]string `mapstructure:"omitempty"`
-	Timeout       int
-	Acls          []string
-	ExecOnStartup bool
-	ExecOnCron    []string
-	MaxConcurrent int
-	Arguments     []ActionArgument
-	PopupOnStart  bool
+	ID                     string
+	Title                  string
+	Icon                   string
+	Shell                  string
+	CSS                    map[string]string `mapstructure:"omitempty"`
+	Timeout                int
+	Acls                   []string
+	ExecOnStartup          bool
+	ExecOnCron             []string
+	ExecOnFileCreatedInDir []string
+	ExecOnFileChangedInDir []string
+	MaxConcurrent          int
+	Arguments              []ActionArgument
+	PopupOnStart           bool
 }
 
 // ActionArgument objects appear on Actions.

+ 85 - 0
internal/onfileindir/fileindir.go

@@ -0,0 +1,85 @@
+package onfileindir
+
+import (
+	"github.com/OliveTin/OliveTin/internal/acl"
+	"github.com/OliveTin/OliveTin/internal/config"
+	"github.com/OliveTin/OliveTin/internal/executor"
+	"github.com/fsnotify/fsnotify"
+	log "github.com/sirupsen/logrus"
+)
+
+func WatchFilesInDirectory(cfg *config.Config, ex *executor.Executor) {
+	for _, action := range cfg.Actions {
+		for _, dirname := range action.ExecOnFileChangedInDir {
+			watch(dirname, action, cfg, ex, fsnotify.Write)
+		}
+
+		for _, dirname := range action.ExecOnFileCreatedInDir {
+			watch(dirname, action, cfg, ex, fsnotify.Create)
+		}
+	}
+}
+
+func watch(directory string, action config.Action, cfg *config.Config, ex *executor.Executor, eventType fsnotify.Op) {
+	log.WithFields(log.Fields{
+		"dir":       directory,
+		"eventType": eventType,
+	}).Infof("Watching dir")
+
+	watcher, err := fsnotify.NewWatcher()
+
+	if err != nil {
+		log.Errorf("Could not watch for files being created: %v", err)
+		return
+	}
+
+	defer watcher.Close()
+
+	done := make(chan bool)
+
+	go func() {
+		for {
+			processEvent(watcher, action, cfg, ex, eventType)
+		}
+	}()
+
+	err = watcher.Add("/tmp")
+
+	if err != nil {
+		log.Errorf("Could not create watcher: %v", err)
+	}
+
+	<-done
+}
+
+func processEvent(watcher *fsnotify.Watcher, action config.Action, cfg *config.Config, ex *executor.Executor, eventType fsnotify.Op) {
+	select {
+	case event, ok := <-watcher.Events:
+		if !ok {
+			return
+		}
+
+		checkEvent(&event, action, cfg, ex, eventType)
+	case err := <-watcher.Errors:
+		log.Errorf("Error in fsnotify: %v", err)
+		return
+	}
+}
+
+func checkEvent(event *fsnotify.Event, action config.Action, cfg *config.Config, ex *executor.Executor, eventType fsnotify.Op) {
+	if event.Has(eventType) {
+		req := &executor.ExecutionRequest{
+			ActionName: action.Title,
+			Cfg:        cfg,
+			Tags:       []string{"fileindir"},
+			Arguments: map[string]string{
+				"filename": event.Name,
+			},
+			AuthenticatedUser: &acl.AuthenticatedUser{
+				Username: "fileindir",
+			},
+		}
+
+		ex.ExecRequest(req)
+	}
+}