Object.resolve_ids: handle multiple inReplyTo

pull/726/head
Ryan Barrett 2023-11-12 13:15:08 -08:00
rodzic a08a76c672
commit 3d0c5ecea5
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 6BE31FDF4776E9D4
2 zmienionych plików z 66 dodań i 30 usunięć

Wyświetl plik

@ -934,46 +934,58 @@ class Object(StringIdModel):
inner_obj = outer_obj['object'] = as1.get_object(outer_obj)
fields = ['actor', 'author', 'inReplyTo']
mention_tags = [t for t in (as1.get_objects(outer_obj, 'tags')
+ as1.get_objects(inner_obj, 'tags'))
if t.get('objectType') == 'mention']
# batch lookup matching users
ids = util.trim_nulls(
[as1.get_object(outer_obj, f).get('id') for f in fields]
+ [as1.get_object(inner_obj, f).get('id') for f in fields]
+ [inner_obj.get('id')]
+ [m.get('url') for m in mention_tags])
# collect relevant ids
ids = [inner_obj.get('id')]
for obj in outer_obj, inner_obj:
for tag in as1.get_objects(obj, 'tags'):
if tag.get('objectType') == 'mention':
ids.append(tag.get('url'))
for field in fields:
for val in as1.get_objects(obj, field):
ids.append(val.get('id'))
ids = util.trim_nulls(ids)
if not ids:
return
origs = get_originals(ids)
# batch lookup matching users
origs = {} # maps str copy URI to str original URI
for obj in get_originals(ids):
for copy in obj.copies:
if copy.protocol in (self_proto.LABEL, self_proto.ABBREV):
origs[copy.uri] = obj.key.id()
logger.debug(f'Replacing copies with originals: {origs}')
replaced = False
def replace(obj, field):
val = as1.get_object(obj, field).get('id')
if not val:
return
for orig in origs:
for target in orig.copies:
if (target.protocol in (self_proto.LABEL, self_proto.ABBREV)
and target.uri == val):
logger.debug(
f'Replacing copy {target} with original {orig.key.id()}')
obj[field] = orig.key.id()
nonlocal replaced
replaced = True
def replace(val):
id = val.get('id') if isinstance(val, dict) else val
orig = origs.get(id)
if not orig:
return val
nonlocal replaced
replaced = True
if isinstance(val, dict) and val.keys() > {'id'}:
val['id'] = orig
return val
else:
return orig
# actually replace ids
for obj in outer_obj, inner_obj:
for tag in as1.get_objects(obj, 'tags'):
if tag.get('objectType') == 'mention':
tag['url'] = replace(tag.get('url'))
for field in fields:
replace(obj, field)
obj[field] = [replace(val) for val in util.get_list(obj, field)]
if len(obj[field]) == 1:
obj[field] = obj[field][0]
replace(inner_obj, 'id')
if inner_obj.keys() == {'id'}:
outer_obj['object'] = inner_obj['id']
for tag in mention_tags:
replace(tag, 'url')
outer_obj['object'] = replace(inner_obj)
if util.trim_nulls(outer_obj['object']).keys() == {'id'}:
outer_obj['object'] = outer_obj['object']['id']
if replaced:
self.our_as1 = util.trim_nulls(outer_obj)

Wyświetl plik

@ -734,6 +734,30 @@ class ObjectTest(TestCase):
},
}, obj.our_as1)
def test_resolve_ids_multiple_in_reply_to(self):
note = {
'id': 'fake:note',
'objectType': 'note',
'inReplyTo': ['fake:a', 'fake:b'],
}
obj = Object(our_as1=note, source_protocol='fake')
# no matching copy users or objects
obj.resolve_ids()
self.assert_equals(note, obj.our_as1)
# matching copies
self.store_object(id='other:a',
copies=[Target(uri='fake:a', protocol='fa')])
self.store_object(id='other:b',
copies=[Target(uri='fake:b', protocol='fake')])
obj.resolve_ids()
self.assert_equals({
'id': 'fake:note',
'objectType': 'note',
'inReplyTo': ['other:a', 'other:b'],
}, obj.our_as1)
def test_resolve_ids_subdomain_urls(self):
obj = Object(our_as1={
'objectType': 'activity',