Web: start on Superfeedr subscribe

for #550
pull/746/head
Ryan Barrett 2023-12-04 10:28:45 -08:00
rodzic 68ba590ae2
commit b113521f94
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 6BE31FDF4776E9D4
3 zmienionych plików z 46 dodań i 2 usunięć

2
.gitignore vendored
Wyświetl plik

@ -10,4 +10,6 @@ flask_secret_key
opt_outs.txt opt_outs.txt
private_notes private_notes
service_account_creds.json service_account_creds.json
superfeedr_token
superfeedr_username
TAGS TAGS

Wyświetl plik

@ -1,6 +1,6 @@
"""Unit tests for webmention.py.""" """Unit tests for webmention.py."""
import copy import copy
from unittest.mock import patch from unittest.mock import ANY, patch
from flask import g, get_flashed_messages from flask import g, get_flashed_messages
from google.cloud import ndb from google.cloud import ndb
@ -20,7 +20,8 @@ import common
from common import CONTENT_TYPE_HTML from common import CONTENT_TYPE_HTML
from flask_app import app from flask_app import app
from models import Follower, Object from models import Follower, Object
from web import TASKS_LOCATION, Web import web
from web import SUPERFEEDR_PUSH_API, TASKS_LOCATION, Web
from . import test_activitypub from . import test_activitypub
from .testutil import Fake, TestCase from .testutil import Fake, TestCase
@ -1769,6 +1770,17 @@ class WebTest(TestCase):
""", headers={'Content-Type': atom.CONTENT_TYPE}) """, headers={'Content-Type': atom.CONTENT_TYPE})
self.assertEqual(400, got.status_code) self.assertEqual(400, got.status_code)
@patch('oauth_dropins.webutil.appengine_info.LOCAL_SERVER', False)
def test_superfeedr_subscribe(self, mock_get, mock_post):
web.superfeedr_subscribe(self.user)
self.assert_req(mock_post, SUPERFEEDR_PUSH_API, data={
'hub.mode': 'subscribe',
'hub.topic': 'https://user.com/feed',
'hub.callback': 'http://localhost/superfeedr/notify/user.com',
'format': 'atom',
'retrieve': 'true',
}, auth=ANY)
def _test_verify(self, redirects, hcard, actor, redirects_error=None): def _test_verify(self, redirects, hcard, actor, redirects_error=None):
self.user.has_redirects = False self.user.has_redirects = False
self.user.put() self.user.put()

30
web.py
Wyświetl plik

@ -18,6 +18,7 @@ from oauth_dropins.webutil.flask_util import cloud_tasks_only, error, flash
from oauth_dropins.webutil.util import json_dumps, json_loads from oauth_dropins.webutil.util import json_dumps, json_loads
from oauth_dropins.webutil import webmention from oauth_dropins.webutil import webmention
from requests import HTTPError, RequestException from requests import HTTPError, RequestException
from requests.auth import HTTPBasicAuth
from werkzeug.exceptions import BadGateway, BadRequest, HTTPException, NotFound from werkzeug.exceptions import BadGateway, BadRequest, HTTPException, NotFound
import common import common
@ -54,6 +55,10 @@ NON_TLDS = frozenset((
'yml', 'yml',
)) ))
SUPERFEEDR_PUSH_API = 'https://push.superfeedr.com'
SUPERFEEDR_USERNAME = util.read('superfeedr_username')
SUPERFEEDR_TOKEN = util.read('superfeedr_token')
def is_valid_domain(domain): def is_valid_domain(domain):
"""Returns True if this is a valid domain we can use, False otherwise. """Returns True if this is a valid domain we can use, False otherwise.
@ -586,6 +591,31 @@ def webmention_interactive():
return redirect('/', code=302) return redirect('/', code=302)
def superfeedr_subscribe(user):
"""Subscribes to a user's Atom or RSS feed in Superfeedr.
Args:
user (Web)
"""
logger.info(f'Subscribing to {user.key.id()} 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': f'{user.web_url()}feed',
'hub.callback': common.host_url(f'/superfeedr/notify/{user.key.id()}'),
# TODO
# 'hub.secret': 'xxx',
'format': 'atom',
'retrieve': 'true',
})
resp.raise_for_status()
return resp
# generate/check per-user token for auth? # generate/check per-user token for auth?
# or https://documentation.superfeedr.com/subscribers.html#http-authentication ? # or https://documentation.superfeedr.com/subscribers.html#http-authentication ?
@app.post(f'/superfeedr/notify/<regex("{DOMAIN_RE}"):domain>') @app.post(f'/superfeedr/notify/<regex("{DOMAIN_RE}"):domain>')