Skip to content

Commit

Permalink
Protocol.translate_ids: translate to, cc, bto, bcc
Browse files Browse the repository at this point in the history
for #12
  • Loading branch information
snarfed committed Sep 13, 2024
1 parent cfaacb8 commit f3522e4
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 13 deletions.
3 changes: 2 additions & 1 deletion activitypub.py
Original file line number Diff line number Diff line change
Expand Up @@ -796,10 +796,11 @@ def postprocess_as2(activity, orig_obj=None, wrap=True):
for recip in as1.get_objects(orig_obj, field):
add(cc, util.get_url(recip) or recip.get('id'))

# for CRUD activities, Pleroma (and Akkoma?) seem to crash if the activity's
# for some activities, Pleroma (and Akkoma?) seem to crash if the activity's
# to and cc aren't exactly the same as the object's. (I think?)
# https://indieweb.social/@[email protected]/112977955332152430
# https://git.pleroma.social/pleroma/pleroma/-/issues/3206#note_108296
# https://github.com/snarfed/bridgy-fed/issues/12#issuecomment-2302776658
if type in ('Create', 'Update'):
activity['to'] = util.get_list(obj, 'to')
activity['cc'] = util.get_list(obj, 'cc')
Expand Down
8 changes: 7 additions & 1 deletion protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -677,13 +677,17 @@ def translate_ids(to_cls, obj):
* ``id``
* ``actor``
* ``author``
* ``bcc``
* ``bto``
* ``cc``
* ``object``
* ``object.actor``
* ``object.author``
* ``object.id``
* ``object.inReplyTo``
* ``attachments[].id``
* ``tags[objectType=mention].url``
* ``to``
This is the inverse of :meth:`models.Object.resolve_ids`. Much of the
same logic is duplicated there!
Expand All @@ -709,6 +713,8 @@ def translate(elem, field, fn):
elem[field] = as1.get_objects(elem, field)
for obj in elem[field]:
if id := obj.get('id'):
if field in ('to', 'cc', 'bcc', 'bto') and as1.is_audience(id):
continue
from_cls = Protocol.for_id(id)
# TODO: what if from_cls is None? relax translate_object_id,
# make it a noop if we don't know enough about from/to?
Expand All @@ -734,7 +740,7 @@ def translate(elem, field, fn):

for o in [outer_obj] + inner_objs:
translate(o, 'inReplyTo', translate_object_id)
for field in 'actor', 'author':
for field in 'actor', 'author', 'to', 'cc', 'bto', 'bcc':
translate(o, field, translate_user_id)
for tag in as1.get_objects(o, 'tags'):
if tag.get('objectType') == 'mention':
Expand Down
59 changes: 48 additions & 11 deletions tests/test_activitypub.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@

