kopia lustrzana https://github.com/snarfed/bridgy-fed
rodzic
5485cbeece
commit
c54df36164
2
app.py
2
app.py
|
@ -6,7 +6,7 @@ registered.
|
|||
from flask_app import app
|
||||
|
||||
# import all modules to register their Flask handlers
|
||||
import activitypub, atproto, convert, follow, pages, redirect, superfeedr, ui, webfinger, web
|
||||
import activitypub, atproto, convert, follow, pages, redirect, ui, webfinger, web
|
||||
|
||||
import models
|
||||
models.reset_protocol_properties()
|
||||
|
|
|
@ -55,11 +55,6 @@ render
|
|||
.. automodule:: render
|
||||
:exclude-members: __eq__, __getnewargs__, __getstate__, __hash__, __new__, __repr__, __str__, __weakref__
|
||||
|
||||
superfeedr
|
||||
----------
|
||||
.. automodule:: superfeedr
|
||||
:exclude-members: __eq__, __getnewargs__, __getstate__, __hash__, __new__, __repr__, __str__, __weakref__
|
||||
|
||||
web
|
||||
---
|
||||
.. automodule:: web
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
"""Superfeedr callback handlers.
|
||||
|
||||
Not really sure what this will be yet.
|
||||
|
||||
* https://github.com/snarfed/bridgy-fed/issues/550
|
||||
* https://github.com/snarfed/bridgy-fed/issues/18#issuecomment-430731476
|
||||
* https://documentation.superfeedr.com/publishers.html
|
||||
"""
|
||||
import logging
|
||||
|
||||
from flask import request
|
||||
|
||||
from flask_app import app
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@app.route(r'/superfeedr/', methods=['GET', 'POST'])
|
||||
@app.route(r'/superfeedr/<path:_>', methods=['GET', 'POST'])
|
||||
def superfeedr(_=None):
|
||||
"""Superfeedr subscription callback handler.
|
||||
|
||||
https://documentation.superfeedr.com/publishers.html#subscription-callback
|
||||
"""
|
||||
logger.info(f'Got:\n{request.get_data(as_text=True)}')
|
||||
return '', 204
|
|
@ -4,7 +4,7 @@ from unittest.mock import patch
|
|||
|
||||
from flask import g, get_flashed_messages
|
||||
from google.cloud import ndb
|
||||
from granary import as1, as2, microformats2
|
||||
from granary import as1, as2, atom, microformats2
|
||||
from oauth_dropins.webutil import util
|
||||
from oauth_dropins.webutil import appengine_info
|
||||
from oauth_dropins.webutil.testutil import NOW, requests_response
|
||||
|
@ -1735,6 +1735,38 @@ class WebTest(TestCase):
|
|||
"WARNING:models:actor https://user.com/ isn't https://user.com/like's author or actor ['https://eve.com/']",
|
||||
logs.output)
|
||||
|
||||
@patch('oauth_dropins.webutil.appengine_config.tasks_client.create_task')
|
||||
def test_superfeedr_make_task(self, mock_create_task, *_):
|
||||
common.RUN_TASKS_INLINE = False
|
||||
|
||||
got = self.post('/superfeedr/notify/user.com', data="""\
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<entry xmlns="http://www.w3.org/2005/Atom">
|
||||
<uri>https://user.com/post</uri>
|
||||
<content>I hereby ☕ post.</content>
|
||||
</entry>
|
||||
""", headers={'Content-Type': atom.CONTENT_TYPE})
|
||||
self.assertEqual(200, got.status_code)
|
||||
self.assert_task(mock_create_task, 'receive', '/queue/receive',
|
||||
obj=Object(id='https://user.com/post').key.urlsafe(),
|
||||
authed_as='user.com')
|
||||
|
||||
def test_superfeedr_no_user(self, *_):
|
||||
orig_count = Object.query().count()
|
||||
|
||||
got = self.post('/webmention', data={'source': 'https://nope.com/post'})
|
||||
self.assertEqual(400, got.status_code)
|
||||
self.assertEqual(orig_count, Object.query().count())
|
||||
|
||||
def test_superfeedr_no_id(self, *mocks):
|
||||
got = self.post('/superfeedr/notify/user.com', data="""\
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<entry xmlns="http://www.w3.org/2005/Atom">
|
||||
<content>I hereby ☕ post.</content>
|
||||
</entry>
|
||||
""", headers={'Content-Type': atom.CONTENT_TYPE})
|
||||
self.assertEqual(400, got.status_code)
|
||||
|
||||
def _test_verify(self, redirects, hcard, actor, redirects_error=None):
|
||||
self.user.has_redirects = False
|
||||
self.user.put()
|
||||
|
|
36
web.py
36
web.py
|
@ -9,7 +9,7 @@ from urllib.parse import quote, urlencode, urljoin, urlparse
|
|||
from flask import g, redirect, render_template, request
|
||||
from google.cloud import ndb
|
||||
from google.cloud.ndb import ComputedProperty
|
||||
from granary import as1, as2, microformats2
|
||||
from granary import as1, as2, atom, microformats2
|
||||
import mf2util
|
||||
from oauth_dropins.webutil import flask_util, util
|
||||
from oauth_dropins.webutil.appengine_config import tasks_client
|
||||
|
@ -581,6 +581,38 @@ def webmention_interactive():
|
|||
return redirect('/', code=302)
|
||||
|
||||
|
||||
# generate/check per-user token for auth?
|
||||
# or https://documentation.superfeedr.com/subscribers.html#http-authentication ?
|
||||
@app.post(f'/superfeedr/notify/<regex("{DOMAIN_RE}"):domain>')
|
||||
def superfeedr_notify(domain):
|
||||
"""Superfeedr notification handler.
|
||||
|
||||
https://documentation.superfeedr.com/publishers.html#subscription-callback
|
||||
"""
|
||||
logger.info(f'Got:\n{request.get_data(as_text=True)}')
|
||||
|
||||
type = request.headers.get('Content-Type', '').split(';')[0]
|
||||
if type != atom.CONTENT_TYPE.split(';')[0]:
|
||||
error(f'Expected Content-Type {atom.CONTENT_TYPE}, got {type}', status=406)
|
||||
|
||||
user = Web.get_by_id(domain)
|
||||
if not user:
|
||||
error(f'No user found for domain {domain}', status=304)
|
||||
|
||||
text = request.get_data(as_text=True)
|
||||
obj = Object(atom=text)
|
||||
logger.info(f'Converted to AS1: {json_dumps(obj.as1, indent=2)}')
|
||||
|
||||
id = obj.as1.get('id')
|
||||
if not id:
|
||||
return error('No id or URL!')
|
||||
|
||||
obj = Object.get_or_create(id=id, atom=text, source_protocol=Web.ABBREV)
|
||||
common.create_task(queue='receive', obj=obj.key.urlsafe(), authed_as=domain)
|
||||
|
||||
return 'OK'
|
||||
|
||||
|
||||
@app.post('/queue/webmention')
|
||||
@cloud_tasks_only
|
||||
def webmention_task():
|
||||
|
@ -593,9 +625,9 @@ def webmention_task():
|
|||
logger.info(f'webmention from {domain}')
|
||||
|
||||
user = Web.get_by_id(domain)
|
||||
logger.info(f'User: {user.key}')
|
||||
if not user:
|
||||
error(f'No user found for domain {domain}', status=304)
|
||||
logger.info(f'User: {user.key}')
|
||||
|
||||
# fetch source page
|
||||
try:
|
||||
|
|
Ładowanie…
Reference in New Issue