Integrations: Enable <!channel> notifications in incoming webhooks (#3039)
Этот коммит содержится в:
коммит произвёл
Harrison Healey
родитель
55f6a0b21c
Коммит
4f34730b3f
@@ -8,6 +8,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -192,6 +193,55 @@ func decodeIncomingWebhookRequest(by []byte) (*IncomingWebhookRequest, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// To mention @channel via a webhook in Slack, the message should contain
|
||||||
|
// <!channel>, as explained at the bottom of this article:
|
||||||
|
// https://get.slack.help/hc/en-us/articles/202009646-Making-announcements
|
||||||
|
func expandAnnouncement(text string) string {
|
||||||
|
c1 := "<!channel>"
|
||||||
|
c2 := "@channel"
|
||||||
|
if strings.Contains(text, c1) {
|
||||||
|
return strings.Replace(text, c1, c2, -1)
|
||||||
|
}
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expand announcements in incoming webhooks from Slack. Those announcements
|
||||||
|
// can be found in the text attribute, or in the pretext, text, title and value
|
||||||
|
// attributes of the attachment structure. The Slack attachment structure is
|
||||||
|
// documented here: https://api.slack.com/docs/attachments
|
||||||
|
func expandAnnouncements(i *IncomingWebhookRequest) {
|
||||||
|
i.Text = expandAnnouncement(i.Text)
|
||||||
|
|
||||||
|
if i.Attachments != nil {
|
||||||
|
attachments := i.Attachments.([]interface{})
|
||||||
|
for _, attachment := range attachments {
|
||||||
|
a := attachment.(map[string]interface{})
|
||||||
|
|
||||||
|
if a["pretext"] != nil {
|
||||||
|
a["pretext"] = expandAnnouncement(a["pretext"].(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
if a["text"] != nil {
|
||||||
|
a["text"] = expandAnnouncement(a["text"].(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
if a["title"] != nil {
|
||||||
|
a["title"] = expandAnnouncement(a["title"].(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
if a["fields"] != nil {
|
||||||
|
fields := a["fields"].([]interface{})
|
||||||
|
for _, field := range fields {
|
||||||
|
f := field.(map[string]interface{})
|
||||||
|
if f["value"] != nil {
|
||||||
|
f["value"] = expandAnnouncement(f["value"].(string))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func IncomingWebhookRequestFromJson(data io.Reader) *IncomingWebhookRequest {
|
func IncomingWebhookRequestFromJson(data io.Reader) *IncomingWebhookRequest {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
buf.ReadFrom(data)
|
buf.ReadFrom(data)
|
||||||
@@ -207,5 +257,7 @@ func IncomingWebhookRequestFromJson(data io.Reader) *IncomingWebhookRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expandAnnouncements(o)
|
||||||
|
|
||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,6 +101,65 @@ func TestIncomingWebhookPreUpdate(t *testing.T) {
|
|||||||
o.PreUpdate()
|
o.PreUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIncomingWebhookRequestFromJson_Announcements(t *testing.T) {
|
||||||
|
text := "This message will send a notification to all team members in the channel where you post the message, because it contains: <!channel>"
|
||||||
|
expected := "This message will send a notification to all team members in the channel where you post the message, because it contains: @channel"
|
||||||
|
|
||||||
|
// simple payload
|
||||||
|
payload := `{"text": "` + text + `"}`
|
||||||
|
data := strings.NewReader(payload)
|
||||||
|
iwr := IncomingWebhookRequestFromJson(data)
|
||||||
|
|
||||||
|
if iwr == nil {
|
||||||
|
t.Fatal("IncomingWebhookRequest should not be nil")
|
||||||
|
}
|
||||||
|
if iwr.Text != expected {
|
||||||
|
t.Fatalf("Sample text should be: %s, got: %s", expected, iwr.Text)
|
||||||
|
}
|
||||||
|
|
||||||
|
// payload with attachment (pretext, title, text, value)
|
||||||
|
payload = `{
|
||||||
|
"attachments": [
|
||||||
|
{
|
||||||
|
"pretext": "` + text + `",
|
||||||
|
"title": "` + text + `",
|
||||||
|
"text": "` + text + `",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"title": "A title",
|
||||||
|
"value": "` + text + `",
|
||||||
|
"short": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
|
||||||
|
data = strings.NewReader(payload)
|
||||||
|
iwr = IncomingWebhookRequestFromJson(data)
|
||||||
|
|
||||||
|
if iwr == nil {
|
||||||
|
t.Fatal("IncomingWebhookRequest should not be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
attachments := iwr.Attachments.([]interface{})
|
||||||
|
attachment := attachments[0].(map[string]interface{})
|
||||||
|
if attachment["pretext"] != expected {
|
||||||
|
t.Fatalf("Sample attachment pretext should be: %s, got: %s", expected, attachment["pretext"])
|
||||||
|
}
|
||||||
|
if attachment["text"] != expected {
|
||||||
|
t.Fatalf("Sample attachment text should be: %s, got: %s", expected, attachment["text"])
|
||||||
|
}
|
||||||
|
if attachment["title"] != expected {
|
||||||
|
t.Fatalf("Sample attachment title should be: %s, got: %s", expected, attachment["title"])
|
||||||
|
}
|
||||||
|
fields := attachment["fields"].([]interface{})
|
||||||
|
field := fields[0].(map[string]interface{})
|
||||||
|
if field["value"] != expected {
|
||||||
|
t.Fatalf("Sample attachment field value should be: %s, got: %s", expected, field["value"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestIncomingWebhookRequestFromJson(t *testing.T) {
|
func TestIncomingWebhookRequestFromJson(t *testing.T) {
|
||||||
texts := []string{
|
texts := []string{
|
||||||
`this is a test`,
|
`this is a test`,
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user