package main
import (
"fmt"
"reflect"
"text/template"
"github.com/BurntSushi/toml"
)
type validator interface {
validate() error
}
type EmailConfig struct {
SubjectTemplate *template.Template `toml:"-"`
SubjectTemplateStr string `toml:"subject_template"`
BodyTemplate *template.Template `toml:"-"`
BodyTemplateStr string `toml:"body_template"`
EmailTo string `toml:"to"`
EmailFrom string `toml:"from"`
Username string `toml:"username"`
Password string `toml:"password"`
Server string `toml:"server"`
StartTLS bool `toml:"starttls"`
}
func (c *EmailConfig) validate() error {
for k, v := range map[string]string{
"subject template": c.SubjectTemplateStr,
"body template": c.BodyTemplateStr,
"\"to\" email": c.EmailTo,
"\"from\" email": c.EmailFrom,
"username": c.Username,
"password": c.Password,
"server": c.Server,
} {
if v == "" {
return fmt.Errorf("you must provide a valid %s", k)
}
}
// parse the templates
subjTmpl, err := template.New("subject_template").Parse(c.SubjectTemplateStr)
if err != nil {
return err
}
c.SubjectTemplate = subjTmpl
bodyTmpl, err := template.New("body_template").Parse(c.BodyTemplateStr)
if err != nil {
return err
}
c.BodyTemplate = bodyTmpl
return nil
}
type GotifyConfig struct {
TitleTemplate *template.Template `toml:"-"`
TitleTemplateStr string `toml:"title_template"`
MessageTemplate *template.Template `toml:"-"`
MessageTemplateStr string `toml:"message_template"`
Server string `toml:"server"`
Token string `toml:"token"`
Priority int `toml:"priority"`
}
func (c *GotifyConfig) validate() error {
for k, v := range map[string]string{
"title template": c.TitleTemplateStr,
"message template": c.MessageTemplateStr,
"server": c.Server,
"token": c.Token,
} {
if v == "" {
return fmt.Errorf("you must provide a valid %s", k)
}
}
// parse the templates
titleTmpl, err := template.New("title_template").Parse(c.TitleTemplateStr)
if err != nil {
return err
}
c.TitleTemplate = titleTmpl
messageTmpl, err := template.New("message_template").Parse(c.MessageTemplateStr)
if err != nil {
return err
}
c.MessageTemplate = messageTmpl
return nil
}
type WebhookConfig struct {
Template *template.Template `toml:"-"`
TemplateStr string `toml:"template"`
Endpoint string `toml:"endpoint"`
}
func (c *WebhookConfig) validate() error {
for k, v := range map[string]string{
"template": c.TemplateStr,
"endpoint": c.Endpoint,
} {
if v == "" {
return fmt.Errorf("you must provide a valid %s", k)
}
}
// parse the template
tmpl, err := template.New("webhook").Parse(c.TemplateStr)
if err != nil {
return err
}
c.Template = tmpl
return nil
}
type Config struct {
Server string `toml:"server"`
Username string `toml:"username"`
Password string `toml:"password"`
DbPath string `toml:"db_path"`
EmailConfig *EmailConfig `toml:"email"`
GotifyConfig *GotifyConfig `toml:"gotify"`
WebhookConfig *WebhookConfig `toml:"webhook"`
}
func LoadConfig(configPath string) (*Config, error) {
var c Config
if _, err := toml.DecodeFile(configPath, &c); err != nil {
return nil, err
}
if err := c.validate(); err != nil {
return nil, err
}
return &c, nil
}
func (c *Config) validate() error {
for k, v := range map[string]string{
"server url": c.Server,
"username": c.Username,
"password": c.Password,
"database path": c.DbPath,
} {
if v == "" {
return fmt.Errorf("you must provide a valid %s", k)
}
}
for k, v := range map[string]validator{
"email": c.EmailConfig,
"gotify": c.GotifyConfig,
"webhook": c.WebhookConfig,
} {
// interfaces + nil have an interesting interaction...
if !reflect.ValueOf(v).IsNil() {
if err := v.validate(); err != nil {
return fmt.Errorf("invalid %s config: %s", k, err)
}
}
}
return nil
}