-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathslackInt.py
172 lines (133 loc) · 5.88 KB
/
slackInt.py
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
167
168
169
170
171
172
"""Generate salck message and send it to appropriate recipient."""
import datetime
import logging
import math
import os
from slack import WebClient as SlackClient
from github import GithubWebhookPayloadParser
from github import getRecipientGithubUserNameByAction
from github import lookupGithubFullName
def notifyRecipient(data):
"""Notify the selected recipient on slack."""
payload = createSlackMessagePayload(data)
sendSlackMessage(payload)
def createSlackMessagePayload(data):
"""Create payload for slack notification."""
pr_metadata = getPullRequestMetadata(data)
msg_text = getMessage(pr_metadata, data)
message = buildPayload(msg_text, pr_metadata)
return message
def getMessage(pr_metadata, data):
"""Generate message based on github action."""
if data.get('action') == 'review_requested':
actionMessage = 'asked by {author} to review a pull request'.format(
author=pr_metadata.get('author'))
elif data.get('action') == 'assigned':
actionMessage = 'assigned a pull request by {author}'.format(
author=pr_metadata.get('author'))
else:
actionMessage = 'pinged'
msg_text = "You've been {action}. Good luck!".format(action=actionMessage)
if pr_metadata.get('channel') == os.environ.get('DEFAULT_NOTIFICATION_CHANNEL'):
github_username = getUnmatchedUserName(data)
msg_text = '{}! {}'.format(github_username, msg_text)
return msg_text
def buildPayload(msg_text, pr_metadata):
"""Build slack notification payload from github action data."""
message = {
"text": msg_text,
"as_user": True,
"link_names": True,
"channel": pr_metadata.get('channel'),
"attachments": [
{
"fallback": "<{}|{}>".format(pr_metadata.get('url'), pr_metadata.get('title')),
"color": "#36a64f",
"author_name": "{} pull request #{}".format(pr_metadata.get('repo'), pr_metadata.get('number')),
"author_link": pr_metadata.get('url'),
"author_icon": "https://github.com/favicon.ico",
"title": pr_metadata.get('title'),
"title_link": pr_metadata.get('url'),
"text": pr_metadata.get('description'),
"footer": "PR Notifications by Magnitude",
"footer_icon": pr_metadata.get('author_image'),
"ts": int(datetime.datetime.now().timestamp())
}
]
}
return message
def getPullRequestMetadata(data):
"""Fetch pull request metadata."""
pullRequestData = {}
payloadParser = GithubWebhookPayloadParser(data)
pullRequestData['url'] = payloadParser.getPullRequestUrl()
pullRequestData['title'] = payloadParser.getPullRequestTitle(
) or 'Unknown Title'
pullRequestData['repo'] = payloadParser.getPullRequestRepo() or 'Unknown'
pullRequestData['number'] = payloadParser.getPullRequestNumber() or math.pi
pullRequestData['author_image'] = payloadParser.getPullRequestAuthorImage()
pullRequestData['description'] = payloadParser.getPullRequestDescription()
pullRequestData['channel'] = getNotificationChannel(data)
pullRequestAuthor = getSlackUserNameByGithubUserName(
payloadParser.getPullRequestAuthor())
if pullRequestAuthor:
pullRequestAuthor = '@{}'.format(pullRequestAuthor)
else:
pullRequestAuthor = 'someone'
pullRequestData['author'] = pullRequestAuthor
return pullRequestData
def getNotificationChannel(data):
"""Get target slack channel for notification."""
github_username = getRecipientGithubUserNameByAction(data)
slack_username = getSlackUserNameByGithubUserName(github_username)
if slack_username:
channel = '@{}'.format(slack_username)
else:
channel = os.environ.get('DEFAULT_NOTIFICATION_CHANNEL')
return channel
def getSlackUserNameByGithubUserName(github_username):
"""Get slack username based on github username."""
slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN'))
response = slack_client.api_call("users.list")
users = response.get('members', [])
if github_username:
slack_username = matchSlackGithubUserName(users, github_username)
if not slack_username:
full_name = lookupGithubFullName(github_username)
slack_username = matchSlackUserNameByFullName(users, full_name)
return slack_username
return None
def matchSlackGithubUserName(users, github_username):
"""Compare slack and github username for a user."""
for user in users:
if isinstance(user, dict) and (
user.get('name').lower() == github_username.lower()
or user.get('profile', {}).get('display_name', '').lower() == github_username.lower()
):
return user.get('name')
return None
def matchSlackUserNameByFullName(users, full_name):
"""Compare salck username with github user full name."""
if full_name:
for user in users:
if isinstance(user, dict) and user.get('real_name', '').strip().lower() == full_name.strip().lower():
return user.get('name')
return None
def getUnmatchedUserName(data):
"""Set username for unmatched user in slack."""
payloadParser = GithubWebhookPayloadParser(data)
github_username = payloadParser.getRequestReviewerUserName()
if github_username is not None:
return '@{}'.format(github_username)
return 'Hey you, tech people'
def sendSlackMessage(payload):
"""Send generated slack message ."""
slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN'))
response = slack_client.api_call(
api_method="chat.postMessage", json=payload)
logger = logging.getLogger(__name__)
if not response.get('ok'):
logger.warning(
'Unable to send message. Response: %s\nPayload:\n%s', response, payload)
else:
logger.info('Success!')