diff --git a/go.mod b/go.mod index 1b34b35..b7e9b75 100644 --- a/go.mod +++ b/go.mod @@ -3,3 +3,5 @@ module git.xenrox.net/~xenrox/ntfy-alertmanager go 1.19 require git.xenrox.net/~xenrox/go-log v0.0.0-20221009121411-e93f4223b622 + +require golang.org/x/text v0.3.7 diff --git a/go.sum b/go.sum index 5642573..b636876 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,4 @@ git.xenrox.net/~xenrox/go-log v0.0.0-20221009121411-e93f4223b622 h1:XxHbaQOQllWEMoeSLocFWPyqMPWCDUDatDEtIdYIXhI= git.xenrox.net/~xenrox/go-log v0.0.0-20221009121411-e93f4223b622/go.mod h1:d98WFDHGpxaEThKue5CfGtr9OrWgbaApprt3GH+OM4s= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= diff --git a/main.go b/main.go index c48e0ed..9bc0511 100644 --- a/main.go +++ b/main.go @@ -1,20 +1,98 @@ package main import ( + "encoding/json" + "fmt" "net/http" "strings" + "time" "git.xenrox.net/~xenrox/go-log" + "golang.org/x/text/cases" + "golang.org/x/text/language" ) -func handleWebhooks(w http.ResponseWriter, r *http.Request) { - http.Post("https://ntfy.sh/alertmanager_test", "text/plain", - strings.NewReader("Payload received")) +type receiver struct { + logger *log.Logger +} + +type payload struct { + Status string `json:"status"` + Alerts []alert `json:"alerts"` + GroupLabels map[string]interface{} `json:"groupLabels"` + CommonLabels map[string]interface{} `json:"commonLabels"` + CommonAnnotations map[string]interface{} `json:"commonAnnotations"` +} + +type alert struct { + Status string `json:"status"` + Labels map[string]interface{} `json:"labels"` + Annotations map[string]interface{} `json:"annotations"` +} + +func (rcv *receiver) handleWebhooks(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + + var event payload + if err := json.NewDecoder(r.Body).Decode(&event); err != nil { + rcv.logger.Error(err) + return + } + + count := len(event.Alerts) + title := fmt.Sprintf("[%s", strings.ToUpper(event.Status)) + if event.Status == "firing" { + title = fmt.Sprintf("%s:%d", title, count) + } + + title += "]" + for _, value := range event.GroupLabels { + title = fmt.Sprintf("%s %s", title, value) + } + + var body string + c := cases.Title(language.English) + + for _, alert := range event.Alerts { + alertBody := fmt.Sprintf("%s\nLabels:\n", c.String(alert.Status)) + for key, value := range alert.Labels { + alertBody = fmt.Sprintf("%s%s = %s\n", alertBody, key, value) + } + + alertBody += "Annotations:\n" + for key, value := range alert.Annotations { + alertBody = fmt.Sprintf("%s%s = %s\n", alertBody, key, value) + } + + alertBody += "\n" + + body += alertBody + } + + client := &http.Client{Timeout: time.Second * 3} + url := "https://ntfy.sh/alertmanager_test" + req, err := http.NewRequest(http.MethodPost, url, strings.NewReader(body)) + if err != nil { + rcv.logger.Error(err) + } + + req.Header.Set("X-Title", title) + resp, err := client.Do(req) + if err != nil { + rcv.logger.Error(err) + } + + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + rcv.logger.Error("ntfy: received status code %d", resp.StatusCode) + } } func main() { logger := log.NewDefaultLogger() - http.HandleFunc("/", handleWebhooks) + receiver := &receiver{logger: logger} + + http.HandleFunc("/", receiver.handleWebhooks) logger.Fatal(http.ListenAndServe("127.0.0.1:8080", nil)) }