Skip to content

Commit

Permalink
activitypub.postprocess_as2: use as2.set_content to keep contentMap i…
Browse files Browse the repository at this point in the history
…n sync

for #1609
  • Loading branch information
snarfed committed Feb 7, 2025
1 parent e7eca33 commit 880cb48
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 17 deletions.
17 changes: 9 additions & 8 deletions activitypub.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'] += '<br><br>'
obj_or_activity['content'] += util.pretty_link(url, text=link.get('name'))
if content:
content += '<br><br>'
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
Expand Down Expand Up @@ -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 <p>. 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('<p>'):
obj_or_activity['content'] = f'<p>{content}</p>'
for lang, val in content_map.items():
if val == content:
content_map[lang] = obj_or_activity['content']
as2.set_content(obj_or_activity, f'<p>{content}</p>')

activity.pop('content_is_html', None)
return util.trim_nulls(activity)
Expand Down
104 changes: 95 additions & 9 deletions tests/test_integrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -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': '<p>foo <a href="http://bar">bar</a></p>',
'attributedTo': 'xyz',
'content': '<p><a class="hashtag" href="https://bsky.app/search?q=%23foo">#foo</a> <a href="http://bar">bar</a> <a class="mention" href="https://bsky.brid.gy/ap/https://bsky.app/profile/did:plc:baz">@baz</a></p>',
'contentMap': {
'en': '<p>foo <a href="http://bar">bar</a></p>',
'en': '<p><a class="hashtag" href="https://bsky.app/search?q=%23foo">#foo</a> <a href="http://bar">bar</a> <a class="mention" href="https://bsky.brid.gy/ap/https://bsky.app/profile/did:plc:baz">@baz</a></p>',
},
'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': '<p>a <a class="mention" href="https://bsky.brid.gy/ap/https://bsky.app/profile/did:plc:def">@b</a> c<br><br>RE: <a href="https://bsky.app/profile/did:plc:abc/post/123">https://bsky.app/profile/did:plc:abc/post/123</a></p>',
'contentMap': {
'en': '<p>a <a class="mention" href="https://bsky.brid.gy/ap/https://bsky.app/profile/did:plc:def">@b</a> c<br><br>RE: <a href="https://bsky.app/profile/did:plc:abc/post/123">https://bsky.app/profile/did:plc:abc/post/123</a></p>',
},
'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'])

0 comments on commit 880cb48

Please sign in to comment.