Skip to content

Commit 04260db

Browse files
Add slack webhook lib
1 parent 729cd96 commit 04260db

8 files changed

Lines changed: 272 additions & 1 deletion

File tree

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
# Output of the go coverage tool, specifically when used with LiteIDE
55
*.out
66

7-
# Emacs
7+
# IDE
88
*~
99
\#*\#
1010
.\#*
11+
.idea

doc.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2019 The Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// Package slack allows application to seamlessly send Slack Message by using the Incoming Webhooks API from Slack.
16+
//
17+
package slack

errors.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2019 The Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
package slack
15+
16+
// Slack errors.
17+
const (
18+
ErrSerializeMessage = Error("couldn't serialise Slack Message")
19+
ErrCreateRequest = Error("couldn't create the request")
20+
ErrSendingRequest = Error("couldn't send Slack Message")
21+
)
22+
23+
// Error represents a Slack error.
24+
type Error string
25+
26+
// Error returns the error message.
27+
func (e Error) Error() string {
28+
return string(e)
29+
}

exemple_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2019 The Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package slack_test
16+
17+
import (
18+
"fmt"
19+
20+
"github.com/anthonycorbacho/slack-webhook"
21+
)
22+
23+
func ExemplBasic() {
24+
hookURL := "<slack_hook_url>"
25+
26+
attachment1 := slack.Attachment{}
27+
attachment1.AddField(slack.Field{Title: "Field test", Value: "Field value"})
28+
29+
msg := slack.Message{
30+
Text: "This is a slack message content",
31+
Attachments: []slack.Attachment{attachment1},
32+
}
33+
err := slack.Send(hookURL, msg)
34+
if err != nil {
35+
fmt.Printf("failed to send message: %v\n", err)
36+
}
37+
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module github.com/anthonycorbacho/slack-webhook

go.sum

Whitespace-only changes.

slack.go

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// Copyright 2019 The Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
package slack
15+
16+
import (
17+
"bytes"
18+
"crypto/tls"
19+
"encoding/json"
20+
"fmt"
21+
"net/http"
22+
)
23+
24+
// Send send message (Payload) to the given slack hook URL.
25+
func Send(hookURL string, message Message) error {
26+
bts, err := json.Marshal(message)
27+
if err != nil {
28+
return ErrSerializeMessage
29+
}
30+
31+
tr := &http.Transport{
32+
TLSClientConfig: &tls.Config{
33+
InsecureSkipVerify: true,
34+
},
35+
}
36+
37+
client := &http.Client{Transport: tr}
38+
req, err := http.NewRequest("POST", hookURL, bytes.NewReader(bts))
39+
if err != nil {
40+
return ErrCreateRequest
41+
}
42+
43+
res, err := client.Do(req)
44+
if err != nil {
45+
return ErrSendingRequest
46+
}
47+
defer res.Body.Close()
48+
49+
if res.StatusCode >= 400 {
50+
return fmt.Errorf("error sending slack message. Status: %v", res.StatusCode)
51+
}
52+
53+
return nil
54+
}
55+
56+
// Message contains the slack message.
57+
type Message struct {
58+
Parse string `json:"parse,omitempty"`
59+
Username string `json:"username,omitempty"`
60+
IconUrl string `json:"icon_url,omitempty"`
61+
IconEmoji string `json:"icon_emoji,omitempty"`
62+
Channel string `json:"channel,omitempty"`
63+
Text string `json:"text,omitempty"`
64+
LinkNames string `json:"link_names,omitempty"`
65+
Attachments []Attachment `json:"attachments,omitempty"`
66+
UnfurlLinks bool `json:"unfurl_links,omitempty"`
67+
UnfurlMedia bool `json:"unfurl_media,omitempty"`
68+
Markdown bool `json:"mrkdwn,omitempty"`
69+
}
70+
71+
// Attachment let you add more context to a message, making them more useful and effective.
72+
// See https://api.slack.com/docs/message-attachments
73+
type Attachment struct {
74+
Fallback *string `json:"fallback"`
75+
Color *string `json:"color"`
76+
PreText *string `json:"pretext"`
77+
AuthorName *string `json:"author_name"`
78+
AuthorLink *string `json:"author_link"`
79+
AuthorIcon *string `json:"author_icon"`
80+
Title *string `json:"title"`
81+
TitleLink *string `json:"title_link"`
82+
Text *string `json:"text"`
83+
ImageUrl *string `json:"image_url"`
84+
Fields []*Field `json:"fields"`
85+
Footer *string `json:"footer"`
86+
FooterIcon *string `json:"footer_icon"`
87+
Timestamp *int64 `json:"ts"`
88+
MarkdownIn *[]string `json:"mrkdwn_in"`
89+
Actions []*Action `json:"actions"`
90+
CallbackID *string `json:"callback_id"`
91+
ThumbnailUrl *string `json:"thumb_url"`
92+
}
93+
94+
// AddField appends a new field to the Attachment
95+
func (attachment *Attachment) AddField(field Field) *Attachment {
96+
attachment.Fields = append(attachment.Fields, &field)
97+
return attachment
98+
}
99+
100+
// AddAction appends a new Action to the Attachment
101+
func (attachment *Attachment) AddAction(action Action) *Attachment {
102+
attachment.Actions = append(attachment.Actions, &action)
103+
return attachment
104+
}
105+
106+
// Field is defined as a dictionary with key-value pairs.
107+
type Field struct {
108+
Title string `json:"title"`
109+
Value string `json:"value"`
110+
Short bool `json:"short"`
111+
}
112+
113+
// Action make message interactive
114+
type Action struct {
115+
Type string `json:"type"`
116+
Text string `json:"text"`
117+
Url string `json:"url"`
118+
Style string `json:"style"`
119+
}

slack_test.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Copyright 2019 The Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
package slack
15+
16+
import (
17+
"encoding/json"
18+
"fmt"
19+
"io/ioutil"
20+
"net/http"
21+
"net/http/httptest"
22+
"testing"
23+
)
24+
25+
func handler() http.Handler {
26+
r := http.NewServeMux()
27+
r.HandleFunc("/services", testHandler)
28+
return r
29+
}
30+
31+
func testHandler(w http.ResponseWriter, r *http.Request) {
32+
body := r.Body
33+
if body == nil {
34+
http.Error(w, "missing value", http.StatusBadRequest)
35+
return
36+
}
37+
defer body.Close()
38+
39+
var msg Message
40+
41+
b, _ := ioutil.ReadAll(r.Body)
42+
err := json.Unmarshal(b, &msg)
43+
if err != nil {
44+
http.Error(w, "cannot unmarshal body", http.StatusBadRequest)
45+
return
46+
}
47+
}
48+
49+
func Test_slack(t *testing.T) {
50+
srv := httptest.NewServer(handler())
51+
defer srv.Close()
52+
53+
slackURL := fmt.Sprintf("%s/services", srv.URL)
54+
55+
attachment1 := Attachment{}
56+
attachment1.AddField(Field{Title: "Field", Value: "Field test value"})
57+
58+
msg := Message{
59+
Text: "the is a slack test massage",
60+
Attachments: []Attachment{attachment1},
61+
}
62+
63+
err := Send(slackURL, msg)
64+
if err != nil {
65+
t.Error(err)
66+
}
67+
}

0 commit comments

Comments
 (0)