diff --git a/tests/test_web.py b/tests/test_web.py
index 22c96389..0bd153e0 100644
--- a/tests/test_web.py
+++ b/tests/test_web.py
@@ -23,7 +23,7 @@
from flask_app import app
from models import Follower, Object
import web
-from web import SUPERFEEDR_PUSH_API, TASKS_LOCATION, Web
+from web import TASKS_LOCATION, Web
from . import test_activitypub
from .testutil import Fake, TestCase
@@ -1962,129 +1962,6 @@ def test_poll_feed_rss(self, mock_create_task, mock_get, _):
self.assert_task(mock_create_task, 'poll-feed', '/queue/poll-feed',
domain='user.com', eta_seconds=expected_eta)
- def test_superfeedr_notify_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_notify_no_id(self, *mocks):
- got = self.post('/superfeedr/notify/user.com', data="""\
-
-
-I hereby ☕ post.
-
-""", headers={'Content-Type': atom.CONTENT_TYPE})
- self.assertEqual(400, got.status_code)
-
- @patch('oauth_dropins.webutil.appengine_config.tasks_client.create_task')
- def test_maybe_superfeedr_subscribe(self, mock_create_task, mock_get, mock_post):
- common.RUN_TASKS_INLINE = False
-
- entries = ["""\
-
- http://my/site
- Mr. Bob
-
- domain.tld:09/05/03-1
- http://domain.tld/entry/1
- 2013-04-21T14:00:40+02:00
- 2013-04-21T14:00:40+02:00
-
Entry published on hour ago
- Entry published on hour ago when it was shiny outside, but now it's raining
- Entry published on hour ago...
-""", """\
-
- http://eve/
-
- http://domain.tld/entry/2
- Second post
- Something else
-"""]
-
- self.assertIsNone(self.user.superfeedr_subscribed)
- self.user.obj.mf2 = ACTOR_MF2_REL_FEED_URL
- self.user.has_redirects = False
-
- # https://documentation.superfeedr.com/schema.html#entries
- mock_post.return_value = requests_response(f"""\
-
-
-
-{entries[0]}
-
-
-{entries[1]}
-
-
-""", content_type=atom.CONTENT_TYPE)
-
- web.maybe_superfeedr_subscribe(self.user)
- self.assert_req(mock_post, SUPERFEEDR_PUSH_API, data={
- 'hub.mode': 'subscribe',
- 'hub.topic': 'https://foo/atom',
- 'hub.callback': 'http://localhost/superfeedr/notify/user.com',
- 'format': 'atom',
- 'retrieve': 'true',
- }, auth=ANY)
- self.assertEqual(NOW, self.user.key.get().superfeedr_subscribed)
- self.assertEqual('https://foo/atom',
- self.user.key.get().superfeedr_subscribed_feed)
-
- obj = Object.get_by_id('http://domain.tld/entry/1')
- self.assertIn(entries[0], obj.atom)
- self.assert_task(mock_create_task, 'receive', '/queue/receive',
- obj=obj.key.urlsafe(), authed_as='user.com')
-
- obj = Object.get_by_id('http://domain.tld/entry/2')
- self.assertIn(entries[1], obj.atom)
- self.assert_task(mock_create_task, 'receive', '/queue/receive',
- obj=obj.key.urlsafe(), authed_as='user.com')
-
- def test_maybe_superfeedr_subscribe_no_feed(self, mock_get, mock_post):
- self.user.obj.mf2 = ACTOR_MF2 # no rel-urls
- web.maybe_superfeedr_subscribe(self.user)
- self.assertIsNone(self.user.key.get().superfeedr_subscribed)
-
- def test_maybe_superfeedr_subscribe_already_subscribed(self, mock_get, mock_post):
- self.user.superfeedr_subscribed = NOW
- self.user.put()
- web.maybe_superfeedr_subscribe(self.user)
- # should be a noop
-
- def test_maybe_superfeedr_unsubscribe(self, mock_get, mock_post):
- appengine_info.LOCAL_SERVER = False
-
- self.user.superfeedr_subscribed = NOW
- self.user.superfeedr_subscribed_feed = 'http://feed'
- self.user.put()
-
- mock_post.return_value = requests_response('OK')
-
- web.maybe_superfeedr_unsubscribe(self.user)
- self.assert_req(mock_post, SUPERFEEDR_PUSH_API, data={
- 'hub.mode': 'unsubscribe',
- 'hub.topic': 'http://feed',
- 'hub.callback': 'http://localhost/superfeedr/notify/user.com',
- }, auth=ANY)
-
- def test_maybe_superfeedr_unsubscribe_not_subscribed(self, mock_get, mock_post):
- appengine_info.LOCAL_SERVER = False
-
- web.maybe_superfeedr_unsubscribe(self.user)
- mock_post.assert_not_called()
-
- def test_maybe_superfeedr_unsubscribe_last_webmention_later(self, _, mock_post):
- appengine_info.LOCAL_SERVER = False
-
- self.user.superfeedr_subscribed = NOW
- self.user.last_webmention_in = NOW + timedelta(days=1)
- self.user.put()
-
- web.maybe_superfeedr_unsubscribe(self.user)
- mock_post.assert_not_called()
-
def _test_verify(self, redirects, hcard, actor, redirects_error=None):
self.user.has_redirects = False
self.user.put()
diff --git a/web.py b/web.py
index bff7bbd4..09f5f0d1 100644
--- a/web.py
+++ b/web.py
@@ -56,14 +56,10 @@
'yml',
))
-SUPERFEEDR_PUSH_API = 'https://push.superfeedr.com'
-SUPERFEEDR_USERNAME = util.read('superfeedr_username')
-SUPERFEEDR_TOKEN = util.read('superfeedr_token')
FEED_TYPES = {
atom.CONTENT_TYPE.split(';')[0]: 'atom',
rss.CONTENT_TYPE.split(';')[0]: 'rss',
}
-
MIN_FEED_POLL_PERIOD = timedelta(hours=2)
MAX_FEED_POLL_PERIOD = timedelta(weeks=1)
@@ -626,71 +622,6 @@ def maybe_superfeedr_subscribe(user):
logger.info(f"User {user.key.id()} has no mf2, can't subscribe via Superfeedr")
return
- # discover feed
- for url, info in user.obj.mf2.get('rel-urls', {}).items():
- if ('alternate' in info.get('rels', [])
- and info.get('type', '').split(';')[0] in FEED_TYPES.keys()):
- break
- else:
- logger.info(f"User {user.key.id()} has no feed URL, can't subscribe")
- return
-
- # subscribe
- logger.info(f'Subscribing to {url} via Superfeedr')
- if appengine_info.LOCAL_SERVER:
- logger.info(f"Skipping since we're local")
- return
-
- auth = HTTPBasicAuth(SUPERFEEDR_USERNAME, SUPERFEEDR_TOKEN)
- resp = util.requests_post(SUPERFEEDR_PUSH_API, auth=auth, data={
- 'hub.mode': 'subscribe',
- 'hub.topic': url,
- 'hub.callback': common.host_url(f'/superfeedr/notify/{user.key.id()}'),
- # TODO
- # 'hub.secret': 'xxx',
- 'format': 'atom',
- 'retrieve': 'true',
- })
- try:
- resp.raise_for_status()
- except BaseException as e:
- util.interpret_http_exception(e)
- return
-
- user.superfeedr_subscribed = util.now()
- user.superfeedr_subscribed_feed = url
- user.put()
-
- # handle feed entries (posts)
- if (resp.headers.get('Content-Type', '').split(';')[0] ==
- atom.CONTENT_TYPE.split(';')[0]):
- return _superfeedr_notify(resp.text, user=user)
-
-
-def maybe_superfeedr_unsubscribe(user):
- """Subscribes to a user's Atom or RSS feed in Superfeedr.
-
- Args:
- user (Web)
- """
- if (not user.superfeedr_subscribed
- or not user.superfeedr_subscribed_feed
- or (user.last_webmention_in
- and user.last_webmention_in > user.superfeedr_subscribed)
- or appengine_info.LOCAL_SERVER):
- return
-
- # unsubscribe
- logger.info(f'Unsubscribing from Superfeedr for {user.superfeedr_subscribed_feed}')
-
- auth = HTTPBasicAuth(SUPERFEEDR_USERNAME, SUPERFEEDR_TOKEN)
- resp = util.requests_post(SUPERFEEDR_PUSH_API, auth=auth, data={
- 'hub.mode': 'unsubscribe',
- 'hub.topic': user.superfeedr_subscribed_feed,
- 'hub.callback': common.host_url(f'/superfeedr/notify/{user.key.id()}'),
- })
- resp.raise_for_status()
-
@app.post(f'/queue/poll-feed')
def poll_feed_task():
@@ -765,48 +696,6 @@ def poll_feed_task():
return 'OK'
-# generate/check per-user token for auth?
-# or https://documentation.superfeedr.com/subscribers.html#http-authentication ?
-@app.post(f'/superfeedr/notify/')
-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)
-
- return _superfeedr_notify(request.get_data(as_text=True), user=user)
-
-
-def _superfeedr_notify(doc, user):
- """Creates :class:`Object`s and ``receive`` tasks for an Atom feed or entry.
-
- Args:
- doc (str): Atom document
- user (Web): user this feed came from
- """
- for entry in atom.extract_entries(doc):
- obj_as1 = Object(atom=entry).as1
- 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=entry, source_protocol=Web.ABBREV)
- common.create_task(queue='receive', obj=obj.key.urlsafe(),
- authed_as=user.key.id())
-
- return 'OK'
-
-
@app.post('/queue/webmention')
@cloud_tasks_only
def webmention_task():