-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathhandlers.go
166 lines (136 loc) · 4.42 KB
/
handlers.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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package main
import (
"bytes"
"encoding/json"
"fmt"
"strings"
)
type Event struct {
author string
message string
repository string
mergeRequest string
link string
}
var previousEventTS string = ""
func handleSlackEvent(slackEvent SlackEvent) error {
if slackEvent.Type != "message" {
return fmt.Errorf("Bot can only handle slack event message, stopping.")
}
if slackEvent.Subtype != "bot_message" {
return fmt.Errorf("Not a message from a bot, stopping.")
}
if len(slackEvent.Attachments) == 0 {
return fmt.Errorf("No message found, no mention needed, stopping.")
}
if SLACK_EVENT_READ_CHANNEL != "" && slackEvent.Channel != SLACK_EVENT_READ_CHANNEL {
return fmt.Errorf("Not monitoring the right channel, stopping.")
}
if slackEvent.TS == previousEventTS {
return fmt.Errorf("Bot prevented to proceed the same Slack event based on the timestamp %v, stopping.", slackEvent.TS)
}
previousEventTS = slackEvent.TS
fmt.Printf("Slack event passed validation for timestamp: %v\n", slackEvent.TS)
event := Event{
author: getAliasFromEventText(slackEvent.Text, author),
message: slackEvent.Attachments[0].Text,
repository: getAliasFromEventText(slackEvent.Text, repo),
mergeRequest: getAliasFromEventText(slackEvent.Text, mr),
link: getAliasFromEventText(slackEvent.Text, link),
}
return handle(event)
}
var previousNoteId int64 = 0
func handleGitLabWebhook(gitLabEvent GitLabWebhookEvent) error {
if gitLabEvent.EventType != "note" {
return fmt.Errorf("Bot can only handle gitlab webhook notes, stopping.")
}
if gitLabEvent.Note.Note == "" && gitLabEvent.Note.Description == "" {
return fmt.Errorf("No message found, no mention needed, stopping.")
}
if previousNoteId == gitLabEvent.Note.Id {
return fmt.Errorf("Bot prevented to proceed the same gitlab note id ''%v'' with note url ''%v'', stopping.", gitLabEvent.Note.Id, gitLabEvent.Note.Url)
}
previousNoteId = gitLabEvent.Note.Id
fmt.Printf("GitLab event passed validation for note: %v\n", gitLabEvent.Note.Url)
event := Event{
author: gitLabEvent.User.Name,
message: defaults(gitLabEvent.Note.Note, gitLabEvent.Note.Description),
repository: defaults(gitLabEvent.Repository.Name, gitLabEvent.Project.Name),
mergeRequest: defaults(gitLabEvent.MergeRequest.Title, gitLabEvent.MergeRequest.Description),
link: gitLabEvent.Note.Url,
}
return handle(event)
}
func handle(event Event) error {
usernames := getAllUsernameTags(event.message)
fmt.Printf("GitLab note usernames found: %v\n", usernames)
for _, username := range usernames {
userID, err := getUserID(username)
if err != nil {
return err
}
if userID == "" {
return fmt.Errorf("Bot did not find any user ID for %v", username)
}
greatings := strings.Join([]string{
fmt.Sprintf("<@%s>", userID),
getGreatings(event),
}, " ")
attachment := SlackAttachment{
Text: event.message,
Footer: event.link,
Color: SLACK_BOT_NOTIFICATION_COLOR,
}
attachmentData := &bytes.Buffer{}
enc := json.NewEncoder(attachmentData)
enc.SetEscapeHTML(false)
err = enc.Encode([]SlackAttachment{attachment})
if err != nil {
return err
}
botMessage := &BotMessage{
UserID: userID,
Attachments: attachmentData.String(),
Message: greatings,
}
notify(botMessage)
}
return nil
}
func getUserID(username string) (string, error) {
// fetch user from GitLab that generate an email
userEmail, err := fetchGitLabUserToFormattedEmail(username)
if err != nil {
return "", err
}
if !isEmailValid(userEmail) {
return "", fmt.Errorf("User email %v is invalid", userEmail)
}
// send query to Slack with email to retrieve the user ID
slackUser, err := fetchSlackUser(userEmail)
if err != nil {
return "", err
}
return slackUser.User.Id, nil
}
func fetchGitLabUserToFormattedEmail(username string) (string, error) {
// send query to gitlab with tag to retrieve user fullname
gitLabUser, err := fetchBasicGitLabUser(username)
if err != nil {
return "", err
}
// user email is public
if gitLabUser.Email != "" {
return gitLabUser.Email, nil
}
// transform fullname to email username
usernameTag, err := formatFullnameToUserEmail(gitLabUser.Name)
if err != nil {
usernameTag = username
fmt.Printf("Cannot parse user name to tag: %v\n", err)
}
fmt.Printf("GitLab user fullname to email username: %v\n", usernameTag)
// generate full email
return usernameTag + "@" + USER_EMAIL_DOMAIN, nil
}