-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapp.py
177 lines (127 loc) · 4.85 KB
/
app.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
# -*- coding: utf-8 -*-
import bot
import json
import hashlib
import requests
import os
import asyncio
import tinys3
from flask import Flask, request, make_response, render_template, send_from_directory, send_file
from pyppeteer.launcher import launch
from os.path import join, dirname
from dotenv import load_dotenv
from threading import Thread
dotenv_path = join(dirname(__file__), '.env')
load_dotenv(dotenv_path)
pyBot = bot.Bot()
slack = pyBot.client
conn = tinys3.Connection(os.environ.get("S3_SECRET"), os.environ.get("S3_KEY"), tls=True, default_bucket='peek-a-bot')
app = Flask(__name__,
static_url_path='',
static_folder='frontend/dist',
template_folder='frontend/dist')
def start_screenshot_worker(loop):
asyncio.set_event_loop(loop)
loop.run_forever()
worker_loop = asyncio.new_event_loop()
worker = Thread(target=start_screenshot_worker, args=(worker_loop,))
worker.start()
async def create_screenshot(config, response_url):
try:
browser = await launch(headless=True, options={"ignoreHTTPSErrors": True})
page = await browser.newPage()
await page.setViewport({
"width": config["width"],
"height": config["height"]
});
await page.goto(config["url"])
# Send the first response to let the user know the screenshot is being generated.
# This is done after page.goto() to prevent multiple messages.
payload = {
"username": "Peek-a-Bot",
"text": "Please wait a second while I'm generating the screenshot."
}
requests.post(response_url, data=json.dumps(payload))
filename = hashlib.sha256((os.environ.get("FILENAME_SALT") + config["url"] + str(config["width"]) + str(config["height"]) + str(config["fullPage"])).encode('utf-8')).hexdigest()
filepath = 'data/{url}.jpg'.format(url=filename)
await page.screenshot({'path': filepath, 'fullPage': config["fullPage"]})
await browser.close()
# Upload the file to S3 and delete the local temp file
file = open(filepath, 'rb')
response = conn.upload(filepath, file)
os.unlink(filepath)
# Send the second response with the screenshot to the user
payload = {
"username": "Peek-a-Bot",
"text": "Here you go:",
"attachments": [{
"text": config["url"],
"image_url": "{S3_INSTANCE}/{filepath}".format(S3_INSTANCE=os.environ.get("S3_INSTANCE"), filepath=filepath)
}]
}
requests.post(response_url, data=json.dumps(payload))
except Exception:
send_error(response_url)
def send_error(response_url):
payload = {
"username": "Peek-a-Bot",
"attachments": [{
"text": "Sorry, there seems to be an issue with your command.\nPlease make sure to pass the URL and the dimensions in the correct order:\n`/peek slack.com`, `/peek slack.com 1024 768` or `/peek slack.com all`",
"color": "#cc0000"
}]
}
requests.post(response_url, data=json.dumps(payload))
def parse_parameters(param_string, response_url):
param_array = param_string.split()
try:
# Add http-protocol in case the user didn't provide one
if (not param_array[0].startswith('http://') and not param_array[0].startswith('https://')):
param_array[0] = 'http://' + param_array[0]
parameters = {
"url": param_array[0],
"fullPage": False
}
# Set the correct size parameters depending on the user input
parameters["width"] = 1920
if (len(param_array) > 1):
if (param_array[1].isdigit()):
parameters["width"] = int(param_array[1])
else:
if (param_array[1] == "all"):
parameters["fullPage"] = True
if (len(param_array) > 2):
parameters["height"] = int(param_array[2])
else:
parameters["height"] = 1080
return parameters
except (ValueError,IndexError):
send_error(response_url)
@app.route("/", methods=["GET"])
def pre_install():
client_id = pyBot.oauth["client_id"]
scope = pyBot.oauth["scope"]
return render_template("index.html", client_id=client_id, scope=scope)
@app.route("/thanks", methods=["GET", "POST"])
def thanks():
code_arg = request.args.get('code')
pyBot.auth(code_arg)
return render_template("thanks.html")
@app.route("/listening", methods=["GET", "POST"])
def hears():
slack_event = json.loads(request.data)
if "challenge" in slack_event:
return make_response(slack_event["challenge"], 200, {"content_type": "application/json"})
if pyBot.verification != slack_event.get("token"):
message = "Invalid Slack verification token: %s \npyBot has: \
%s\n\n" % (slack_event["token"], pyBot.verification)
return make_response("[NO EVENT IN SLACK REQUEST]", 404, {"X-Slack-No-Retry": 1})
@app.route("/peek", methods=["GET", "POST"])
def peeks():
if (request.form):
response_url = request.form["response_url"]
screenshot_parameters = parse_parameters(request.form["text"], response_url)
if(screenshot_parameters):
worker_loop.call_soon_threadsafe(asyncio.async, create_screenshot(screenshot_parameters, response_url))
return ('', 204)
if __name__ == '__main__':
app.run(debug=False,ssl_context='adhoc')