Notice configuration changes and restart the watchers.
This commit is contained in:
parent
90f8c3588b
commit
fd6f6884ee
@ -38,7 +38,8 @@ type ConfigV2 struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ConfigService struct {
|
type ConfigService struct {
|
||||||
Config ConfigV2
|
Config *ConfigV2
|
||||||
|
Changed chan bool
|
||||||
ConfigFilename string
|
ConfigFilename string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,7 +58,7 @@ func (c *ConfigService) LoadOrInit() error {
|
|||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
daulog.SendLog("NOTE: No config file, writing out sample configuration", daulog.LogTypeInfo)
|
daulog.SendLog("NOTE: No config file, writing out sample configuration", daulog.LogTypeInfo)
|
||||||
daulog.SendLog("You need to set the configuration via the web interface", daulog.LogTypeInfo)
|
daulog.SendLog("You need to set the configuration via the web interface", daulog.LogTypeInfo)
|
||||||
c.Config = *DefaultConfig()
|
c.Config = DefaultConfig()
|
||||||
return c.Save()
|
return c.Save()
|
||||||
} else {
|
} else {
|
||||||
return c.Load()
|
return c.Load()
|
||||||
@ -158,6 +159,7 @@ func (c *ConfigService) Save() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cannot save config %s: %s", c.ConfigFilename, err.Error())
|
return fmt.Errorf("cannot save config %s: %s", c.ConfigFilename, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
46
dau.go
46
dau.go
@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -39,8 +40,10 @@ func main() {
|
|||||||
|
|
||||||
parseOptions()
|
parseOptions()
|
||||||
|
|
||||||
// grab the config
|
// grab the config, register to notice changes
|
||||||
config := config.DefaultConfigService()
|
config := config.DefaultConfigService()
|
||||||
|
configChanged := make(chan bool)
|
||||||
|
config.Changed = configChanged
|
||||||
config.LoadOrInit()
|
config.LoadOrInit()
|
||||||
|
|
||||||
// create the uploader
|
// create the uploader
|
||||||
@ -48,26 +51,41 @@ func main() {
|
|||||||
|
|
||||||
// log.Print("Opening web browser")
|
// log.Print("Opening web browser")
|
||||||
// open.Start("http://localhost:9090")
|
// open.Start("http://localhost:9090")
|
||||||
web := web.WebService{Config: *config}
|
web := web.WebService{Config: config}
|
||||||
web.StartWebServer()
|
web.StartWebServer()
|
||||||
|
|
||||||
go func() { checkUpdates() }()
|
go func() { checkUpdates() }()
|
||||||
|
|
||||||
// create the watchers
|
// create the watchers, restart them if config changes
|
||||||
|
// blocks forever
|
||||||
|
startWatchers(config, &up, configChanged)
|
||||||
|
|
||||||
log.Printf("Conf: %#v", config.Config)
|
|
||||||
|
|
||||||
for _, c := range config.Config.Watchers {
|
|
||||||
log.Printf("Creating watcher for %v", c)
|
|
||||||
watcher := watch{uploader: up, lastCheck: time.Now(), newLastCheck: time.Now(), config: c}
|
|
||||||
go watcher.Watch(config.Config.WatchInterval)
|
|
||||||
}
|
|
||||||
|
|
||||||
select {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *watch) Watch(interval int) {
|
func startWatchers(config *config.ConfigService, up *upload.Uploader, configChange chan bool) {
|
||||||
for {
|
for {
|
||||||
|
log.Printf("Creating watchers")
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
for _, c := range config.Config.Watchers {
|
||||||
|
log.Printf("Creating watcher for %s interval %d", c.Path, config.Config.WatchInterval)
|
||||||
|
watcher := watch{uploader: *up, lastCheck: time.Now(), newLastCheck: time.Now(), config: c}
|
||||||
|
go watcher.Watch(config.Config.WatchInterval, ctx)
|
||||||
|
}
|
||||||
|
// wait for single that the config changed
|
||||||
|
<-configChange
|
||||||
|
cancel()
|
||||||
|
log.Printf("starting new watchers due to config change")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *watch) Watch(interval int, ctx context.Context) {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
log.Printf("Killing old watcher")
|
||||||
|
return
|
||||||
|
default:
|
||||||
newFiles := w.ProcessNewFiles()
|
newFiles := w.ProcessNewFiles()
|
||||||
for _, f := range newFiles {
|
for _, f := range newFiles {
|
||||||
w.uploader.AddFile(f, w.config)
|
w.uploader.AddFile(f, w.config)
|
||||||
@ -77,6 +95,7 @@ func (w *watch) Watch(interval int) {
|
|||||||
daulog.SendLog(fmt.Sprintf("sleeping for %ds before next check of %s", interval, w.config.Path), daulog.LogTypeDebug)
|
daulog.SendLog(fmt.Sprintf("sleeping for %ds before next check of %s", interval, w.config.Path), daulog.LogTypeDebug)
|
||||||
time.Sleep(time.Duration(interval) * time.Second)
|
time.Sleep(time.Duration(interval) * time.Second)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProcessNewFiles returns an array of new files that have appeared since
|
// ProcessNewFiles returns an array of new files that have appeared since
|
||||||
@ -119,7 +138,6 @@ func (w *watch) checkPath() bool {
|
|||||||
// If the file is eligible, not excluded and new enough to care we add it
|
// If the file is eligible, not excluded and new enough to care we add it
|
||||||
// to the passed in array of files
|
// to the passed in array of files
|
||||||
func (w *watch) checkFile(path string, found *[]string, exclusions []string) error {
|
func (w *watch) checkFile(path string, found *[]string, exclusions []string) error {
|
||||||
log.Printf("Considering %s", path)
|
|
||||||
|
|
||||||
extension := strings.ToLower(filepath.Ext(path))
|
extension := strings.ToLower(filepath.Ext(path))
|
||||||
|
|
||||||
|
96
dau_test.go
Normal file
96
dau_test.go
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/tardisx/discord-auto-upload/config"
|
||||||
|
"github.com/tardisx/discord-auto-upload/upload"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestWatchNewFiles(t *testing.T) {
|
||||||
|
dir := createFileTree()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
|
w := watch{
|
||||||
|
config: config.Watcher{Path: dir},
|
||||||
|
uploader: upload.Uploader{},
|
||||||
|
lastCheck: time.Now(),
|
||||||
|
newLastCheck: time.Now(),
|
||||||
|
}
|
||||||
|
files := w.ProcessNewFiles()
|
||||||
|
if len(files) != 0 {
|
||||||
|
t.Errorf("was not zero files (%d): %v", len(files), files)
|
||||||
|
}
|
||||||
|
// create a new file
|
||||||
|
os.Create(fmt.Sprintf("%s%c%s", dir, os.PathSeparator, "b.gif"))
|
||||||
|
files = w.ProcessNewFiles()
|
||||||
|
if len(files) != 1 {
|
||||||
|
t.Error("was not one file")
|
||||||
|
}
|
||||||
|
if files[0] != fmt.Sprintf("%s%c%s", dir, os.PathSeparator, "b.gif") {
|
||||||
|
t.Error("wrong file")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExclsion(t *testing.T) {
|
||||||
|
dir := createFileTree()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
|
w := watch{
|
||||||
|
config: config.Watcher{Path: dir, Exclude: []string{"thumb", "tiny"}},
|
||||||
|
uploader: upload.Uploader{},
|
||||||
|
lastCheck: time.Now(),
|
||||||
|
newLastCheck: time.Now(),
|
||||||
|
}
|
||||||
|
files := w.ProcessNewFiles()
|
||||||
|
if len(files) != 0 {
|
||||||
|
t.Errorf("was not zero files (%d): %v", len(files), files)
|
||||||
|
}
|
||||||
|
// create a new file that would not hit exclusion, and two that would
|
||||||
|
os.Create(fmt.Sprintf("%s%c%s", dir, os.PathSeparator, "b.gif"))
|
||||||
|
os.Create(fmt.Sprintf("%s%c%s", dir, os.PathSeparator, "b_thumb.gif"))
|
||||||
|
os.Create(fmt.Sprintf("%s%c%s", dir, os.PathSeparator, "tiny_b.jpg"))
|
||||||
|
files = w.ProcessNewFiles()
|
||||||
|
if len(files) != 1 {
|
||||||
|
t.Error("was not one new file")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCheckPath(t *testing.T) {
|
||||||
|
dir := createFileTree()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
w := watch{
|
||||||
|
config: config.Watcher{Path: dir},
|
||||||
|
uploader: upload.Uploader{},
|
||||||
|
lastCheck: time.Now(),
|
||||||
|
newLastCheck: time.Now(),
|
||||||
|
}
|
||||||
|
if !w.checkPath() {
|
||||||
|
t.Error("checkPath failed?")
|
||||||
|
}
|
||||||
|
os.RemoveAll(dir)
|
||||||
|
if w.checkPath() {
|
||||||
|
t.Error("checkPath succeeded when shouldn't?")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createFileTree() string {
|
||||||
|
dir, err := ioutil.TempDir("", "dau-test")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
os.Create(fmt.Sprintf("%s%c%s", dir, os.PathSeparator, "a.gif"))
|
||||||
|
os.Create(fmt.Sprintf("%s%c%s", dir, os.PathSeparator, "a.jpg"))
|
||||||
|
os.Create(fmt.Sprintf("%s%c%s", dir, os.PathSeparator, "a.png"))
|
||||||
|
|
||||||
|
return dir
|
||||||
|
}
|
@ -18,7 +18,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type WebService struct {
|
type WebService struct {
|
||||||
Config config.ConfigService
|
Config *config.ConfigService
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:embed data
|
//go:embed data
|
||||||
@ -129,7 +129,7 @@ func (ws *WebService) handleConfig(w http.ResponseWriter, r *http.Request) {
|
|||||||
w.Write(j)
|
w.Write(j)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ws.Config.Config = newConfig
|
ws.Config.Config = &newConfig
|
||||||
err = ws.Config.Save()
|
err = ws.Config.Save()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(400)
|
w.WriteHeader(400)
|
||||||
@ -138,6 +138,11 @@ func (ws *WebService) handleConfig(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// config has changed, so tell the world
|
||||||
|
if ws.Config.Changed != nil {
|
||||||
|
ws.Config.Changed <- true
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
b, _ := json.Marshal(ws.Config.Config)
|
b, _ := json.Marshal(ws.Config.Config)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user