113 lines
2.5 KiB
Go
113 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
|
||
|
}
|