when an unbridged user replies to a bridged user, DM them a prompt

one time only, per user per protocol!

for #1205
pull/1263/head
Ryan Barrett 2024-08-16 14:03:44 -07:00
rodzic ccb7158350
commit 98098aeabb
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 6BE31FDF4776E9D4
2 zmienionych plików z 60 dodań i 14 usunięć

Wyświetl plik

@ -1373,22 +1373,33 @@ class Protocol:
# process direct targets
for id in sorted(target_uris):
protocol = Protocol.for_id(id)
if not protocol:
target_proto = Protocol.for_id(id)
if not target_proto:
logger.info(f"Can't determine protocol for {id}")
continue
elif protocol.is_blocklisted(id):
elif target_proto.is_blocklisted(id):
logger.info(f'{id} is blocklisted')
continue
elif (protocol not in to_protocols
and obj.source_protocol != protocol.LABEL):
continue
orig_obj = protocol.load(id)
orig_obj = target_proto.load(id)
if not orig_obj or not orig_obj.as1:
logger.info(f"Couldn't load {id}")
continue
target_author_key = target_proto.actor_key(orig_obj)
if (target_proto not in to_protocols
and obj.source_protocol != target_proto.LABEL):
# if author isn't bridged and inReplyTo author is, DM a prompt
if id in in_reply_tos:
if target_author := target_author_key.get():
if target_author.is_enabled(from_cls):
target_proto.maybe_bot_dm(to_user=from_user,
type='replied_to_bridged_user',
text=f"""\
Hi! You <a href="{obj.as1.get('url') or obj.key.id()}">recently replied</a> to {obj.actor_link(image=False)}, who's bridged here from {target_proto.PHRASE}. If you want them to see your replies in the future, you can bridge your account into {target_proto.PHRASE} by following this account. <a href="https://fed.brid.gy/docs">See the docs</a> for more information.""")
continue
# deliver self-replies to followers
# https://github.com/snarfed/bridgy-fed/issues/639
if id in in_reply_tos and owner == as1.get_owner(orig_obj.as1):
@ -1404,11 +1415,11 @@ class Protocol:
logger.info(f'Adding target {target} for copy {copy.uri} of original {id}')
targets[Target(protocol=copy.protocol, uri=target)] = orig_obj
if protocol == from_cls and from_cls.LABEL != 'fake':
if target_proto == from_cls and from_cls.LABEL != 'fake':
logger.info(f'Skipping same-protocol target {id}')
continue
target = protocol.target_for(orig_obj)
target = target_proto.target_for(orig_obj)
if not target:
# TODO: surface errors like this somehow?
logger.error(f"Can't find delivery target for {id}")
@ -1417,14 +1428,13 @@ class Protocol:
logger.info(f'Target for {id} is {target}')
# only use orig_obj for inReplyTos and repost objects
# https://github.com/snarfed/bridgy-fed/issues/1237
targets[Target(protocol=protocol.LABEL, uri=target)] = (
targets[Target(protocol=target_proto.LABEL, uri=target)] = (
orig_obj if id in in_reply_tos or id in as1.get_ids(obj.as1, 'object')
else None)
orig_user = protocol.actor_key(orig_obj)
if orig_user:
logger.info(f'Recipient is {orig_user}')
obj.add('notify', orig_user)
if target_author_key:
logger.info(f'Recipient is {target_author_key}')
obj.add('notify', target_author_key)
if obj.type == 'undo':
logger.info('Object is an undo; adding targets for inner object')

Wyświetl plik

@ -1055,6 +1055,8 @@ class ProtocolReceiveTest(TestCase):
self.assertEqual(0, mock_send.call_count)
def test_reply_to_non_bridged_post_skips_enabled_protocol_with_followers(self):
self.make_user(id='fa.brid.gy', cls=Web)
# should skip even if it's enabled and we have followers there
self.user.enabled_protocols = ['eefake']
self.user.put()
@ -1076,6 +1078,40 @@ class ProtocolReceiveTest(TestCase):
self.assertEqual(202, code)
self.assertEqual([], ExplicitEnableFake.sent)
def test_reply_from_non_bridged_post_isnt_bridged_but_gets_dm_prompt(self):
self.make_user(id='fa.brid.gy', cls=Web)
self.user.enabled_protocols = ['eefake']
self.user.put()
eve = self.make_user('eefake:eve', cls=ExplicitEnableFake, obj_as1={
'id': 'eefake:eve',
})
self.store_object(id='fake:post', source_protocol='fake', our_as1={
'id': 'fake:post',
'objectType': 'note',
'author': 'fake:alice',
})
# with self.assertRaises(NoContent):
_, code = ExplicitEnableFake.receive_as1({
'id': 'eefake:reply',
'objectType': 'note',
'actor': 'eefake:eve',
'inReplyTo': 'fake:post',
})
self.assertEqual(204, code)
self.assertEqual([], Fake.sent)
self.assertEqual([
('https://fa.brid.gy/#replied_to_bridged_user-dm-eefake:eve-2022-01-02T03:04:05+00:00',
'eefake:eve:target'),
], ExplicitEnableFake.sent)
eve = eve.key.get()
self.assertEqual([DM(protocol='fake', type='replied_to_bridged_user')],
eve.sent_dms)
@patch.object(ATProto, 'send', return_value=True)
def test_repost_of_non_bridged_account_skips_atproto(self, mock_send):
user = self.make_user('eefake:user', cls=ExplicitEnableFake,