diff --git a/activitypub.py b/activitypub.py index 9c1a78a..d3ed328 100644 --- a/activitypub.py +++ b/activitypub.py @@ -559,7 +559,7 @@ def postprocess_as2(activity, orig_obj=None, wrap=True): if isinstance(to, dict): to = util.get_first(to, 'url') or to.get('id') if to: - activity.setdefault('tag', []).append({ + add(activity.setdefault('tag', []), { 'type': 'Mention', 'href': to, }) @@ -605,14 +605,23 @@ def postprocess_as2(activity, orig_obj=None, wrap=True): if imgs: atts.extend(img for img in imgs if img not in atts) - # cc target's author(s) and recipients + # cc target's author(s), recipients, mentions # https://www.w3.org/TR/activitystreams-vocabulary/#audienceTargeting # https://w3c.github.io/activitypub/#delivery + # https://docs.joinmastodon.org/spec/activitypub/#Mention + obj_or_activity.setdefault('cc', []) + + tags = util.get_list(activity, 'tag') + util.get_list(obj, 'tag') + for tag in tags: + href = tag.get('href') + if (href and tag.get('type') == 'Mention' + and not ActivityPub.is_blocklisted(href)): + add(obj_or_activity['cc'], href) + if orig_obj and type in as2.TYPE_TO_VERB: - recips = itertools.chain(*(util.get_list(orig_obj, field) for field in - ('actor', 'attributedTo', 'to', 'cc'))) - obj_or_activity['cc'] = sorted(util.dedupe_urls( - util.get_url(recip) or recip.get('id') for recip in recips)) + for field in 'actor', 'attributedTo', 'to', 'cc': + for recip in as1.get_objects(orig_obj, field): + add(obj_or_activity['cc'], util.get_url(recip) or recip.get('id')) # to public, since Mastodon interprets to public as public, cc public as unlisted: # https://socialhub.activitypub.rocks/t/visibility-to-cc-mapping/284 @@ -633,7 +642,7 @@ def postprocess_as2(activity, orig_obj=None, wrap=True): # # https://docs.joinmastodon.org/spec/activitypub/#properties-used # https://github.com/snarfed/bridgy-fed/issues/45 - for tag in util.get_list(activity, 'tag') + util.get_list(obj, 'tag'): + for tag in tags: name = tag.get('name') if name and tag.get('type', 'Tag') == 'Tag': tag['type'] = 'Hashtag' diff --git a/tests/test_activitypub.py b/tests/test_activitypub.py index 26c1ce9..f132c9f 100644 --- a/tests/test_activitypub.py +++ b/tests/test_activitypub.py @@ -1671,6 +1671,7 @@ class ActivityPubUtilsTest(TestCase): {'type': 'Mention', 'href': 'foo'}, ], 'to': ['https://www.w3.org/ns/activitystreams#Public'], + 'cc': ['foo'], }, postprocess_as2({ 'tag': [ {'name': 'bar', 'href': 'bar'}, @@ -1734,6 +1735,12 @@ class ActivityPubUtilsTest(TestCase): }], })['preferredUsername']) + def test_postprocess_as2_mentions_into_cc(self): + obj = copy.deepcopy(MENTION_OBJECT) + del obj['cc'] + self.assertEqual(['https://masto.foo/@other'], + postprocess_as2(obj)['cc']) + # TODO: make these generic and use Fake @patch('requests.get') def test_load_http(self, mock_get):