]> git.gir.st - subscriptionfeed.git/blob - app/webhooks.py
move flask secret_key to config.ini
[subscriptionfeed.git] / app / webhooks.py
1 """
2 This is the webhook server that interfaces with Google's WebSub (formerly pubsubhubbub) server. This is its own server, so it can live on a different host than the frontend.
3 """
4
5 #TODO: fold update-websub.py into this?
6
7 import time
8 import sqlite3
9 from flask import Flask, request
10 from urllib.parse import parse_qs, urlparse
11
12 from common import *
13
14 app = Flask(__name__)
15
16 @app.route('/websub/v1/<int:timestamp>/<nonce>/<subject>/<sig>', methods=["GET"])
17 def websub(timestamp, nonce, subject, sig):
18 mode = request.args.get('hub.mode', '')
19 topic = request.args.get('hub.topic', '')
20 challenge = request.args.get('hub.challenge', '')
21 until = int(request.args.get('hub.lease_seconds', '0'))
22
23 # extract the first query parameter, which is either channel_id or playlist_id:
24 channel_id = next(iter(parse_qs(urlparse(topic).query).values()), [None])[0]
25
26 if not channel_id:
27 return '', 400
28
29 if time.time() - timestamp > int(cf['websub']['lease']):
30 return '', 400
31 # TODO: implement hmac check: return '',400 unless hmac_sha1_hex("$timestamp/$nonce", $HMACKEY) eq $sig
32
33 if mode != "subscribe":
34 return '', 200
35 # Note: channels are not purged from the websub dbtable.
36
37 with sqlite3.connect(cf['global']['database']) as conn:
38 c = conn.cursor()
39 c.execute("""
40 INSERT OR REPLACE INTO websub (channel_id, subscribed_until)
41 VALUES (?, datetime(?, 'unixepoch'))
42 """, (channel_id, time.time()+until))
43 return challenge, 200
44
45 @app.route('/websub/v1/<int:timestamp>/<nonce>/<subject>/<sig>', methods=["POST"])
46 def websub_post(timestamp, nonce, subject, sig):
47 # TODO: implement hmac check: return '',400 unless hmac_sha1_hex("$timestamp/$nonce", $HMACKEY) eq $sig
48 # todo: # say 400 and exit unless hmac_sha1_hex($body, $HMACKEY) eq $ENV{X-Hub-Signature }
49
50 with sqlite3.connect(cf['global']['database']) as conn:
51 c = conn.cursor()
52 try:
53 update_channel(conn, request.data)
54 except:
55 with open('/tmp/websub-subscriptions.err', 'a') as f:
56 f.write(f"<!-- {time.ctime()} ({int(time.time())}) -->\n{xmlfeed}\n")
57 return '', 200
58
59 if __name__ == '__main__':
60 app.run(debug=True)
Imprint / Impressum