-
Notifications
You must be signed in to change notification settings - Fork 0
/
message.go
146 lines (123 loc) · 3.98 KB
/
message.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package message
import (
"fmt"
"regexp"
"strings"
"slackbot_atlassian/atlassian"
"slackbot_atlassian/config"
"slackbot_atlassian/log"
)
type Message struct {
SlackChannel string
AsUser config.SlackUser
Text string
}
type MessageMatcher interface {
GetMatchingMessages([]*config.MessageTrigger, ...atlassian.ActivityIssue) []Message
}
type matcher struct {
cfg config.SlackConfig
custom_jira_fields []config.CustomJiraFieldConfig
user_image_urls map[string]string
}
func NewMessageMatcher(cfg config.SlackConfig, user_image_urls map[string]string, custom_jira_fields ...config.CustomJiraFieldConfig) MessageMatcher {
return matcher{cfg, custom_jira_fields, user_image_urls}
}
func (m matcher) GetMatchingMessages(triggers []*config.MessageTrigger, activity_issues ...atlassian.ActivityIssue) []Message {
messages := make([]Message, 0)
for _, activity_issue := range activity_issues {
for _, trigger := range triggers {
if match, ok, err := m.get_match(trigger, activity_issue); ok && err == nil {
messages = append(messages, match.get_messages()...)
} else if err != nil {
log.LogF("Error matching issue %v: %s", activity_issue, err)
}
}
}
return messages
}
func (m matcher) get_match(trigger *config.MessageTrigger, activity_issue atlassian.ActivityIssue) (*match, bool, error) {
for name, match := range trigger.GetCompiledMatches() {
// Look up the value for this field
field_val, ok, err := m.get_trigger_field_value(name, activity_issue)
if err != nil || !ok {
return nil, ok, err
}
if !match.MatchString(field_val) {
return nil, false, nil
}
}
return &match{m.user_image_urls, trigger, activity_issue}, true, nil
}
func (m matcher) get_trigger_field_value(name string, activity_issue atlassian.ActivityIssue) (string, bool, error) {
// First, check if this is a custom field defined by the JSON
lookup_field := func(name string) (string, bool, error) {
val, ok := activity_issue.Issue.Fields[name]
if !ok {
return "", false, nil
} else if val == nil {
return "", false, nil
}
switch val.(type) {
case map[string]interface{}:
value, ok := val.(map[string]interface{})["value"].(string)
if !ok {
return "", false, fmt.Errorf("Wrong type for val inside %s: want string, have %T", name, val)
}
return value, ok, nil
case string:
return val.(string), true, nil
case []interface{}:
// For now we just join them all with strings
var strs []string
for _, v := range val.([]interface{}) {
strs = append(strs, fmt.Sprintf("%s", v))
}
return strings.Join(strs, ","), true, nil
default:
return "", false, fmt.Errorf("Wrong type for %s: want map or string, have %T", name, val)
}
}
// First try to look up for each of our custom fields
for _, cf := range m.custom_jira_fields {
if cf.Name == name {
val, ok, err := lookup_field(cf.JiraField)
if ok {
return val, ok, err
}
}
}
// Now try with built-in fields
return lookup_field(name)
}
type match struct {
user_image_urls map[string]string
trigger *config.MessageTrigger
activity_issue atlassian.ActivityIssue
}
func (m match) get_messages() []Message {
message := Message{
m.trigger.SlackChannel,
config.SlackUser{
Name: m.activity_issue.Activity.Author.Name,
IconUrl: m.user_image_urls[m.activity_issue.Activity.Author.Username],
},
GetTextFromActivityItem(m.activity_issue.Activity),
}
return []Message{message}
}
func GetTextFromActivityItem(activity *atlassian.ActivityItem) string {
// Strip name from start of title
re := regexp.MustCompile("^<a.+?</a>")
text := re.ReplaceAllString(activity.Title, "")
// Convert resolved links
re = regexp.MustCompile(`<span class='resolved-link'>(.+?)</span>`)
text = re.ReplaceAllString(text, "~$1~")
// Convert HTML links
re = regexp.MustCompile(`<a .*?href="(.+?)".*?>(.+?)</a>`)
text = re.ReplaceAllString(text, "<$1|$2>")
// Strip duplicate whitespace
re = regexp.MustCompile("\\s+")
text = re.ReplaceAllString(text, " ")
return text
}