diff --git a/engine/viewmodel.go b/engine/viewmodel.go index bb70cfb..368f6fa 100644 --- a/engine/viewmodel.go +++ b/engine/viewmodel.go @@ -3,7 +3,6 @@ package engine import ( "encoding/json" "fmt" - "io/ioutil" "log" "o2/client" "o2/games" @@ -45,6 +44,7 @@ type ViewModel struct { serverViewModel *ServerViewModel config Config + configName string } type Config struct { @@ -112,6 +112,25 @@ func (vm *ViewModel) NotifyView(view string, model interface{}) { vn.NotifyView(view, viewModel) } +func (vm *ViewModel) GetConfigName() string { + return vm.configName +} + +func (vm *ViewModel) SetConfigName(configName string) { + vm.configName = configName +} + +func (vm *ViewModel) getConfigFilePath(dir string) string { + path := "config.json" + configName := vm.GetConfigName() + + if configName != "" { + path = "config-" + configName + ".json" + } + + return filepath.Join(dir, path) +} + // initializes all view models: func (vm *ViewModel) Init() { for _, model := range vm.viewModels { @@ -141,9 +160,19 @@ func (vm *ViewModel) LoadConfiguration() bool { log.Printf("viewmodel: loadConfiguration: could not find configuration directory: %v\n", err) return false } - path := filepath.Join(dir, "config.json") + defaultPath := filepath.Join(dir, "config.json") + path := vm.getConfigFilePath(dir) - b, err := ioutil.ReadFile(path) + var b []byte + err = nil + + b, err = os.ReadFile(path) + if path != defaultPath && err != nil { + // fall back to default config location: + log.Printf("viewmodel: loadConfiguration: could not find read custom configuration file: %v\n", err) + b, err = os.ReadFile(defaultPath) + } + if err != nil { log.Printf("viewmodel: loadConfiguration: could not find read configuration file: %v\n", err) return false @@ -215,10 +244,10 @@ func (vm *ViewModel) SaveConfiguration() bool { if err != nil { log.Printf("viewmodel: saveConfiguration: could not make directories along the path '%s': %v\n", dir, err) } + + path := vm.getConfigFilePath(dir) - path := filepath.Join(dir, "config.json") - - err = ioutil.WriteFile(path, b, 0644) + err = os.WriteFile(path, b, 0644) if err != nil { log.Printf("viewmodel: saveConfiguration: could not write configuration file '%s': %v\n", path, err) return false diff --git a/webui/o2/main.go b/webui/o2/main.go index 920a309..be0c910 100644 --- a/webui/o2/main.go +++ b/webui/o2/main.go @@ -10,6 +10,7 @@ import ( "o2/util/env" "os" "path/filepath" + "regexp" "strconv" "strings" "time" @@ -30,6 +31,8 @@ import ( _ "o2/games/alttp" ) +const defaultPort = 27637 + // build variables set via ldflags by goreleaser: var ( version string = "v0.0.0" @@ -43,6 +46,7 @@ var ( listenPort int // port number to listen on for webserver browserHost string // hostname to send as part of URL to browser to connect to webserver browserUrl string // full URL that is sent to browser (composed of browserHost:listenPort) + configName string // save configuration data to a unique location logPath string ) @@ -75,6 +79,25 @@ type O2ViewModel struct { Version string `json:"version"` } +func sanitizeConfigName(s string) string { + var invalidChars = regexp.MustCompile(`[^\p{L}\p{N}_-]+`) + result := invalidChars.ReplaceAllString(s, "_") + result = strings.Trim(result, "._-") + return result +} + +func resolveConfigName(configName string, listenPort int) string { + if configName != "" { + return sanitizeConfigName(configName) + } + + if listenPort != defaultPort { + return strconv.Itoa(listenPort) + } + + return "" +} + func main() { defer func() { if err := recover(); err != nil { @@ -87,22 +110,26 @@ func main() { // Parse env vars: listenHost = env.GetOrDefault("O2_WEB_LISTEN_HOST", "0.0.0.0") - listenPort, err = strconv.Atoi(env.GetOrDefault("O2_WEB_LISTEN_PORT", "27637")) + listenPort, err = strconv.Atoi(env.GetOrDefault("O2_WEB_LISTEN_PORT", strconv.Itoa(defaultPort))) if err != nil { - listenPort = 27637 + listenPort = defaultPort } if listenPort <= 0 { - listenPort = 27637 + listenPort = defaultPort } listenAddr := net.JoinHostPort(listenHost, strconv.Itoa(listenPort)) browserHost = env.GetOrDefault("O2_WEB_BROWSER_HOST", "127.0.0.1") browserUrl = fmt.Sprintf("http://%s:%d/", browserHost, listenPort) + configName = resolveConfigName(env.GetOrDefault("O2_CONFIG_NAME", ""), listenPort); + // construct our viewModel: viewModel := engine.NewViewModel() viewModel.SetViewModel("o2", &O2ViewModel{Version: version}) + viewModel.SetConfigName(configName) + // construct the web server: webServer := NewWebServer(listenAddr)