⛳ 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 User string `toml:"user"`
26 CTFdConfig CTFdConfig `toml:"ctfd"`
27 NtfyConfig NtfyConfig `toml:"ntfy"`
28 MonitorInterval int `toml:"interval"`
29}
30
31var config *Config
32
33func loadConfig(path string) (*Config, error) {
34 data, err := os.ReadFile(path)
35 if err != nil {
36 return nil, err
37 }
38
39 var cfg Config
40 if err := toml.Unmarshal(data, &cfg); err != nil {
41 return nil, err
42 }
43
44 if cfg.CTFdConfig.ApiBase == "" {
45 return nil, errors.New("ctfd api_base URL cannot be empty")
46 }
47
48 if cfg.CTFdConfig.ApiKey == "" {
49 return nil, errors.New("ctfd api_key cannot be empty")
50 }
51
52 // Check API key format (should start with ctfd_ followed by 64 hex characters)
53 if len(cfg.CTFdConfig.ApiKey) != 69 || !strings.HasPrefix(cfg.CTFdConfig.ApiKey, "ctfd_") {
54 return nil, errors.New("ctfd api_key must be in the format ctfd_<64 hex characters> not " + cfg.CTFdConfig.ApiKey)
55 }
56
57 if cfg.NtfyConfig.ApiBase == "" {
58 return nil, errors.New("ntfy api_base URL cannot be empty")
59 }
60
61 if cfg.NtfyConfig.Topic == "" {
62 return nil, errors.New("ntfy topic cannot be empty")
63 }
64
65 if cfg.User == "" {
66 return nil, errors.New("user cannot be empty")
67 }
68
69 if cfg.MonitorInterval == 0 {
70 cfg.MonitorInterval = 300
71 fmt.Println("you haven't set a monitor interval; setting to 300")
72 }
73
74 return &cfg, nil
75}