birthdaybot/model/config.go
2023-07-11 16:43:20 +02:00

157 lines
3.3 KiB
Go

package model
import (
"errors"
"fmt"
"os"
"strings"
"gopkg.in/yaml.v3"
)
var (
ErrBirthdaysConfigFileEmpty = 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 {
Birthdays *BirthdaysConfig `yaml:"birthdays"`
Logger *LoggerConfig `yaml:"logger"`
Web *WebConfig `yaml:"web"`
TelegramNotifications *TelegramNotificationsConfig `yaml:"telegram_notifications"`
}
func (c *Config) IsValid() error {
if err := c.Birthdays.IsValid(); err != nil {
return fmt.Errorf("invalid birthdays config: %w", err)
}
if err := c.Logger.IsValid(); err != nil {
return fmt.Errorf("invalid logger config: %w", err)
}
if err := c.Web.IsValid(); err != nil {
return fmt.Errorf("invalid web 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.Birthdays == nil {
c.Birthdays = &BirthdaysConfig{}
}
c.Birthdays.SetDefaults()
if c.Logger == nil {
c.Logger = &LoggerConfig{}
}
c.Logger.SetDefaults()
if c.Web == nil {
c.Web = &WebConfig{}
}
c.Web.SetDefaults()
if c.TelegramNotifications != nil {
c.TelegramNotifications.SetDefaults()
}
}
type BirthdaysConfig struct {
File string `yaml:"file"`
Template string `yaml:"template"`
Pictures string `yaml:"pictures"`
}
func (bc *BirthdaysConfig) IsValid() error {
if bc.File == "" {
return ErrBirthdaysConfigFileEmpty
}
return nil
}
func (bc *BirthdaysConfig) 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 WebConfig struct {
Enabled bool `yaml:"enabled"`
Port int `yaml:"port"`
}
func (wc *WebConfig) SetDefaults() {}
func (wc *WebConfig) IsValid() error {
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 := os.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
}