package config import ( "encoding/json" "errors" "fmt" "io/fs" "os" "strconv" "github.com/sirupsen/logrus" ) type TelegramConfig struct { ChannelID int64 `json:"channel_id"` Token string `json:"token"` } type LogConfig struct { Level logrus.Level } type jsonLogConfig struct { Level string `json:"level"` } type ListenerConfig struct { SockPath string `json:"sock_path"` } type Config struct { Telegram TelegramConfig Log LogConfig Listener ListenerConfig } type jsonConfig struct { Telegram TelegramConfig `json:"telegram"` Log jsonLogConfig `json:"log"` Listener ListenerConfig `json:"listener"` } func parseLevel(lvlStr string) logrus.Level { for _, lvl := range logrus.AllLevels { if lvl.String() == lvlStr { return lvl } } return logrus.InfoLevel } var defaultConfig Config = Config{ Telegram: TelegramConfig{ ChannelID: 0, Token: "", }, Log: LogConfig{ Level: logrus.InfoLevel, }, Listener: ListenerConfig{ SockPath: "input/notifier.sock", }, } func checkOverride(conf *Config) { if val, ok := os.LookupEnv("LOG_LEVEL"); ok { conf.Log.Level = parseLevel(val) } if val, ok := os.LookupEnv("SOCK_PATH"); ok { conf.Listener.SockPath = val } if val, ok := os.LookupEnv("TELEGRAM_CHANNEL_ID"); ok { if intVal, err := strconv.Atoi(val); err == nil { conf.Telegram.ChannelID = int64(intVal) } } if val, ok := os.LookupEnv("TELEGRAM_TOKEN"); ok { conf.Telegram.Token = val } } func New(filepath string) (*Config, error) { content, err := os.ReadFile(filepath) if err != nil { if errors.Is(err, fs.ErrNotExist) { conf := defaultConfig checkOverride(&conf) return &conf, nil } return nil, fmt.Errorf("failed to read config file %q: %w", filepath, err) } var jsonConf jsonConfig if err := json.Unmarshal(content, &jsonConf); err != nil { return nil, fmt.Errorf("failed to parse config file: %w", err) } conf := &Config{ Telegram: jsonConf.Telegram, Log: LogConfig{ Level: parseLevel(jsonConf.Log.Level), }, Listener: jsonConf.Listener, } checkOverride(conf) return conf, nil }