package main import ( "encoding/json" "fmt" "os" "strings" ) // Config represents the blocklist configuration file. type Config struct { // ListName is the name for the RouterOS address list (e.g. "CountryIPBlocks"). ListName string `json:"list_name"` // Provider specifies which GeoIP data source to use. // Supported values: "ipverse" (default), "ipdeny" Provider string `json:"provider"` // Countries is a list of ISO 3166-1 alpha-2 country codes (lowercase). Countries []string `json:"countries"` } // LoadConfig reads and validates a blocklist configuration file. func LoadConfig(filename string) (*Config, error) { b, err := os.ReadFile(filename) if err != nil { return nil, fmt.Errorf("failed to read config file %q: %v", filename, err) } var cfg Config if err := json.Unmarshal(b, &cfg); err != nil { return nil, fmt.Errorf("failed to parse config file %q: %v", filename, err) } // Validate if cfg.ListName == "" { return nil, fmt.Errorf("config: list_name is required") } if cfg.Provider == "" { cfg.Provider = "ipverse" // default provider } cfg.Provider = strings.ToLower(cfg.Provider) if len(cfg.Countries) == 0 { return nil, fmt.Errorf("config: at least one country code is required") } // Normalize country codes to lowercase for i := range cfg.Countries { cfg.Countries[i] = strings.ToLower(strings.TrimSpace(cfg.Countries[i])) } return &cfg, nil }