server/settings/settings.go

107 lines
2.4 KiB
Go

package settings
import (
"encoding/json"
"log"
"os"
"path"
"time"
"gopkg.in/fsnotify.v1"
)
const SettingsFile = "settings.json"
type FICSettings struct {
Title string `json:"title"`
Authors string `json:"authors"`
Start time.Time `json:"start"`
End time.Time `json:"end"`
Generation time.Time `json:"generation"`
FirstBlood float64 `json:"firstBlood"`
SubmissionCostBase float64 `json:"submissionCostBase"`
AllowRegistration bool `json:"allowRegistration"`
DenyNameChange bool `json:"denyNameChange"`
EnableResolutionRoute bool `json:"enableResolutionRoute"`
PartialValidation bool `json:"partialValidation"`
EnableExerciceDepend bool `json:"enableExerciceDepend"`
}
func ExistsSettings(settingsPath string) bool {
_, err := os.Stat(settingsPath)
return !os.IsNotExist(err)
}
func ReadSettings(path string) (FICSettings, error) {
var s FICSettings
if fd, err := os.Open(path); err != nil {
return s, err
} else {
defer fd.Close()
jdec := json.NewDecoder(fd)
if err := jdec.Decode(&s); err != nil {
return s, err
}
return s, nil
}
}
func SaveSettings(path string, s FICSettings) error {
if fd, err := os.Create(path); err != nil {
return err
} else {
defer fd.Close()
jenc := json.NewEncoder(fd)
if err := jenc.Encode(s); err != nil {
return err
}
return nil
}
}
func LoadAndWatchSettings(settingsPath string, reload func (FICSettings)) {
// First load of configuration if it exists
if _, err := os.Stat(settingsPath); !os.IsNotExist(err) {
if config, err := ReadSettings(settingsPath); err != nil {
log.Println("ERROR: Unable to read challenge settings:", err)
} else {
reload(config)
}
}
// Watch the configuration file
if watcher, err := fsnotify.NewWatcher(); err != nil {
log.Fatal(err)
} else {
if err := watcher.Add(path.Dir(settingsPath)); err != nil {
log.Fatal("Unable to watch: ", path.Dir(settingsPath), ": ", err)
}
go func() {
defer watcher.Close()
for {
select {
case ev := <-watcher.Events:
if path.Base(ev.Name) == SettingsFile && ev.Op & fsnotify.Write == fsnotify.Write {
log.Println("Settings file changes, reloading it!")
if config, err := ReadSettings(settingsPath); err != nil {
log.Println("ERROR: Unable to read challenge settings:", err)
} else {
reload(config)
}
}
case err := <-watcher.Errors:
log.Println("watcher error:", err)
}
}
}()
}
}