From b14d7083878c961fa5918bc15976aaec4440a3a2 Mon Sep 17 00:00:00 2001 From: Ibrahim Date: Fri, 19 Nov 2021 14:57:15 +0300 Subject: [PATCH] add slack library Signed-off-by: Ibrahim --- slack/slack.go | 77 +++++++++++++++++++++++++++++++++++++++++++++ slack/slack_test.go | 43 +++++++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 slack/slack.go create mode 100644 slack/slack_test.go diff --git a/slack/slack.go b/slack/slack.go new file mode 100644 index 0000000..5c431b8 --- /dev/null +++ b/slack/slack.go @@ -0,0 +1,77 @@ +package slack + +import ( + "encoding/json" + "errors" + + "gopkg.in/resty.v1" +) + +var ( + errorBadResponse = "API call gave an other-than-200 result" + errorEmptyText = "refusing to send an empty message, consider calling slack.SetText() first" +) + +// Provider provides an interface to interact with the Slack Webhook API +type Provider struct { + Debug bool + Payload Payload + WebhookURL string +} + +// Payload holds information about the message we want to send. Any of these values except Text may be left empty to +// use the defaults for the Webhook. IconEmoji and IconURL are mutually exclusive, do not set both. +// https://api.slack.com/incoming-webhooks#posting_with_webhooks +type Payload struct { + Channel string `json:"channel,omitempty"` + IconEmoji string `json:"icon_emoji,omitempty"` + IconURL string `json:"icon_url,omitempty"` + Text string `json:"text,omitempty"` + Username string `json:"username,omitempty"` +} + +// New creates a new invocation of this Provider wrapper +func New(webhookURL string) Provider { + return Provider{ + WebhookURL: webhookURL, + } +} + +// SetText sets the message text, i.e. what will be displayed in the Slack window +func (a *Provider) SetText(text string) { + a.Payload.Text = text +} + +// Send sends a message to Slack +func (a *Provider) Send() error { + if a.Payload.Text == "" { + return errors.New(errorEmptyText) + } + body, err := json.Marshal(a.Payload) + if err != nil { + return err + } + + restyResult, err := resty. + SetDebug(a.Debug). + SetHostURL(a.WebhookURL). + R(). + SetFormData(map[string]string{"payload": string(body)}). + Post(a.WebhookURL) + + if err != nil { + return err + } + + if restyResult.StatusCode() != 200 { + return errors.New(errorBadResponse) + } + + return nil +} + +// SendText sets message text and sends the message, a convenience wrapper for SetText and Send +func (a *Provider) SendText(text string) error { + a.SetText(text) + return a.Send() +} diff --git a/slack/slack_test.go b/slack/slack_test.go new file mode 100644 index 0000000..385ece5 --- /dev/null +++ b/slack/slack_test.go @@ -0,0 +1,43 @@ +package slack + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// generic helper for loading Slack API wrapper with Webhook URL +func getAPI(t *testing.T) Provider { + webhookURL := os.Getenv("SLACK_WEBHOOK_URL") + require.NotEmpty(t, webhookURL, "ParameterNotFound: SLACK_WEBHOOK_URL") + + api := New(webhookURL) + api.Payload.IconEmoji = ":robot_face:" + api.Payload.Username = "Insights Slack - Unit Test" + + return api +} + +func TestSendEmpty(t *testing.T) { + api := getAPI(t) + + err := api.Send() + assert.EqualError(t, err, errorEmptyText) +} + +func TestSendNotEmpty(t *testing.T) { + api := getAPI(t) + api.SetText("TestSendNotEmpty Test Content") + + err := api.Send() + assert.NoError(t, err, "unexpected err from api.Send()") +} + +func TestSendText(t *testing.T) { + api := getAPI(t) + + err := api.SendText("TestSendText Test Content") + assert.NoError(t, err, "unexpected err from api.SendText()") +}