...
1 package webhooks
2
3 import (
4 "bytes"
5 "encoding/json"
6 "errors"
7 "net/http"
8 "time"
9
10 "github.com/go-logr/logr"
11
12 "edge-infra.dev/pkg/lib/logging"
13 )
14
15 type SlackMessage struct {
16 Text string `json:"text"`
17 }
18
19 type Slack interface {
20
21 SendMsg(msg *SlackMessage) error
22 }
23
24 type slack struct {
25 logger logr.Logger
26 client *http.Client
27 webhookURL string
28 }
29
30
31 var _ Slack = (*slack)(nil)
32
33 type Options struct {
34 Logger *logr.Logger
35 Client *http.Client
36 }
37
38 type Option func(*Options)
39
40 func NewSlackWebhook(url string, opts ...Option) Slack {
41 options := Options{}
42 for _, opt := range opts {
43 opt(&options)
44 }
45 options = setOptionsDefaults(options)
46
47 return &slack{
48 logger: options.Logger.WithValues("webhook", "slack"),
49 client: options.Client,
50 webhookURL: url,
51 }
52 }
53
54 func (s *slack) SendMsg(msg *SlackMessage) error {
55 slackBody, err := json.Marshal(msg)
56 if err != nil {
57 return err
58 }
59
60 req, err := http.NewRequest(http.MethodPost, s.webhookURL, bytes.NewBuffer(slackBody))
61 if err != nil {
62 return err
63 }
64 req.Header.Add("Content-Type", "application/json")
65
66
67
68
69
70
71
72
73 resp, err := s.client.Do(req)
74 if err != nil {
75 return err
76 }
77
78 buf := new(bytes.Buffer)
79 if _, err = buf.ReadFrom(resp.Body); err != nil {
80 return err
81 }
82
83
84
85
86 if buf.String() != "ok" {
87 return errors.New("INVALID RESPONSE RETURNED FROM THE SLACK API")
88 }
89
90 return nil
91 }
92
93
94 func setOptionsDefaults(options Options) Options {
95 if options.Logger == nil {
96 options.Logger = &logging.NewLogger().Logger
97 }
98 if options.Client == nil {
99 options.Client = &http.Client{Timeout: 10 * time.Second}
100 }
101 return options
102 }
103
View as plain text