⛳ alerts for any ctfd instance via ntfy
1package main 2 3import ( 4 "errors" 5 "fmt" 6 "os" 7 "strings" 8 9 "github.com/pelletier/go-toml/v2" 10) 11 12type CTFdConfig struct { 13 ApiBase string `toml:"api_base"` 14 ApiKey string `toml:"api_key"` 15} 16 17type NtfyConfig struct { 18 ApiBase string `toml:"api_base"` 19 AccessToken string `toml:"acess_token"` 20 Topic string `toml:"topic"` 21} 22 23type Config struct { 24 Debug bool `toml:"debug"` 25 CTFdConfig CTFdConfig `toml:"ctfd"` 26 NtfyConfig NtfyConfig `toml:"ntfy"` 27 MonitorInterval int `toml:"interval"` 28} 29 30var config *Config 31 32func loadConfig(path string) (*Config, error) { 33 data, err := os.ReadFile(path) 34 if err != nil { 35 return nil, err 36 } 37 38 var cfg Config 39 if err := toml.Unmarshal(data, &cfg); err != nil { 40 return nil, err 41 } 42 43 if cfg.CTFdConfig.ApiBase == "" { 44 return nil, errors.New("ctfd api_base URL cannot be empty") 45 } 46 47 if cfg.CTFdConfig.ApiKey == "" { 48 return nil, errors.New("ctfd api_key cannot be empty") 49 } 50 51 // Check API key format (should start with ctfd_ followed by 64 hex characters) 52 if len(cfg.CTFdConfig.ApiKey) != 69 || !strings.HasPrefix(cfg.CTFdConfig.ApiKey, "ctfd_") { 53 return nil, errors.New("ctfd api_key must be in the format ctfd_<64 hex characters> not " + cfg.CTFdConfig.ApiKey) 54 } 55 56 if cfg.NtfyConfig.ApiBase == "" { 57 return nil, errors.New("ntfy api_base URL cannot be empty") 58 } 59 60 if cfg.NtfyConfig.Topic == "" { 61 return nil, errors.New("ntfy topic cannot be empty") 62 } 63 64 if cfg.MonitorInterval == 0 { 65 cfg.MonitorInterval = 300 66 fmt.Println("you haven't set a monitor interval; setting to 300") 67 } 68 69 return &cfg, nil 70}