+ slogger := mobius.NewLogger(logLevel, logFile)
+
+ // It's important for Windows compatibility to use path.Join and not filepath.Join for the config dir initialization.
+ // https://github.com/golang/go/issues/44305
+ if *init {
+ if _, err := os.Stat(path.Join(*configDir, "/config.yaml")); os.IsNotExist(err) {
+ if err := os.MkdirAll(*configDir, 0750); err != nil {
+ slogger.Error(fmt.Sprintf("error creating config dir: %s", err))
+ os.Exit(1)
+ }
+ if err := copyDir(path.Join("mobius", "config"), *configDir); err != nil {
+ slogger.Error(fmt.Sprintf("error copying config dir: %s", err))
+ os.Exit(1)
+ }
+ slogger.Info("Config dir initialized at " + *configDir)
+ } else {
+ slogger.Info("Existing config dir found. Skipping initialization.")
+ }
+ }
+
+ config, err := mobius.LoadConfig(path.Join(*configDir, "config.yaml"))
+ if err != nil {
+ slogger.Error(fmt.Sprintf("Error loading config: %v", err))
+ os.Exit(1)
+ }
+
+ srv, err := hotline.NewServer(
+ hotline.WithInterface(*netInterface),
+ hotline.WithLogger(slogger),
+ hotline.WithPort(*basePort),
+ hotline.WithConfig(*config),
+ )
+ if err != nil {
+ slogger.Error(fmt.Sprintf("Error starting server: %s", err))
+ os.Exit(1)
+ }
+
+ srv.MessageBoard, err = mobius.NewFlatNews(path.Join(*configDir, "MessageBoard.txt"))
+ if err != nil {
+ slogger.Error(fmt.Sprintf("Error loading message board: %v", err))
+ os.Exit(1)
+ }
+
+ srv.BanList, err = mobius.NewBanFile(path.Join(*configDir, "Banlist.yaml"))
+ if err != nil {
+ slogger.Error(fmt.Sprintf("Error loading ban list: %v", err))
+ os.Exit(1)
+ }
+
+ srv.ThreadedNewsMgr, err = mobius.NewThreadedNewsYAML(path.Join(*configDir, "ThreadedNews.yaml"))
+ if err != nil {
+ slogger.Error(fmt.Sprintf("Error loading news: %v", err))
+ os.Exit(1)
+ }
+
+ srv.AccountManager, err = mobius.NewYAMLAccountManager(filepath.Join(*configDir, "Users/"))
+ if err != nil {
+ slogger.Error(fmt.Sprintf("Error loading accounts: %v", err))
+ os.Exit(1)
+ }
+
+ srv.Agreement, err = mobius.NewAgreement(*configDir, "\r")
+ if err != nil {
+ slogger.Error(fmt.Sprintf("Error loading agreement: %v", err))
+ os.Exit(1)
+ }
+
+ bannerPath := filepath.Join(*configDir, config.BannerFile)
+ srv.Banner, err = os.ReadFile(bannerPath)
+ if err != nil {
+ slogger.Error(fmt.Sprintf("Error loading accounts: %v", err))
+ os.Exit(1)