Protocol.receive: automatically send to ATProto PDS if user has ATProto enabled

for #999
pull/1020/head
Ryan Barrett 2024-05-05 17:13:42 -07:00
rodzic c608ecaa36
commit 515be28cdd
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 6BE31FDF4776E9D4
3 zmienionych plików z 56 dodań i 8 usunięć

Wyświetl plik

@ -402,6 +402,17 @@ class Protocol:
if owner:
return cls.key_for(owner)
@classmethod
def bot_user_id(cls):
"""Returns the Web user id for the bot user for this protocol.
For example, ``'bsky.brid.gy'`` for ATProto.
Returns:
str:
"""
return f'{cls.ABBREV}{SUPERDOMAIN}'
@classmethod
def create_for(cls, user):
"""Creates a copy user in this protocol.
@ -1020,8 +1031,8 @@ class Protocol:
obj (models.Object): activity to deliver
from_user (models.User): user (actor) this activity is from
"""
# find delivery targets
targets = from_cls.targets(obj) # maps Target to Object or None
# find delivery targets. maps Target to Object or None
targets = from_cls.targets(obj, from_user=from_user)
if not targets:
obj.status = 'ignored'
@ -1050,13 +1061,14 @@ class Protocol:
return 'OK', 202
@classmethod
def targets(cls, obj):
def targets(cls, obj, from_user):
"""Collects the targets to send a :class:`models.Object` to.
Targets are both objects - original posts, events, etc - and actors.
Args:
obj (models.Object)
from_user (User)
Returns:
dict: maps :class:`models.Target` to original (in response to)
@ -1192,6 +1204,21 @@ class Protocol:
if feed_obj:
feed_obj.put()
# include ATProto if this user is enabled there.
# TODO: abstract across protocols. maybe with this, below
# targets.update({
# Target(protocol=proto.LABEL,
# uri=proto.target_for(proto.bot_user_id())): None
# for proto in PROTOCOLS
# if proto and proto.HAS_COPIES
# })
if 'atproto' in from_user.enabled_protocols:
from atproto import ATProto
targets.setdefault(Target(protocol=ATProto.LABEL, uri=ATProto.PDS_URL),
None)
logger.info(f'user has ATProto enabled, added target {ATProto.PDS_URL}')
# de-dupe targets, discard same-domain
# maps string target URL to (Target, Object) tuple
candidates = {t.uri: (t, obj) for t, obj in targets.items()}

Wyświetl plik

@ -147,7 +147,7 @@ def run():
obj.put()
targets = list(user.targets(obj).keys())
targets = list(user.targets(obj, from_user=user).keys())
if from_proto != ActivityPub:
targets += [Target(protocol='activitypub', uri=t)

Wyświetl plik

@ -443,14 +443,14 @@ class ProtocolTest(TestCase):
self.assertCountEqual([
Target(protocol='fake', uri='fake:post:target'),
Target(protocol='atproto', uri='https://atproto.brid.gy'),
], Protocol.targets(obj).keys())
], Protocol.targets(obj, from_user=user).keys())
def test_targets_composite_inreplyto(self):
Fake.fetchable['fake:post'] = {
'objectType': 'note',
}
self.assertEqual({Target(protocol='fake', uri='fake:post:target')},
OtherFake.targets(Object(our_as1={
obj = Object(our_as1={
'objectType': 'activity',
'verb': 'post',
'object': {
@ -461,7 +461,10 @@ class ProtocolTest(TestCase):
'url': 'http://foo',
},
},
})).keys())
})
self.assertEqual({Target(protocol='fake', uri='fake:post:target')},
OtherFake.targets(obj, from_user=self.user).keys())
def test_translate_ids_follow(self):
self.assert_equals({
@ -681,6 +684,24 @@ class ProtocolReceiveTest(TestCase):
self.assertEqual([(obj.key.id(), 'shared:target')], Fake.sent)
@patch.object(ATProto, 'send', return_value=True)
def test_create_post_user_enabled_copy_protocol_adds_pds_target(self, mock_send):
self.user.enabled_protocols = ['atproto']
self.user.put()
post_as1 = {
'id': 'fake:post',
'objectType': 'note',
'author': 'fake:user',
}
obj = self.store_object(id='fake:post', our_as1=post_as1)
self.assertEqual(('OK', 202), Fake.receive_as1(post_as1))
[obj, url], _ = mock_send.call_args
self.assertEqual('fake:post#bridgy-fed-create', obj.key.id())
self.assertEqual(ATProto.PDS_URL, url)
def test_create_post_use_instead(self):
self.make_user('fake:not-this', cls=Fake, use_instead=self.user.key, obj_mf2={
'type': ['h-card'],