⛳ 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}