You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
82 lines
2.4 KiB
82 lines
2.4 KiB
5 years ago
|
import datetime
|
||
|
import hashlib
|
||
|
import hmac
|
||
|
import json
|
||
|
import logging
|
||
|
import os
|
||
|
|
||
|
import flask
|
||
|
import flask_apscheduler
|
||
|
import flask_restful
|
||
|
import flask_restful.reqparse
|
||
|
|
||
|
from sender import Sender
|
||
|
|
||
|
|
||
|
subscriptions = {}
|
||
|
|
||
|
app = flask.Flask(__name__)
|
||
|
app.logger.setLevel(logging.INFO)
|
||
|
app.config.update(
|
||
|
ERROR_404_HELP=False,
|
||
|
SCHEDULER_TIMEZONE='UTC',
|
||
|
SCHEDULER_JOBS=[
|
||
|
dict(id='subscribe',
|
||
|
func='twitch:Twitch.subscribe',
|
||
|
args=(app, subscriptions, 86400),
|
||
|
max_instances=1,
|
||
|
trigger='interval',
|
||
|
seconds=3600,
|
||
|
next_run_time=datetime.datetime.utcnow() + datetime.timedelta(seconds=10))])
|
||
|
|
||
|
scheduler = flask_apscheduler.APScheduler()
|
||
|
scheduler.init_app(app)
|
||
|
|
||
|
api = flask_restful.Api(app)
|
||
|
|
||
|
sender = Sender(app)
|
||
|
|
||
|
|
||
|
verification_parser = flask_restful.reqparse.RequestParser()
|
||
|
verification_parser.add_argument('hub.challenge', type=str, required=True)
|
||
|
verification_parser.add_argument('hub.lease_seconds', type=int, required=True)
|
||
|
verification_parser.add_argument('hub.mode', type=str, required=True)
|
||
|
verification_parser.add_argument('hub.topic', type=str, required=True)
|
||
|
|
||
|
|
||
|
class WebhooksResource(flask_restful.Resource):
|
||
|
def get(self):
|
||
|
args = verification_parser.parse_args()
|
||
|
verified = False
|
||
|
for sub in subscriptions.values():
|
||
|
h = '{0[hub.mode]}|{0[hub.topic]}|{0[hub.lease_seconds]}'.format(args)
|
||
|
if hashlib.sha256(h.encode()).hexdigest() == sub['request_hash']:
|
||
|
verified = True
|
||
|
break
|
||
|
if not verified:
|
||
|
flask_restful.abort(400, message='Verification failed')
|
||
|
r = app.make_response(args['hub.challenge'])
|
||
|
r.mimetype = 'text/plain'
|
||
|
r.status_code = 200
|
||
|
return r
|
||
|
|
||
|
def post(self):
|
||
|
sha, signature = flask.request.headers.get('X-Hub-Signature').split('=')
|
||
|
data = flask.request.data
|
||
|
for topic, sub in subscriptions.items():
|
||
|
mac = hmac.new(sub['secret'].encode(), data, getattr(hashlib, sha))
|
||
|
if not hmac.compare_digest(mac.hexdigest(), signature):
|
||
|
continue
|
||
|
message = flask.request.get_json(force=True)
|
||
|
message['topic'] = topic
|
||
|
sender.send(json.dumps(message).encode())
|
||
|
return None, 204
|
||
|
|
||
|
|
||
|
api.add_resource(WebhooksResource, '/webhooks')
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
scheduler.start()
|
||
|
app.run(host='0.0.0.0', threaded=True, debug=False)
|