package settings import ( "encoding/json" "log" "os" "path" "time" "gopkg.in/fsnotify.v1" ) const SettingsFile = "settings.json" var SettingsDir string = "./SETTINGS" 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) } } }() } }