kopia lustrzana https://github.com/snarfed/bridgy-fed
activitypub: fetch and include source actor if necessary
e.g. for likes and reposts, so that we can render them in our proxy page.pull/27/head
rodzic
269602d36b
commit
f2fa44bfff
|
@ -68,6 +68,8 @@ class InboxHandler(webapp2.RequestHandler):
|
|||
|
||||
def post(self, domain):
|
||||
logging.info('Got: %s', self.request.body)
|
||||
|
||||
# parse and validate AS2 activity
|
||||
try:
|
||||
activity = json.loads(self.request.body)
|
||||
assert activity
|
||||
|
@ -82,6 +84,7 @@ class InboxHandler(webapp2.RequestHandler):
|
|||
|
||||
# TODO: verify signature if there is one
|
||||
|
||||
# extract source and targets
|
||||
source = activity.get('url') or activity.get('id')
|
||||
obj = activity.get('object')
|
||||
obj_url = util.get_url(obj)
|
||||
|
@ -90,7 +93,7 @@ class InboxHandler(webapp2.RequestHandler):
|
|||
if isinstance(obj, dict):
|
||||
if not source:
|
||||
source = obj_url or obj.get('id')
|
||||
targets |= util.get_list(obj, 'inReplyTo')
|
||||
targets |= set(util.get_list(obj, 'inReplyTo'))
|
||||
|
||||
if not source:
|
||||
self.abort(400, "Couldn't find source URL or id")
|
||||
|
@ -99,14 +102,22 @@ class InboxHandler(webapp2.RequestHandler):
|
|||
if not targets:
|
||||
self.abort(400, "Couldn't find target URL (inReplyTo or object)")
|
||||
|
||||
# fetch actor if necessary so we have name, profile photo, etc
|
||||
if type in ('Like', 'Announce'):
|
||||
actor = activity.get('actor')
|
||||
if actor:
|
||||
activity['actor'] = common.requests_get(
|
||||
actor, parse_json=True, headers=CONNEG_HEADER)
|
||||
|
||||
# send webmentions to each target
|
||||
errors = []
|
||||
for target in targets:
|
||||
if not target:
|
||||
continue
|
||||
|
||||
response = Response.get_or_create(
|
||||
source=source, target=target, direction='in', protocol='activitypub',
|
||||
source_as2=json.dumps(activity))
|
||||
response = Response(source=source, target=target, protocol='activitypub',
|
||||
direction='in', source_as2=json.dumps(activity))
|
||||
response.put()
|
||||
|
||||
wm_source = (response.proxy_url() if type in ('Like', 'Announce')
|
||||
else source)
|
||||
|
|
|
@ -8,7 +8,7 @@ import copy
|
|||
import json
|
||||
import urllib
|
||||
|
||||
import mock
|
||||
from mock import call, patch
|
||||
from oauth_dropins.webutil import util
|
||||
from oauth_dropins.webutil.testutil import requests_response
|
||||
import requests
|
||||
|
@ -20,8 +20,8 @@ from models import MagicKey, Response
|
|||
import testutil
|
||||
|
||||
|
||||
@mock.patch('requests.post')
|
||||
@mock.patch('requests.get')
|
||||
@patch('requests.post')
|
||||
@patch('requests.get')
|
||||
class ActivityPubTest(testutil.TestCase):
|
||||
|
||||
def test_actor_handler(self, mock_get, _):
|
||||
|
@ -101,8 +101,21 @@ class ActivityPubTest(testutil.TestCase):
|
|||
self.assertEqual(as2_note, json.loads(resp.source_as2))
|
||||
|
||||
def test_inbox_like_proxy_url(self, mock_get, mock_post):
|
||||
mock_get.return_value = requests_response(
|
||||
'<html><head><link rel="webmention" href="/webmention"></html>')
|
||||
actor = {
|
||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||
'id': 'http://orig/actor',
|
||||
'type': 'Person',
|
||||
'name': 'Ms. Actor',
|
||||
'preferredUsername': 'msactor',
|
||||
'image': {'type': 'Image', 'url': 'http://orig/pic.jpg'},
|
||||
}
|
||||
mock_get.side_effect = [
|
||||
# source actor
|
||||
requests_response(actor),
|
||||
# target post webmention discovery
|
||||
requests_response(
|
||||
'<html><head><link rel="webmention" href="/webmention"></html>'),
|
||||
]
|
||||
mock_post.return_value = requests_response()
|
||||
|
||||
# based on example Mastodon like:
|
||||
|
@ -113,14 +126,20 @@ class ActivityPubTest(testutil.TestCase):
|
|||
'id': 'http://this/like#ok',
|
||||
'type': 'Like',
|
||||
'object': 'http://orig/post',
|
||||
'actor': 'http://this/author',
|
||||
'actor': 'http://orig/actor',
|
||||
}
|
||||
|
||||
got = app.get_response('/foo.com/inbox', method='POST',
|
||||
body=json.dumps(as2_like))
|
||||
self.assertEquals(200, got.status_int)
|
||||
mock_get.assert_called_once_with(
|
||||
'http://orig/post', headers=common.HEADERS, verify=False)
|
||||
|
||||
as2_headers = copy.deepcopy(common.HEADERS)
|
||||
as2_headers.update(activitypub.CONNEG_HEADER)
|
||||
print mock_get.call_args_list
|
||||
mock_get.assert_has_calls((
|
||||
call('http://orig/actor', headers=as2_headers, timeout=15),
|
||||
call('http://orig/post', headers=common.HEADERS, verify=False),
|
||||
))
|
||||
|
||||
args, kwargs = mock_post.call_args
|
||||
self.assertEquals(('http://orig/webmention',), args)
|
||||
|
@ -134,4 +153,5 @@ class ActivityPubTest(testutil.TestCase):
|
|||
self.assertEqual('in', resp.direction)
|
||||
self.assertEqual('activitypub', resp.protocol)
|
||||
self.assertEqual('complete', resp.status)
|
||||
as2_like['actor'] = actor
|
||||
self.assertEqual(as2_like, json.loads(resp.source_as2))
|
||||
|
|
Ładowanie…
Reference in New Issue