package configuration import ( "encoding/json" "errors" "fmt" "os" "path/filepath" "strings" ) var errCfg = errors.New("configuration") // Config is a configuration controlling structure. type Config struct { RSS *RSS `json:"rss"` Outputs *Outputs `json:"outputs"` } // New creates new configuration controller. func New(path string) (*Config, error) { cfg := &Config{} // Get configuration file real path. userHomeDir, err := os.UserHomeDir() if err != nil { return nil, fmt.Errorf("%w: parse configuration file: get real path: get user home dir: %w", errCfg, err) } path = strings.Replace(path, "~", userHomeDir, 1) absPath, err := filepath.Abs(path) if err != nil { return nil, fmt.Errorf("%w: parse configuration file: get real path: get absolute path: %w", errCfg, err) } cfgFileData, err := os.ReadFile(absPath) if err != nil { return nil, fmt.Errorf("%w: parse configuration file: read file: %w", errCfg, err) } if err := json.Unmarshal(cfgFileData, cfg); err != nil { return nil, fmt.Errorf("%w: parse configuration file: %w", errCfg, err) } // Validate configuration. if err := cfg.Validate(); err != nil { return nil, fmt.Errorf("%w: %w", errCfg, err) } return cfg, nil } // Validate validates app configuration. func (c *Config) Validate() error { if err := c.RSS.Validate(); err != nil { return fmt.Errorf("validate configuration: %w", err) } return nil }