diff --git a/activitypub.py b/activitypub.py index 26b70e45..27a347e5 100644 --- a/activitypub.py +++ b/activitypub.py @@ -774,11 +774,15 @@ def postprocess_as2(activity, orig_obj=None, wrap=True): obj_or_activity['attachment'] = [a for a in atts if a.get('type') != 'Link'] link_atts = [a for a in atts if a.get('type') == 'Link'] + content = obj_or_activity.get('content', '') for link in link_atts: for url in util.get_list(link, 'href'): - if obj_or_activity.setdefault('content', ''): - obj_or_activity['content'] += '

' - obj_or_activity['content'] += util.pretty_link(url, text=link.get('name')) + if content: + content += '

' + content += util.pretty_link(url, text=link.get('name')) + + if content: + as2.set_content(obj_or_activity, content) # copy image(s) into attachment(s). may be Mastodon-specific. # https://github.com/snarfed/bridgy-fed/issues/33#issuecomment-440965618 @@ -863,17 +867,14 @@ def postprocess_as2(activity, orig_obj=None, wrap=True): if content := obj_or_activity.get('content'): # language, in contentMap # https://github.com/snarfed/bridgy-fed/issues/681 - content_map = obj_or_activity.setdefault('contentMap', {'en': content}) + obj_or_activity.setdefault('contentMap', {'en': content}) # wrap in

. some fediverse servers (eg Mastodon) have a white-space: # pre-wrap style that applies to p inside content. this preserves # meaningful whitespace in plain text content. # https://github.com/snarfed/bridgy-fed/issues/990 if not content.startswith('

'): - obj_or_activity['content'] = f'

{content}

' - for lang, val in content_map.items(): - if val == content: - content_map[lang] = obj_or_activity['content'] + as2.set_content(obj_or_activity, f'

{content}

') activity.pop('content_is_html', None) return util.trim_nulls(activity) diff --git a/tests/test_integrations.py b/tests/test_integrations.py index 8554dc87..39c46205 100644 --- a/tests/test_integrations.py +++ b/tests/test_integrations.py @@ -997,30 +997,116 @@ def test_atproto_convert_hashtag_to_activitypub_preserves_bsky_app_link(self): }], }, ActivityPub.convert(obj), ignore=['@context', 'attributedTo', 'to']) - def test_atproto_convert_link_to_activitypub_contentMap(self): + def test_convert_with_html_content_from_atproto_to_activitypub(self): obj = Object(id='at://xyz', source_protocol='atproto', bsky={ '$type': 'app.bsky.feed.post', - 'text': 'foo bar', + 'text': '#foo bar @baz', 'langs': ['en'], 'facets': [{ + '$type': 'app.bsky.richtext.facet', + 'features': [{ + '$type': 'app.bsky.richtext.facet#tag', + 'tag': 'foo', + }], + 'index': { + 'byteStart': 0, + 'byteEnd': 4, + }, + }, { '$type': 'app.bsky.richtext.facet', 'features': [{ '$type': 'app.bsky.richtext.facet#link', 'uri': 'http://bar', }], 'index': { - 'byteStart': 4, - 'byteEnd': 7, + 'byteStart': 5, + 'byteEnd': 8, + }, + }, { + '$type': 'app.bsky.richtext.facet', + 'features': [{ + '$type': 'app.bsky.richtext.facet#mention', + 'did': 'did:plc:baz', + }], + 'index': { + 'byteStart': 9, + 'byteEnd': 13, }, }], }) - self.assert_equals({ + + expected = { 'type': 'Note', 'id': 'https://bsky.brid.gy/convert/ap/at://xyz', 'url': 'http://localhost/r/https://bsky.app/profile/xyz', - 'content': '

foo bar

', + 'attributedTo': 'xyz', + 'content': '

#foo bar @baz

', 'contentMap': { - 'en': '

foo bar

', + 'en': '

#foo bar @baz

', }, - 'tag': [{'name': 'bar', 'type': 'Article', 'url': 'http://bar'}], - }, ActivityPub.convert(obj), ignore=['@context', 'attributedTo', 'to']) + 'tag': [{ + 'type': 'Hashtag', + 'name': '#foo', + 'href': 'https://bsky.app/search?q=%23foo', + }, { + 'type': 'Article', + 'name': 'bar', + 'url': 'http://bar', + }, { + 'type': 'Mention', + 'name': '@baz', + 'href': 'https://bsky.brid.gy/ap/https://bsky.app/profile/did:plc:baz', + }], + } + self.assert_equals(expected, ActivityPub.convert(obj), + ignore=['@context', 'to']) + + def test_convert_quote_with_html_content_from_atproto_to_activitypub(self): + obj = Object(id='at://xyz', source_protocol='atproto', bsky={ + '$type': 'app.bsky.feed.post', + 'text': "a @b c", + 'langs': ['en'], + 'embed': { + '$type': 'app.bsky.embed.record', + 'record': { + 'cid': 'bafyfoo', + 'uri': 'at://did:plc:abc/app.bsky.feed.post/123', + }, + }, + 'facets': [{ + '$type': 'app.bsky.richtext.facet', + 'features': [{ + '$type': 'app.bsky.richtext.facet#mention', + 'did': 'did:plc:def', + }], + 'index': { + 'byteStart': 2, + 'byteEnd': 4, + }, + }], + }) + + expected = { + 'type': 'Note', + 'id': 'https://bsky.brid.gy/convert/ap/at://xyz', + 'url': 'http://localhost/r/https://bsky.app/profile/xyz', + 'attributedTo': 'xyz', + 'content': '

a @b c

RE: https://bsky.app/profile/did:plc:abc/post/123

', + 'contentMap': { + 'en': '

a @b c

RE: https://bsky.app/profile/did:plc:abc/post/123

', + }, + 'quoteUrl': 'https://bsky.brid.gy/convert/ap/at://did:plc:abc/app.bsky.feed.post/123', + '_misskey_quote': 'https://bsky.brid.gy/convert/ap/at://did:plc:abc/app.bsky.feed.post/123', + 'tag': [{ + 'type': 'Mention', + 'name': '@b', + 'href': 'https://bsky.brid.gy/ap/https://bsky.app/profile/did:plc:def', + }, { + 'type': 'Link', + 'href': 'https://bsky.brid.gy/convert/ap/at://did:plc:abc/app.bsky.feed.post/123', + 'name': 'RE: https://bsky.app/profile/did:plc:abc/post/123', + 'mediaType': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"', + }], + } + self.assert_equals(expected, ActivityPub.convert(obj), + ignore=['@context', 'to'])