package model import ( "errors" "fmt" "io/ioutil" "strings" "gopkg.in/yaml.v3" ) var ( ErrConfigBirthdayFileEmpty = errors.New("birthday file cannot be empty") ErrLoggerConfigBadLevel = errors.New("logger level needs to be one of debug, info, warn, error, fatal or left empty") ErrTelegramNotificationsConfigEmptyBotToken = errors.New("bot token cannot be empty") ErrTelegramNotificationsConfigEmptyChannelID = errors.New("channel ID cannot be empty") ) type Config struct { BirthdayFile string `yaml:"birthday_file"` BirthdayTemplate string `yaml:"birthday_template"` Logger *LoggerConfig `yaml:"logger"` TelegramNotifications *TelegramNotificationsConfig `yaml:"telegram_notifications"` } func (c *Config) IsValid() error { if c.BirthdayFile == "" { return ErrConfigBirthdayFileEmpty } if err := c.Logger.IsValid(); err != nil { return fmt.Errorf("invalid logger config: %w", err) } if c.TelegramNotifications != nil { if err := c.TelegramNotifications.IsValid(); err != nil { return fmt.Errorf("invalid telegram notifications config: %w", err) } } return nil } func (c *Config) SetDefaults() { if c.Logger == nil { c.Logger = &LoggerConfig{} } c.Logger.SetDefaults() if c.TelegramNotifications != nil { c.TelegramNotifications.SetDefaults() } } type LoggerConfig struct { Level string `yaml:"level"` ReportCaller bool `yaml:"report_caller"` } func (lc *LoggerConfig) SetDefaults() {} func (lc *LoggerConfig) IsValid() error { level := strings.TrimSpace(strings.ToLower(lc.Level)) found := false for _, ll := range []string{"debug", "info", "warn", "error", "fatal", ""} { if level == ll { found = true break } } if !found { return ErrLoggerConfigBadLevel } return nil } type TelegramNotificationsConfig struct { BotToken string `yaml:"bot_token"` ChannelID string `yaml:"channel_id"` } func (tnc *TelegramNotificationsConfig) SetDefaults() {} func (tnc *TelegramNotificationsConfig) IsValid() error { if tnc.BotToken == "" { return ErrTelegramNotificationsConfigEmptyBotToken } if tnc.ChannelID == "" { return ErrTelegramNotificationsConfigEmptyChannelID } return nil } func ReadConfig(path string) (*Config, error) { fileBytes, err := ioutil.ReadFile(path) if err != nil { return nil, err } var config *Config if err := yaml.Unmarshal(fileBytes, &config); err != nil { return nil, err } config.SetDefaults() return config, nil }