]>
git.gir.st - subscriptionfeed.git/blob - app/webhooks/__init__.py
2 This is the webhook server that interfaces with Google's WebSub (formerly
3 pubsubhubbub) server. This can be run either as a module on the main frontend,
4 or as its own server, so it can live on a different host than the frontend.
9 from flask
import Flask
, Blueprint
, request
10 from urllib
.parse
import parse_qs
, urlparse
12 from ..common
.common
import *
14 frontend
= Blueprint('webhooks', __name__
)
18 app
.register_blueprint(frontend
)
21 @frontend.route('/websub')
23 return '', 204 # No Content
25 @frontend.route('/websub/v1/<int:timestamp>/<nonce>/<subject>/<sig>', methods
=["GET"])
26 def websub(timestamp
, nonce
, subject
, sig
):
27 hmackey
= cf
['websub']['hmac_key']
28 mode
= request
.args
.get('hub.mode', '')
29 topic
= request
.args
.get('hub.topic', '')
30 challenge
= request
.args
.get('hub.challenge', '')
31 until
= int(request
.args
.get('hub.lease_seconds', '0'))
33 if sig
!= websub_url_hmac(hmackey
, subject
, timestamp
, nonce
):
36 if time
.time() - timestamp
> int(cf
['websub']['lease']):
39 if mode
!= "subscribe":
41 # Note: channels are not purged from the websub dbtable.
43 with sqlite3
.connect(cf
['global']['database']) as conn
:
46 INSERT OR REPLACE INTO websub (channel_id, subscribed_until)
47 VALUES (?, datetime(?, 'unixepoch'))
48 """, (subject
, time
.time()+until
))
51 @frontend.route('/websub/v1/<int:timestamp>/<nonce>/<subject>/<sig>', methods
=["POST"])
52 def websub_post(timestamp
, nonce
, subject
, sig
):
53 lease
= cf
['websub']['lease']
54 hmackey
= cf
['websub']['hmac_key']
55 hub_signature
= request
.headers
.get('X-Hub-Signature').replace("sha1=", "")
57 if sig
!= websub_url_hmac(hmackey
, subject
, timestamp
, nonce
):
59 if hub_signature
!= websub_body_hmac(hmackey
, request
.data
):
62 with sqlite3
.connect(cf
['global']['database']) as conn
:
65 update_channel(conn
, request
.data
, from_webhook
=True)
66 except Exception as e
:
67 with
open('/tmp/websub-subscriptions.err', 'ab') as f
:
68 f
.write(f
"<!-- {time.ctime()} ({int(time.time())}) -->\n".encode('ascii'))
69 f
.write(request
.data
+ b
"\n")
73 if __name__
== '__main__':