Restructures configuration for birthdays and adds pictures directory

This commit is contained in:
Miguel de la Cruz 2023-07-10 21:08:05 +02:00
parent c7399eb9da
commit ec2cdfdeaa
9 changed files with 55 additions and 31 deletions

3
.gitignore vendored
View file

@ -1,2 +1,3 @@
dist dist
config.yml config.yml
pics

View file

@ -1,6 +1,8 @@
--- ---
birthday_file: birthdays.csv birthdays:
birthday_template: ./birthday_message.tmpl file: birthdays.csv
template: ./birthday_message.tmpl
pictures: ./pics
logger: logger:
level: debug level: debug

View file

@ -10,22 +10,21 @@ import (
) )
var ( var (
ErrConfigBirthdayFileEmpty = errors.New("birthday file cannot be empty") 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") 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") ErrTelegramNotificationsConfigEmptyBotToken = errors.New("bot token cannot be empty")
ErrTelegramNotificationsConfigEmptyChannelID = errors.New("channel ID cannot be empty") ErrTelegramNotificationsConfigEmptyChannelID = errors.New("channel ID cannot be empty")
) )
type Config struct { type Config struct {
BirthdayFile string `yaml:"birthday_file"` Birthdays *BirthdaysConfig `yaml:"birthdays"`
BirthdayTemplate string `yaml:"birthday_template"`
Logger *LoggerConfig `yaml:"logger"` Logger *LoggerConfig `yaml:"logger"`
TelegramNotifications *TelegramNotificationsConfig `yaml:"telegram_notifications"` TelegramNotifications *TelegramNotificationsConfig `yaml:"telegram_notifications"`
} }
func (c *Config) IsValid() error { func (c *Config) IsValid() error {
if c.BirthdayFile == "" { if err := c.Birthdays.IsValid(); err != nil {
return ErrConfigBirthdayFileEmpty return fmt.Errorf("invalid birthdays config: %w", err)
} }
if err := c.Logger.IsValid(); err != nil { if err := c.Logger.IsValid(); err != nil {
@ -42,6 +41,12 @@ func (c *Config) IsValid() error {
} }
func (c *Config) SetDefaults() { func (c *Config) SetDefaults() {
if c.Birthdays == nil {
c.Birthdays = &BirthdaysConfig{}
}
c.Birthdays.SetDefaults()
if c.Logger == nil { if c.Logger == nil {
c.Logger = &LoggerConfig{} c.Logger = &LoggerConfig{}
} }
@ -53,6 +58,22 @@ func (c *Config) SetDefaults() {
} }
} }
type BirthdaysConfig struct {
File string `yaml:"file"`
Template string `yaml:"template"`
Picures string `yaml:"pictures"`
}
func (bc *BirthdaysConfig) IsValid() error {
if bc.File == "" {
return ErrBirthdaysConfigFileEmpty
}
return nil
}
func (bc *BirthdaysConfig) SetDefaults() {}
type LoggerConfig struct { type LoggerConfig struct {
Level string `yaml:"level"` Level string `yaml:"level"`
ReportCaller bool `yaml:"report_caller"` ReportCaller bool `yaml:"report_caller"`

View file

@ -15,13 +15,13 @@ func TestReadConfig(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
defer os.Remove(f.Name()) defer os.Remove(f.Name())
_, werr := io.WriteString(f, "---\nbirthday_file: birthday.csv") _, werr := io.WriteString(f, "---\nbirthdays:\n file: birthday.csv")
require.NoError(t, werr) require.NoError(t, werr)
require.NoError(t, f.Close()) require.NoError(t, f.Close())
config, err := ReadConfig(f.Name()) config, err := ReadConfig(f.Name())
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, "birthday.csv", config.BirthdayFile) require.Equal(t, "birthday.csv", config.Birthdays.File)
}) })
t.Run("should fail if the file doesn't exist", func(t *testing.T) { t.Run("should fail if the file doesn't exist", func(t *testing.T) {

View file

@ -13,12 +13,12 @@ import (
type TelegramNotificationService struct { type TelegramNotificationService struct {
logger *log.Logger logger *log.Logger
config *model.TelegramNotificationsConfig config *model.Config
bot *tgbotapi.BotAPI bot *tgbotapi.BotAPI
} }
func NewTelegramNotificationService(logger *log.Logger, config *model.TelegramNotificationsConfig) (*TelegramNotificationService, error) { func NewTelegramNotificationService(logger *log.Logger, config *model.Config) (*TelegramNotificationService, error) {
bot, err := tgbotapi.NewBotAPI(config.BotToken) bot, err := tgbotapi.NewBotAPI(config.TelegramNotifications.BotToken)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot create bot: %w", err) return nil, fmt.Errorf("cannot create bot: %w", err)
} }

View file

@ -28,7 +28,7 @@ func testConfig(t *testing.T) *model.Config {
require.NoError(t, f.Close()) require.NoError(t, f.Close())
require.NoError(t, os.Remove(f.Name())) require.NoError(t, os.Remove(f.Name()))
return &model.Config{BirthdayFile: f.Name()} return &model.Config{Birthdays: &model.BirthdaysConfig{File: f.Name()}}
} }
func SetupTestHelper(t *testing.T) *TestHelper { func SetupTestHelper(t *testing.T) *TestHelper {

View file

@ -10,7 +10,7 @@ type Option func(*Server) *Server
func WithConfig(config *model.Config) Option { func WithConfig(config *model.Config) Option {
return func(server *Server) *Server { return func(server *Server) *Server {
server.config = config server.Config = config
return server return server
} }
} }

View file

@ -19,18 +19,18 @@ var (
type Server struct { type Server struct {
Logger *log.Logger Logger *log.Logger
config *model.Config Config *model.Config
workers []Worker workers []Worker
birthdays []*model.Birthday birthdays []*model.Birthday
notificationServices []notification.NotificationService notificationServices []notification.NotificationService
tmpl *template.Template tmpl *template.Template
} }
func createNotificationServices(logger *log.Logger, config *model.Config) ([]notification.NotificationService, error) { func (s *Server) createNotificationServices() ([]notification.NotificationService, error) {
notificationServices := []notification.NotificationService{} notificationServices := []notification.NotificationService{}
if config.TelegramNotifications != nil { if s.Config.TelegramNotifications != nil {
telegramNotificationService, err := notification.NewTelegramNotificationService(logger, config.TelegramNotifications) telegramNotificationService, err := notification.NewTelegramNotificationService(s.Logger, s.Config)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot create telegram notification service: %w", err) return nil, fmt.Errorf("cannot create telegram notification service: %w", err)
} }
@ -54,18 +54,18 @@ func New(options ...Option) (*Server, error) {
return nil, ErrNoLogger return nil, ErrNoLogger
} }
if srv.config == nil { if srv.Config == nil {
return nil, ErrNoConfig return nil, ErrNoConfig
} }
if len(srv.birthdays) == 0 { if len(srv.birthdays) == 0 {
srv.Logger.Debug("parsing CSV file", "birthdayFile", srv.config.BirthdayFile) srv.Logger.Debug("parsing CSV file", "birthdayFile", srv.Config.Birthdays.File)
var err error var err error
srv.birthdays, err = parser.ParseCSV(srv.config.BirthdayFile) srv.birthdays, err = parser.ParseCSV(srv.Config.Birthdays.File)
if err != nil { if err != nil {
srv.Logger.Error("cannot parse CSV file", "birthdayFile", srv.config.BirthdayFile, "error", err) srv.Logger.Error("cannot parse CSV file", "birthdayFile", srv.Config.Birthdays.File, "error", err)
return nil, fmt.Errorf("cannot parse CSV file %s: %w", srv.config.BirthdayFile, err) return nil, fmt.Errorf("cannot parse CSV file %s: %w", srv.Config.Birthdays.File, err)
} }
} }
@ -73,7 +73,7 @@ func New(options ...Option) (*Server, error) {
srv.Logger.Debug("creating notification services from config") srv.Logger.Debug("creating notification services from config")
var err error var err error
srv.notificationServices, err = createNotificationServices(srv.Logger, srv.config) srv.notificationServices, err = srv.createNotificationServices()
if err != nil { if err != nil {
srv.Logger.Error("error creating notification services", "error", err) srv.Logger.Error("error creating notification services", "error", err)
return nil, err return nil, err
@ -86,13 +86,13 @@ func New(options ...Option) (*Server, error) {
srv.workers = []Worker{NewSimpleWorker(srv)} srv.workers = []Worker{NewSimpleWorker(srv)}
} }
if srv.config.BirthdayTemplate != "" { if srv.Config.Birthdays.Template != "" {
srv.Logger.Debug("parsing birthday template", "file", srv.config.BirthdayTemplate) srv.Logger.Debug("parsing birthday template", "file", srv.Config.Birthdays.Template)
var err error var err error
srv.tmpl, err = template.ParseFiles(srv.config.BirthdayTemplate) srv.tmpl, err = template.ParseFiles(srv.Config.Birthdays.Template)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot parse template file %q: %w", srv.config.BirthdayTemplate, err) return nil, fmt.Errorf("cannot parse template file %q: %w", srv.Config.Birthdays.Template, err)
} }
} }

View file

@ -14,7 +14,7 @@ func TestNotify(t *testing.T) {
birthday := th.srv.birthdays[0] birthday := th.srv.birthdays[0]
th.mockNotificationService. th.mockNotificationService.
EXPECT(). EXPECT().
Notify(birthday). Notify(birthday, nil).
Return(nil). Return(nil).
Times(1) Times(1)
@ -27,7 +27,7 @@ func TestNotify(t *testing.T) {
birthday := th.srv.birthdays[0] birthday := th.srv.birthdays[0]
th.mockNotificationService. th.mockNotificationService.
EXPECT(). EXPECT().
Notify(birthday). Notify(birthday, nil).
Return(mockErr). Return(mockErr).
Times(1) Times(1)