diff --git a/activitypub.py b/activitypub.py index e2babf3..e0fdecf 100644 --- a/activitypub.py +++ b/activitypub.py @@ -359,10 +359,11 @@ def postprocess_as2(activity, target=None, wrap=True): # activity objects (for Like, Announce, etc): prefer id over url obj = as1.get_object(activity) id = obj.get('id') - if not id: - obj['id'] = util.get_first(obj, 'url') or target_id - elif target_id and id != target_id: + if target_id and type in as2.TYPES_WITH_OBJECT: + # inline most objects as bare string ids, not composite objects, for interop activity['object'] = target_id + elif not id: + obj['id'] = util.get_first(obj, 'url') or target_id elif g.user.is_homepage(id): obj['id'] = g.user.actor_id() diff --git a/tests/test_webmention.py b/tests/test_webmention.py index c538606..b148312 100644 --- a/tests/test_webmention.py +++ b/tests/test_webmention.py @@ -124,9 +124,9 @@ REPOST_AS1_UNWRAPPED = { REPOST_HCITE_HTML = """\ - +reposted!
-

Reposted Mr. Foo:

+ Mr. Foo:

a post
Ms. ☕ Baz @@ -136,25 +136,6 @@ REPOST_HCITE_HTML = """\ """ REPOST_HCITE = requests_response(REPOST_HTML, content_type=CONTENT_TYPE_HTML, url='https://user.com/repost') -REPOST_HCITE_AS2 = { - '@context': 'https://www.w3.org/ns/activitystreams', - 'type': 'Announce', - 'id': 'http://localhost/r/https://user.com/repost', - 'url': 'http://localhost/r/https://user.com/repost', - 'object': { - 'type': 'Note', - 'id': 'https://mas.to/toot/id', - 'url': 'https://mas.to/toot/id', - 'attributedTo': [{ - 'type': 'Person', - 'url': 'https://mas.to/@foo', - 'name': 'Mr. Foo', - }], - 'to': [as2.PUBLIC_AUDIENCE], - }, - 'to': [as2.PUBLIC_AUDIENCE], - 'actor': 'http://localhost/user.com', -} WEBMENTION_REL_LINK = requests_response( '') @@ -687,7 +668,7 @@ class WebmentionTest(testutil.TestCase): self._test_announce(REPOST_HTML, REPOST_AS2, mock_get, mock_post) def test_announce_repost_composite_hcite(self, mock_get, mock_post): - self._test_announce(REPOST_HCITE_HTML, REPOST_HCITE_AS2, mock_get, mock_post) + self._test_announce(REPOST_HCITE_HTML, REPOST_AS2, mock_get, mock_post) def _test_announce(self, html, expected_as2, mock_get, mock_post): self.make_followers() @@ -1184,7 +1165,8 @@ class WebmentionTest(testutil.TestCase): 'source': 'https://user.com/repost', 'target': 'https://fed.brid.gy/', }) - self.assertEqual(304, got.status_code) + self.assertEqual(200, got.status_code) + mock_post.assert_not_called() def test_update_profile(self, mock_get, mock_post): mock_get.side_effect = [ACTOR] diff --git a/webmention.py b/webmention.py index 6e1b9b5..77a5eb2 100644 --- a/webmention.py +++ b/webmention.py @@ -383,27 +383,7 @@ def _activitypub_targets(obj): targets = common.remove_blocklisted(targets) inboxes_to_targets = {} - if not targets or verb == 'share': - logger.info('Delivering to followers') - inboxes = set() - domain = g.user.key.id() - for follower in Follower.query().filter( - Follower.key > Key('Follower', domain + ' '), - Follower.key < Key('Follower', domain + CHAR_AFTER_SPACE)): - if follower.status != 'inactive' and follower.last_follow: - actor = follower.last_follow.get('actor') - if actor and isinstance(actor, dict): - inboxes.add(actor.get('endpoints', {}).get('sharedInbox') or - actor.get('publicInbox') or - actor.get('inbox')) - - inboxes_to_targets = {inbox: None for inbox in inboxes} - if verb != 'share': - return inboxes_to_targets - - if not targets: - error(f"Silo responses are not yet supported.", status=304) - + target_obj = None for target in targets: # fetch target page as AS2 object try: @@ -446,4 +426,20 @@ def _activitypub_targets(obj): inbox_url = urllib.parse.urljoin(target, inbox_url) inboxes_to_targets[inbox_url] = target_obj + if not targets or verb == 'share': + logger.info('Delivering to followers') + domain = g.user.key.id() + for follower in Follower.query().filter( + Follower.key > Key('Follower', domain + ' '), + Follower.key < Key('Follower', domain + CHAR_AFTER_SPACE)): + if follower.status != 'inactive' and follower.last_follow: + actor = follower.last_follow.get('actor') + if actor and isinstance(actor, dict): + inbox = (actor.get('endpoints', {}).get('sharedInbox') or + actor.get('publicInbox') or + actor.get('inbox')) + # HACK: use last target object from above for reposts, which + # has its resolved id + inboxes_to_targets[inbox] = (target_obj if verb == 'share' else None) + return inboxes_to_targets