kopia lustrzana https://github.com/snarfed/bridgy-fed
handle wm => AP with targets that we've already federated wm => AP
fixes https://console.cloud.google.com/errors/detail/CMHpr9L3ooGKeQ;time=P30D?project=bridgy-federatedpull/459/head
rodzic
1a77a99e36
commit
20f86c7de3
|
@ -293,7 +293,8 @@ class Object(StringIdModel):
|
|||
# https://github.com/googleapis/python-ndb/issues/874
|
||||
as2 = JsonProperty() # only one of the rest will be populated...
|
||||
bsky = JsonProperty() # Bluesky / AT Protocol
|
||||
mf2 = JsonProperty() # HTML microformats2
|
||||
mf2 = JsonProperty() # HTML microformats2 item (ie _not_ the top level
|
||||
# parse object with items inside an 'items' field)
|
||||
our_as1 = JsonProperty() # AS1 for activities that we generate or modify ourselves
|
||||
|
||||
@ComputedJsonProperty
|
||||
|
|
|
@ -182,13 +182,13 @@ class WebmentionTest(testutil.TestCase):
|
|||
"""
|
||||
self.reply = requests_response(self.reply_html, content_type=CONTENT_TYPE_HTML,
|
||||
url='https://user.com/reply')
|
||||
self.reply_mf2 = util.parse_mf2(self.reply_html, url='https://user.com/reply')
|
||||
self.reply_as1 = microformats2.json_to_object(self.reply_mf2['items'][0])
|
||||
self.reply_mf2 = util.parse_mf2(self.reply_html)['items'][0]
|
||||
self.reply_as1 = microformats2.json_to_object(self.reply_mf2)
|
||||
|
||||
self.repost = requests_response(REPOST_HTML, content_type=CONTENT_TYPE_HTML,
|
||||
url='https://user.com/repost')
|
||||
self.repost_mf2 = util.parse_mf2(REPOST_HTML, url='https://user.com/repost')
|
||||
self.repost_as1 = microformats2.json_to_object(self.repost_mf2['items'][0])
|
||||
self.repost_mf2 = util.parse_mf2(REPOST_HTML)['items'][0]
|
||||
self.repost_as1 = microformats2.json_to_object(self.repost_mf2)
|
||||
|
||||
self.like_html = """\
|
||||
<html>
|
||||
|
@ -203,7 +203,7 @@ class WebmentionTest(testutil.TestCase):
|
|||
"""
|
||||
self.like = requests_response(self.like_html, content_type=CONTENT_TYPE_HTML,
|
||||
url='https://user.com/like')
|
||||
self.like_mf2 = util.parse_mf2(self.like_html, url='https://user.com/like')
|
||||
self.like_mf2 = util.parse_mf2(self.like_html)['items'][0]
|
||||
|
||||
self.actor = self.as2_resp({
|
||||
'objectType' : 'Person',
|
||||
|
@ -260,8 +260,8 @@ class WebmentionTest(testutil.TestCase):
|
|||
"""
|
||||
self.follow = requests_response(
|
||||
self.follow_html, content_type=CONTENT_TYPE_HTML)
|
||||
self.follow_mf2 = util.parse_mf2(self.follow_html, url='https://user.com/follow')
|
||||
self.follow_as1 = microformats2.json_to_object(self.follow_mf2['items'][0])
|
||||
self.follow_mf2 = util.parse_mf2(self.follow_html)['items'][0]
|
||||
self.follow_as1 = microformats2.json_to_object(self.follow_mf2)
|
||||
self.follow_as2 = {
|
||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||
'type': 'Follow',
|
||||
|
@ -290,9 +290,8 @@ class WebmentionTest(testutil.TestCase):
|
|||
self.follow_fragment = requests_response(
|
||||
self.follow_fragment_html, content_type=CONTENT_TYPE_HTML)
|
||||
self.follow_fragment_mf2 = util.parse_mf2(
|
||||
self.follow_fragment_html, url='https://user.com/follow', id='2')
|
||||
self.follow_fragment_as1 = microformats2.json_to_object(
|
||||
self.follow_fragment_mf2['items'][0])
|
||||
self.follow_fragment_html, id='2')['items'][0]
|
||||
self.follow_fragment_as1 = microformats2.json_to_object(self.follow_fragment_mf2)
|
||||
self.follow_fragment_as2 = copy.deepcopy(self.follow_as2)
|
||||
self.follow_fragment_as2.update({
|
||||
'id': 'http://localhost/r/https://user.com/follow#2',
|
||||
|
@ -311,10 +310,9 @@ class WebmentionTest(testutil.TestCase):
|
|||
</body>
|
||||
</html>
|
||||
"""
|
||||
self.create = requests_response(
|
||||
self.create_html, content_type=CONTENT_TYPE_HTML)
|
||||
self.create_mf2 = util.parse_mf2(self.create_html, url='https://user.com/create')
|
||||
self.create_as1 = microformats2.json_to_object(self.create_mf2['items'][0])
|
||||
self.create = requests_response(self.create_html, content_type=CONTENT_TYPE_HTML)
|
||||
self.create_mf2 = util.parse_mf2(self.create_html)['items'][0]
|
||||
self.create_as1 = microformats2.json_to_object(self.create_mf2)
|
||||
self.create_as2 = {
|
||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||
'type': 'Create',
|
||||
|
@ -556,11 +554,9 @@ class WebmentionTest(testutil.TestCase):
|
|||
|
||||
def test_update_reply(self, mock_get, mock_post):
|
||||
mf2 = {
|
||||
'items': [{
|
||||
'properties': {
|
||||
'content': ['other'],
|
||||
},
|
||||
}],
|
||||
'properties': {
|
||||
'content': ['other'],
|
||||
},
|
||||
}
|
||||
with app.test_request_context('/'):
|
||||
Object(id='https://user.com/reply', status='complete', mf2=mf2).put()
|
||||
|
@ -599,7 +595,7 @@ class WebmentionTest(testutil.TestCase):
|
|||
def test_skip_update_if_content_unchanged(self, mock_get, mock_post):
|
||||
"""https://github.com/snarfed/bridgy-fed/issues/78"""
|
||||
with app.test_request_context('/'):
|
||||
Object(id='https://user.com/reply', status='complete', mf2=self.reply_mf2['items'][0],
|
||||
Object(id='https://user.com/reply', status='complete', mf2=self.reply_mf2,
|
||||
delivered=[Target(uri='https://mas.to/inbox', protocol='activitypub')]
|
||||
).put()
|
||||
mock_get.side_effect = self.activitypub_gets
|
||||
|
@ -713,6 +709,27 @@ class WebmentionTest(testutil.TestCase):
|
|||
self.assertEqual(('https://mas.to/inbox',), args)
|
||||
self.assert_equals(self.as2_create, json_loads(kwargs['data']))
|
||||
|
||||
def test_like_stored_object_without_as2(self, mock_get, mock_post):
|
||||
Object(id='https://mas.to/toot', mf2=self.create_mf2).put()
|
||||
Object(id='https://user.com/', mf2=ACTOR_MF2).put()
|
||||
mock_get.side_effect = [
|
||||
self.like,
|
||||
]
|
||||
|
||||
got = self.client.post('/webmention', data={
|
||||
'source': 'https://user.com/like',
|
||||
'target': 'https://fed.brid.gy/',
|
||||
})
|
||||
self.assertEqual(200, got.status_code)
|
||||
|
||||
mock_get.assert_has_calls((
|
||||
self.req('https://user.com/like'),
|
||||
))
|
||||
mock_post.assert_not_called()
|
||||
|
||||
# TODO: we should eventually store this as ignored instead
|
||||
self.assertIsNone(Object.get_by_id('https://user.com/like'))
|
||||
|
||||
def test_create_default_url_to_wm_source(self, mock_get, mock_post):
|
||||
"""Source post has no u-url. AS2 id should default to webmention source."""
|
||||
missing_url = requests_response("""\
|
||||
|
@ -848,7 +865,7 @@ class WebmentionTest(testutil.TestCase):
|
|||
|
||||
with app.test_request_context('/'):
|
||||
Object(id='https://user.com/post', domains=['user.com'], status='in progress',
|
||||
mf2=self.create_mf2['items'][0],
|
||||
mf2=self.create_mf2,
|
||||
delivered=[Target(uri='https://skipped/inbox', protocol='activitypub')],
|
||||
undelivered=[Target(uri='https://shared/inbox', protocol='activitypub')],
|
||||
failed=[Target(uri='https://public/inbox', protocol='activitypub')],
|
||||
|
@ -890,8 +907,10 @@ class WebmentionTest(testutil.TestCase):
|
|||
mock_post.return_value = requests_response('abc xyz')
|
||||
|
||||
with app.test_request_context('/'):
|
||||
mf2 = copy.deepcopy(self.create_mf2)
|
||||
mf2['properties']['content'] = 'different'
|
||||
Object(id='https://user.com/post', domains=['user.com'], status='in progress',
|
||||
mf2={**self.create_mf2, 'content': 'different'},
|
||||
mf2=mf2,
|
||||
delivered=[Target(uri='https://delivered/inbox', protocol='activitypub')],
|
||||
undelivered=[Target(uri='https://shared/inbox', protocol='activitypub')],
|
||||
failed=[Target(uri='https://public/inbox', protocol='activitypub')],
|
||||
|
|
|
@ -107,12 +107,12 @@ class WebmentionView(View):
|
|||
error(f'Bad source URL: {source}: {e}')
|
||||
self.source_url = source_resp.url or source
|
||||
fragment = urllib.parse.urlparse(self.source_url).fragment
|
||||
self.source_mf2 = util.parse_mf2(source_resp, id=fragment)
|
||||
parsed_mf2 = util.parse_mf2(source_resp, id=fragment)
|
||||
|
||||
if fragment and self.source_mf2 is None:
|
||||
if fragment and parsed_mf2 is None:
|
||||
error(f'#{fragment} not found in {self.source_url}')
|
||||
|
||||
# logger.debug(f'Parsed mf2 for {source_resp.url} : {json_dumps(self.source_mf2 indent=2)}')
|
||||
# logger.debug(f'Parsed mf2 for {source_resp.url} : {json_dumps(parsed_mf2 indent=2)}')
|
||||
|
||||
# check for backlink for webmention spec and to confirm source's intent
|
||||
# to federate
|
||||
|
@ -123,7 +123,7 @@ class WebmentionView(View):
|
|||
error(f"Couldn't find link to {common.host_url().rstrip('/')}")
|
||||
|
||||
# convert source page to ActivityStreams
|
||||
self.source_mf2 = mf2util.find_first_entry(self.source_mf2, ['h-entry'])
|
||||
self.source_mf2 = mf2util.find_first_entry(parsed_mf2, ['h-entry'])
|
||||
if not self.source_mf2:
|
||||
error(f'No microformats2 found on {self.source_url}')
|
||||
|
||||
|
@ -338,7 +338,8 @@ class WebmentionView(View):
|
|||
# fetch target page as AS2 object
|
||||
try:
|
||||
# TODO: make this generic across protocols
|
||||
target_obj = activitypub.ActivityPub.get_object(target).as2
|
||||
target_stored = activitypub.ActivityPub.get_object(target)
|
||||
target_obj = target_stored.as2 or as2.from_as1(target_stored.as1)
|
||||
except (requests.HTTPError, BadGateway) as e:
|
||||
resp = getattr(e, 'requests_response', None)
|
||||
if resp and resp.ok:
|
||||
|
@ -363,7 +364,8 @@ class WebmentionView(View):
|
|||
if not inbox_url:
|
||||
# fetch actor as AS object
|
||||
# TODO: make this generic across protocols
|
||||
actor = activitypub.ActivityPub.get_object(actor).as2
|
||||
actor_obj = activitypub.ActivityPub.get_object(actor)
|
||||
actor = actor_obj.as2 or as2.from_as1(actor_obj.as1)
|
||||
inbox_url = actor.get('inbox')
|
||||
|
||||
if not inbox_url:
|
||||
|
|
Ładowanie…
Reference in New Issue