grimoire/config.go

112 lines
2.5 KiB
Go

package main
import (
"os"
"path/filepath"
"runtime"
"strings"
)
type Config struct {
Streams map[string]string // stream in the form stream::name=url
DataDir string // location of templates/ and static/
Name string // name of this instance
ListenAddress string // address the webserver listens on
}
func GetConfigLocation() string {
home := os.Getenv("HOME")
appdata := os.Getenv("APPDATA")
switch runtime.GOOS {
case "windows":
return filepath.Join(appdata, "grimoire")
case "darwin":
return filepath.Join(home, "Library", "Application Support", "grimoire")
case "plan9":
return filepath.Join(home, "lib", "grimoire")
default:
return filepath.Join(home, ".config", "grimoire")
}
}
func ensureConfigLocationExists() {
fileInfo, err := os.Stat(GetConfigLocation())
if os.IsNotExist(err) {
os.MkdirAll(GetConfigLocation(), os.ModePerm)
} else if !fileInfo.IsDir() {
panic("Config location is not a directory!")
}
}
func ReadConfig() *Config {
ensureConfigLocationExists()
return parseConfig(filepath.Join(GetConfigLocation(), "grimoire.conf"))
}
func (self *Config) Write() error {
ensureConfigLocationExists()
return writeConfig(self, filepath.Join(GetConfigLocation(), "grimoire.conf"))
}
func writeConfig(cfg *Config, configFile string) error {
f, err := os.Create(configFile)
if err != nil {
return err
}
defer f.Close()
f.WriteString("listenAddress=" + cfg.ListenAddress + "\n")
f.WriteString("dataDir=" + cfg.DataDir + "\n")
f.WriteString("name=" + cfg.Name + "\n")
for k, v := range cfg.Streams {
f.WriteString("stream::" + k + "=" + v)
}
return nil
}
func parseConfig(configFile string) *Config {
f, err := os.ReadFile(configFile)
cfg := &Config{}
cfg.Streams = make(map[string]string)
if err != nil {
return cfg
}
fileData := string(f[:])
lines := strings.Split(fileData, "\n")
for _, l := range lines {
if len(l) == 0 {
continue
}
if !strings.Contains(l, "=") {
panic("Malformed config not in INI format")
}
kvp := strings.Split(l, "=")
k := strings.TrimSpace(kvp[0])
v := strings.TrimSpace(kvp[1])
switch k {
case "listenAddress":
cfg.ListenAddress = v
case "dataDir":
cfg.DataDir = v
case "name":
cfg.Name = v
default:
if strings.HasPrefix(k, "stream::") {
stream := strings.Split(k, "stream::")[1]
if len(stream) == 0 {
panic("stream in config has no name!")
}
cfg.Streams[stream] = v
} else {
panic("Unrecognized config option: " + k)
}
}
}
return cfg
}