package main import ( "embed" "errors" "fmt" "os" "sync" "github.com/pelletier/go-toml/v2" ) const CONFIG_DIR = "./data" //go:embed sample_configs/* var sampleConfig embed.FS type Config struct { Web struct { Bind string `toml:"bind"` Port int `toml:"port"` } `toml:"web"` Jack struct { Enabled bool `toml:"enabled"` ClientName string `toml:"client_name"` } `toml:"jack"` } var config Config var shouldSaveConfigsMutex = new(sync.Mutex) var shouldSaveConfigs = map[string]bool{ "ports": false, } // Copy default config if `{name}.toml` file does not exist func createDefaultConfig(name string) { dest_path := fmt.Sprintf("%s/%s.toml", CONFIG_DIR, name) source_path := fmt.Sprintf("sample_configs/%s.toml", name) if _, err := os.Stat(CONFIG_DIR); errors.Is(err, os.ErrNotExist) { os.MkdirAll(CONFIG_DIR, 0744) } if _, err := os.Stat(dest_path); errors.Is(err, os.ErrNotExist) { content, err := sampleConfig.ReadFile(source_path) if err != nil { fmt.Printf("Warning! Default config for `%s` does not exist!\n", name) return } os.WriteFile(dest_path, content, 0644) } } // Load config from `.toml` file into a struct func loadConfig(name string, dest interface{}) { createDefaultConfig(name) file, err := os.ReadFile(fmt.Sprintf("%s/%s.toml", CONFIG_DIR, name)) if err != nil { fmt.Println(err) os.Exit(1) } err = toml.Unmarshal(file, dest) if err != nil { fmt.Println(err) os.Exit(1) } } // Mark a config file as changed, so it gets saved to disk later func markConfig(name string) { shouldSaveConfigsMutex.Lock() shouldSaveConfigs[name] = true shouldSaveConfigsMutex.Unlock() } // Save struct as a `.toml` file func saveConfig(name string, dest interface{}) { bin, err := toml.Marshal(dest) if err != nil { fmt.Println(err) } err = os.WriteFile(fmt.Sprintf("%s/%s.toml", CONFIG_DIR, name), bin, 0644) if err != nil { fmt.Println(err) } } func saveConfigIfMarked(name string, dest interface{}) { shouldSaveConfigsMutex.Lock() if shouldSaveConfigs[name] { shouldSaveConfigs[name] = false saveConfig(name, dest) } shouldSaveConfigsMutex.Unlock() }