-
Notifications
You must be signed in to change notification settings - Fork 2
/
handler.py
285 lines (245 loc) · 8.69 KB
/
handler.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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
# -*- coding: utf-8 -*-
"""
A routing layer for the onboarding bot tutorial built using
[Slack's Events API](https://api.slack.com/events-api) in Python
"""
import bot
import boto3
import json
import mention
pyBot = bot.Bot()
slack = pyBot.client
def store_token(token):
try:
res = boto3.resource('dynamodb', region_name='us-east-1')
table = res.Table('poor-webhook-tokens')
response = table.put_item(
Item={
'account_id': token.split('.')[0],
'token': token
}
)
pyBot.update_auth()
return response
except Exception as e:
print(e)
def thanks(event, context):
message = """
<!doctype html>
<title>Install pythOnBoarding</title>
<br>
<br>
<br>
<center>
<h1>Thanks for installing!</h1>
</center>
"""
print(event)
print(context)
try:
store_token(event['queryStringParameters']['code'])
response = {
"statusCode": 200,
"body": message,
"headers": {
"Content-Type": "text/html"
}
}
except Exception as e:
print(e)
message = 'Could not store token.'
response = {
"statusCode": 500,
"body": message,
"headers": {
"Content-Type": "text/html"
}
}
return response
def install(event, context):
scope = pyBot.oauth["scope"]
client_id = pyBot.oauth["client_id"]
message = """
<!doctype html>
<title>Install pythOnBoarding</title>
<br>
<br>
<br>
<center>
<h1>Click the button to install pythOnBoarding Bot</h1>
<a href="https://slack.com/oauth/authorize?scope={scope}&client_id={client_id}">
<img alt="Add to Slack" height="40" width="139" src="https://platform.slack-edge.com/img/add_to_slack.png" srcset="https://platform.slack-edge.com/img/add_to_slack.png 1x, https://platform.slack-edge.com/img/add_to_slack@2x.png 2x" />
</a>
</center>
""".format(
scope=scope,
client_id=client_id
)
response = {
"statusCode": 200,
"body": message,
"headers": {
"Content-Type": "text/html"
}
}
return response
def _event_handler(event_type, slack_event):
"""
A helper function that routes events from Slack to our Bot
by event type and subtype.
Parameters
----------
event_type : str
type of event received from Slack
slack_event : dict
JSON response from a Slack reaction event
Returns
----------
obj
Response object with 200 - ok or 500 - No Event Handler error
"""
team_id = slack_event["team_id"]
# ================ Team Join Events =============== #
# When the user first joins a team, the type of event will be team_join
if event_type == "team_join":
pass
else:
pass
def hears(event, context):
"""
This route listens for incoming events from Slack and uses the event
handler helper function to route events to our Bot.
"""
slack_event = event.get('body')
if slack_event is not None:
slack_event = json.loads(slack_event)
# ============= Slack URL Verification ============ #
# In order to verify the url of our endpoint, Slack will send a challenge
# token in a request and check for this token in the response our endpoint
# sends back.
# For more info: https://api.slack.com/events/url_verification
# TBD handle this
"""
{
"token": "QSNFm4OA5WD9jr8v5MAlJOky", "team_id": "T63CVJG4U",
"api_app_id": "A63ELGLVB",
"event": {
"type": "message", "user": "U62M7T83A",
"text": "@poor-webhook get changelog boo.md for commit for
commit bff6b7dcda5cb723908c514d814ca4fbbe558912",
"ts": "1499662208.370661", "channel": "C646H1UBZ", "event_ts": "1499662208.370661" },
"type": "event_callback", "authed_users": [ "U62M7T83A" ], "event_id": "Ev661M0Q11",
"event_time": 1499662208
}
"""
#print(slack_event['event']['text'].split(' ')[0])
try:
if slack_event['event']['text'].split(' ')[0] == "@poor-webhook":
"""If this is a direct message to the bot in the channel react appropriately."""
print('Message sent directly to slack bot, reacting now.')
mention.react(slack_event['event'].get('text'), pyBot)
except:
pass
if "challenge" in slack_event:
# return make_response(slack_event["challenge"], 200, {"content_type":
# "application/json"
# })
response = {
"statusCode": 200,
"body": slack_event.get('challenge'),
"headers": {
"Content-Type": "application/json"
}
}
return response
# ============ Slack Token Verification =========== #
# We can verify the request is coming from Slack by checking that the
# verification token in the request matches our app's settings
if pyBot.verification != slack_event.get("token"):
message = "Invalid Slack verification token: %s \npyBot has: \
%s\n\n" % (slack_event["token"], pyBot.verification)
# By adding "X-Slack-No-Retry" : 1 to our response headers, we turn off
# Slack's automatic retries during development.
response = {
"statusCode": 403,
"body": message,
"headers": {
"Content-Type": "text/html",
"X-Slack-No-Retry": 1
}
}
return response
# ====== Process Incoming Events from Slack ======= #
# If the incoming request is an Event we've subcribed to
if "event" in slack_event:
event_type = slack_event["event"]["type"]
# Then handle the event by event_type and have your bot respond
return _event_handler(event_type, slack_event)
# If our bot hears things that are not events we've subscribed to,
# send a quirky but helpful error response
message = "[NO EVENT IN SLACK REQUEST] These are not the droids you're looking for."
response = {
"statusCode": 404,
"body": message,
"headers": {
"Content-Type": "text/html",
"X-Slack-No-Retry": 1
}
}
return
def clean_empty(d):
if not isinstance(d, (dict, list)):
return d
if isinstance(d, list):
return [v for v in (clean_empty(v) for v in d) if v]
return {k: v for k, v in ((k, clean_empty(v)) for k, v in d.items()) if v}
def github_webhook(event, context):
"""Fires anytime github webhook content comes in."""
try:
# Parse the headers for convenience.
event_id = event['headers']['X-GitHub-Delivery']
event_type = event['headers']['X-GitHub-Event']
event_body = json.loads(event['body'])
# Add our event_id to the body.
event_body['X-Github-Delivery'] = event_id
event_body['X-GitHub-Event'] = event_type
# Remove any keys whose value is empty string.
event_body = clean_empty(event_body)
print(event_body)
# Store the event in DynamoDb for use later.
res = boto3.resource('dynamodb', region_name='us-east-1')
table = res.Table('poor-webhook-events')
response = table.put_item(
Item=event_body
)
except Exception as e:
print(e)
if event_type == 'push':
"""Handle pushes to any branch"""
slack_message = "A commit has landed in the {branch} of {repository}. Message is : {message}. "\
"For a copy of the changelog you can say @poor-webhook get changelog ||filename|| "\
"for event {event_id}.".format(
branch=event_body['ref'].split('/')[2],
message=event_body['head_commit']['message'],
event_id=event_id,
repository=event_body['repository']['full_name']
)
pyBot.message_channel(
'#general',
slack_message
)
pass
elif event_type == 'pull_request':
"""Handle PRs"""
pass
elif event_type == 'issue':
pass
response = {
"statusCode": 200,
"body": "",
"headers": {
"Content-Type": "text/html",
"X-Slack-No-Retry": 1
}
}
return response