FOLLOW = {
'@context': 'https://www.w3.org/ns/activitystreams',
'id': 'https://mas.to/6d1a',
'id': 'https://mas.to/follow',
'type': 'Follow',
'actor': ACTOR['id'],
'object': 'https://user.com/',
Expand All @@ -223,11 +223,11 @@
ACCEPT = {
'@context': 'https://www.w3.org/ns/activitystreams',
'type': 'Accept',
'id': 'http://localhost/r/user.com/followers#accept-https://mas.to/6d1a',
'id': 'http://localhost/r/user.com/followers#accept-https://mas.to/follow',
'actor': 'http://localhost/user.com',
'object': {
'type': 'Follow',
'id': 'https://mas.to/6d1a',
'id': 'https://mas.to/follow',
'object': 'http://localhost/user.com',
'actor': 'https://mas.to/users/swentel',
'url': 'https://mas.to/users/swentel#followed-user.com',
Expand Down Expand Up @@ -1076,7 +1076,7 @@ def test_inbox_follow_accept_with_id(self, *mocks):
'url': 'https://mas.to/users/swentel#followed-user.com',
'object': 'user.com'
}
self.assert_object('https://mas.to/6d1a',
self.assert_object('https://mas.to/follow',
users=[self.swentel_key],
notify=[self.user.key],
source_protocol='activitypub',
Expand All @@ -1103,7 +1103,7 @@ def test_inbox_follow_accept_with_object(self, *mocks):
'url': 'https://mas.to/users/swentel#followed-https://user.com/',
})
follow['object']['id'] = 'user.com'
self.assert_object('https://mas.to/6d1a',
self.assert_object('https://mas.to/follow',
users=[self.swentel_key],
notify=[self.user.key],
source_protocol='activitypub',
Expand All @@ -1113,6 +1113,32 @@ def test_inbox_follow_accept_with_object(self, *mocks):
type='follow',
)

def test_inbox_follow_accept_inner_follow_to(self, *mocks):
follow = {
'type': 'Follow',
'id': 'https://mas.to/follow',
'actor': 'https://mas.to/users/swentel',
'object': 'http://localhost/user.com',
'to': ['http://localhost/user.com'],
}

accept = {
'@context': 'https://www.w3.org/ns/activitystreams',
'type': 'Accept',
'id': 'http://localhost/r/user.com/followers#accept-https://mas.to/follow',
'actor': 'http://localhost/user.com',
'object': {
'type': 'Follow',
'id': 'https://mas.to/follow',
'actor': 'https://mas.to/users/swentel',
'object': 'http://localhost/user.com',
'url': 'https://mas.to/users/swentel#followed-user.com',
'to': ['http://localhost/user.com']
},
'to': ['https://www.w3.org/ns/activitystreams#Public']
}
self._test_inbox_follow_accept(follow, accept, *mocks)

def test_inbox_follow_accept_shared_inbox(self, mock_head, mock_get, mock_post):
self._test_inbox_follow_accept(FOLLOW_WRAPPED, ACCEPT,
mock_head, mock_get, mock_post,
Expand All @@ -1124,7 +1150,7 @@ def test_inbox_follow_accept_shared_inbox(self, mock_head, mock_get, mock_post):
'url': url,
'object': 'user.com',
}
self.assert_object('https://mas.to/6d1a',
self.assert_object('https://mas.to/follow',
users=[self.swentel_key],
notify=[self.user.key],
source_protocol='activitypub',
Expand All @@ -1149,7 +1175,7 @@ def test_inbox_follow_accept_webmention_fails(self, mock_head, mock_get,
'url': url,
'object': 'user.com',
}
self.assert_object('https://mas.to/6d1a',
self.assert_object('https://mas.to/follow',
users=[self.swentel_key],
notify=[self.user.key],
source_protocol='activitypub',
Expand Down Expand Up @@ -1191,7 +1217,7 @@ def _test_inbox_follow_accept(self, follow_as2, accept_as2, mock_head,
args, kwargs = mock_post.call_args_list[1]
self.assertEqual(('https://user.com/webmention',), args)
self.assertEqual({
'source': 'https://ap.brid.gy/convert/web/https://mas.to/6d1a',
'source': 'https://ap.brid.gy/convert/web/https://mas.to/follow',
'target': 'https://user.com/',
}, kwargs['data'])

Expand Down Expand Up @@ -1266,11 +1292,11 @@ def test_inbox_follow_web_brid_gy_subdomain(self, mock_head, mock_get, mock_post
self.assert_equals(('http://mas.to/inbox',), args)
self.assert_equals({
'type': 'Accept',
'id': 'http://localhost/r/user.com/followers#accept-https://mas.to/6d1a',
'id': 'http://localhost/r/user.com/followers#accept-https://mas.to/follow',
'actor': 'http://localhost/user.com',
'object': {
'type': 'Follow',
'id': 'https://mas.to/6d1a',
'id': 'https://mas.to/follow',
'object': 'http://localhost/user.com',
'actor': 'https://mas.to/users/swentel',
'url': 'https://mas.to/users/swentel#followed-user.com',
Expand Down Expand Up @@ -2710,7 +2736,7 @@ def test_convert_actor_as1_no_from_user(self):

def test_convert_follow_as1_no_from_user(self):
# prevent HTTP fetches to infer protocol
self.store_object(id='https://mas.to/6d1a', source_protocol='activitypub')
self.store_object(id='https://mas.to/follow', source_protocol='activitypub')
self.store_object(id='https://user.com/', source_protocol='web')

obj = Object(our_as1=as2.to_as1(FOLLOW))
Expand Down Expand Up @@ -2753,6 +2779,17 @@ def test_convert_adds_context_to_as2(self):
'object': ACTOR,
}, ActivityPub.convert(obj))

def test_convert_to_cc(self):
self.assert_equals({
'@context': 'https://www.w3.org/ns/activitystreams',
'to': ['http://localhost/alice.com',
'https://www.w3.org/ns/activitystreams#Public'],
'cc': ['http://localhost/bob.com'],
}, ActivityPub.convert(Object(our_as1={
'to': ['alice.com'],
'cc': ['bob.com'],
})))

def test_convert_quote_post(self):
obj = Object(id='at://did:alice/app.bsky.feed.post/123', bsky={
'$type': 'app.bsky.feed.post',
Expand Down
11 changes: 11 additions & 0 deletions tests/test_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,17 @@ def test_translate_ids_multiple_objects(self):
]
}))

def test_translate_ids_to_cc(self):
self.assert_equals({
'id': 'xyz',
'to': ['other:u:fake:alice', 'other:bob'],
'cc': ['other:u:eefake:eve', as2.PUBLIC_AUDIENCE],
}, OtherFake.translate_ids({
'id': 'xyz',
'to': ['fake:alice', 'other:bob'],
'cc': ['eefake:eve', as2.PUBLIC_AUDIENCE],
}))

def test_convert_object_is_from_user_adds_source_links(self):
alice = Fake(id='fake:alice')
self.assertEqual({
Expand Down

0 comments on commit f3522e4

Please sign in to comment.