package main import ( "bufio" "log" "os" "strconv" "strings" "sync" "github.com/fsnotify/fsnotify" "gopkg.in/ini.v1" ) func initConfig() error { if _, err := os.Stat(configFilePath); os.IsNotExist(err) { return createConfig() } printInfo("Configuration file already exists.") config = loadConfig() return nil } func createConfig() error { reader := bufio.NewReader(os.Stdin) printMessage("Configuration file not found.") printMessage("Do you want to use default values? (yes/no): ") useDefaults, _ := reader.ReadString('\n') if strings.TrimSpace(useDefaults) != "yes" { printMessage("Enter port (default 5000): ") portStr, _ := reader.ReadString('\n') if portStr != "\n" { port, err := strconv.Atoi(strings.TrimSpace(portStr)) if err != nil { config.Port = 5000 } else { config.Port = port } } printMessage("Enter your domain address (default localhost): ") domain, _ := reader.ReadString('\n') if domain != "\n" { config.Domain = strings.TrimSpace(domain) } } else { config = defaultConfig } if config.AuthCode == "" { config.AuthCode = generateStrongRandomString(64) printMessage("Generated connection code: %s\n", config.AuthCode) } config.NodesEnabled = len(config.Peers) > 0 config.CrawlerEnabled = true config.WebsiteEnabled = true config.LogLevel = 1 saveConfig(config) return nil } func saveConfig(config Config) { cfg := ini.Empty() sec := cfg.Section("") sec.Key("Port").SetValue(strconv.Itoa(config.Port)) sec.Key("AuthCode").SetValue(config.AuthCode) sec.Key("PeerID").SetValue(config.PeerID) peers := strings.Join(config.Peers, ",") sec.Key("Peers").SetValue(peers) sec.Key("Domain").SetValue(config.Domain) sec.Key("NodesEnabled").SetValue(strconv.FormatBool(config.NodesEnabled)) sec.Key("CrawlerEnabled").SetValue(strconv.FormatBool(config.CrawlerEnabled)) sec.Key("WebsiteEnabled").SetValue(strconv.FormatBool(config.WebsiteEnabled)) sec.Key("LogLevel").SetValue(strconv.Itoa(config.LogLevel)) err := cfg.SaveTo(configFilePath) if err != nil { printErr("Error writing to config file: %v", err) } } func loadConfig() Config { cfg, err := ini.Load(configFilePath) if err != nil { printErr("Error opening config file: %v", err) } port, err := cfg.Section("").Key("Port").Int() if err != nil || port == 0 { port = 5000 // Default to 5000 if not set or error } peersStr := cfg.Section("").Key("Peers").String() var peers []string if peersStr != "" { peers = strings.Split(peersStr, ",") for i, peer := range peers { peers[i] = addProtocol(peer) } } domain := cfg.Section("").Key("Domain").String() if domain == "" { domain = "localhost" // Default to localhost if not set } nodesEnabled, err := cfg.Section("").Key("NodesEnabled").Bool() if err != nil { // If NodesEnabled is not found in config nodesEnabled = len(peers) > 0 // Enable nodes if peers are configured } crawlerEnabled, err := cfg.Section("").Key("CrawlerEnabled").Bool() if err != nil { // Default to true if not found crawlerEnabled = true } websiteEnabled, err := cfg.Section("").Key("WebsiteEnabled").Bool() if err != nil { // Default to true if not found websiteEnabled = true } logLevel, err := cfg.Section("").Key("LogLevel").Int() if err != nil || logLevel < 0 || logLevel > 4 { // Default to 1 if not found or out of range logLevel = 1 } config = Config{ Port: port, AuthCode: cfg.Section("").Key("AuthCode").String(), PeerID: cfg.Section("").Key("PeerID").String(), Peers: peers, Domain: domain, NodesEnabled: nodesEnabled, CrawlerEnabled: crawlerEnabled, WebsiteEnabled: websiteEnabled, LogLevel: logLevel, } return config } var configLock sync.RWMutex func startFileWatcher() { watcher, err := fsnotify.NewWatcher() if err != nil { printErr("%v", err) } go func() { defer watcher.Close() for { select { case event, ok := <-watcher.Events: if !ok { return } if event.Op&fsnotify.Write == fsnotify.Write { printInfo("Modified file: %v", event.Name) configLock.Lock() config = loadConfig() configLock.Unlock() } case err, ok := <-watcher.Errors: if !ok { return } printWarn("Error watching configuration file: %v", err) } } }() err = watcher.Add(configFilePath) if err != nil { log.Fatal(err) } }