From 22bf082b3ee8165d361eb3798b8bf1c40a2fae59 Mon Sep 17 00:00:00 2001 From: Jesse Kalil Martins Date: Sun, 10 Jul 2022 14:10:44 -0300 Subject: [PATCH 1/2] checkup: add new notifier - gotify --- notifier.go | 3 ++ notifier/gotify/gotify.go | 107 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 notifier/gotify/gotify.go diff --git a/notifier.go b/notifier.go index 498a4f2..25bd773 100644 --- a/notifier.go +++ b/notifier.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/sourcegraph/checkup/notifier/discord" + "github.com/sourcegraph/checkup/notifier/gotify" "github.com/sourcegraph/checkup/notifier/mail" "github.com/sourcegraph/checkup/notifier/mailgun" "github.com/sourcegraph/checkup/notifier/pushover" @@ -23,6 +24,8 @@ func notifierDecode(typeName string, config json.RawMessage) (Notifier, error) { return pushover.New(config) case discord.Type: return discord.New(config) + case gotify.Type: + return gotify.New(config) default: return nil, fmt.Errorf(errUnknownNotifierType, typeName) } diff --git a/notifier/gotify/gotify.go b/notifier/gotify/gotify.go new file mode 100644 index 0000000..acc0d06 --- /dev/null +++ b/notifier/gotify/gotify.go @@ -0,0 +1,107 @@ +package gotify + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io/ioutil" + "log" + "net/http" + "net/url" + "strings" + "time" + + "github.com/sourcegraph/checkup/types" +) + +const Type = "gotify" + +type Notifier struct { + Token string `json:"token"` + Webhook string `json:"webhook"` +} + +func New(config json.RawMessage) (Notifier, error) { + var notifier Notifier + err := json.Unmarshal(config, ¬ifier) + return notifier, err +} + +func (Notifier) Type() string { + return Type +} + +func (g Notifier) Notify(results []types.Result) error { + var issues []types.Result + for _, result := range results { + if !result.Healthy { + issues = append(issues, result) + } + } + if len(issues) == 0 { + return nil + } + + return g.Send(issues) +} + +func (g Notifier) Send(results []types.Result) error { + message := renderMessage(results) + requestBody, err := json.Marshal(struct { + Title string `json:"title"` + Message string `json:"message"` + Priority int `json:"priority"` + }{"Checkup", message, 5}) + + if err != nil { + return fmt.Errorf("gotify: error marshalling body: %w", err) + } + + ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) + client := &http.Client{} + webhookUrl, err := url.Parse(g.Webhook) + + if err != nil { + return fmt.Errorf("gotify: error in parse webhook: %w", err) + } + + query := webhookUrl.Query() + query.Add("token", g.Token) + webhookUrl.RawQuery = query.Encode() + + req, err := http.NewRequestWithContext(ctx, "POST", + webhookUrl.String(), + bytes.NewBuffer(requestBody)) + req.Header.Set("Content-Type", "application/json") + + // response + resp, err := client.Do(req) + if err != nil { + return fmt.Errorf("gotify: error issuing request: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode > http.StatusBadRequest { + bodyBytes, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Println("gotify: error reading response body", err) + } + bodyString := string(bodyBytes) + log.Println("gotify: response body:", bodyString) + return fmt.Errorf("gotify: expected status 200, got %d", resp.StatusCode) + } + return err +} + +func renderMessage(issues []types.Result) string { + body := []string{"Checkup has detected the following issues:\n"} + for _, issue := range issues { + status := strings.ToUpper(fmt.Sprint(issue.Status())) + text := fmt.Sprintf("%s (%s) - Status: %s - Attempts: %d", + issue.Title, issue.Endpoint, status, issue.Times.Len()) + body = append(body, text) + } + return strings.Join(body, "\n") + +} From 5eb84dc94b6089e8660db5272dcc5a81144d66ea Mon Sep 17 00:00:00 2001 From: Jesse Kalil Martins Date: Sun, 10 Jul 2022 14:28:12 -0300 Subject: [PATCH 2/2] Add the Gotify example in README.md --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index cb459f9..054aed5 100644 --- a/README.md +++ b/README.md @@ -384,6 +384,17 @@ Enable notifications using Pushover with this Notifier configuration: } ``` +#### Gotify notifier + +Enable notifications using [Gotify](https://github.com/gotify/server) with this Notifier configuration: +```js +{ + "type": "gotify", + "token": "APP_TOKEN", + "webhook": "https://push.example.com/message" +} +``` + ## Setting up storage on S3 The easiest way to do this is to give an IAM user these two privileges (keep the credentials secret):