diff --git a/activitypub.py b/activitypub.py index c639b61..94fab6a 100644 --- a/activitypub.py +++ b/activitypub.py @@ -738,7 +738,9 @@ def postprocess_as2_actor(actor, wrap=True): # https://docs.joinmastodon.org/spec/webfinger/#mastodons-requirements-for-webfinger # https://github.com/snarfed/bridgy-fed/issues/302#issuecomment-1324305460 # https://github.com/snarfed/bridgy-fed/issues/77 - actor['preferredUsername'] = g.user.handle_as(ActivityPub).strip('@').split('@')[0] + handle = g.user.handle_as(ActivityPub) + if handle: + actor['preferredUsername'] = handle.strip('@').split('@')[0] # Override the label for their home page to be "Web site" for att in util.get_list(actor, 'attachment'): @@ -942,15 +944,15 @@ def outbox(id): objects, before, after = fetch_objects(query, by=Object.updated, user=g.user) return { - '@context': 'https://www.w3.org/ns/activitystreams', - 'id': request.url, - 'summary': f"{id}'s outbox", - 'type': 'OrderedCollection', - # TODO. needs to handle deleted - # 'totalItems': query.count(), - 'first': { - 'type': 'CollectionPage', - 'partOf': request.base_url, - 'items': [ActivityPub.convert(obj) for obj in objects], - }, - }, {'Content-Type': as2.CONTENT_TYPE} + '@context': 'https://www.w3.org/ns/activitystreams', + 'id': request.url, + 'summary': f"{id}'s outbox", + 'type': 'OrderedCollection', + # TODO. needs to handle deleted + # 'totalItems': query.count(), + 'first': { + 'type': 'CollectionPage', + 'partOf': request.base_url, + 'items': [ActivityPub.convert(obj) for obj in objects], + }, + }, {'Content-Type': as2.CONTENT_TYPE} diff --git a/atproto.py b/atproto.py index 991f3f5..45edb5d 100644 --- a/atproto.py +++ b/atproto.py @@ -79,12 +79,11 @@ class ATProto(User, Protocol): @ndb.ComputedProperty def handle(self): """Returns handle if the DID document includes one, otherwise None.""" - did_obj = ATProto.load(self.key.id()) - if did_obj: - handle, _, _ = parse_at_uri( - util.get_first(did_obj.raw, 'alsoKnownAs', '')) - if handle: - return handle + if did_obj := ATProto.load(self.key.id()): + if aka := util.get_first(did_obj.raw, 'alsoKnownAs', ''): + handle, _, _ = parse_at_uri(aka) + if handle: + return handle def web_url(self): return bluesky.Bluesky.user_url(self.handle_or_id()) diff --git a/tests/test_activitypub.py b/tests/test_activitypub.py index 07b70e3..5ebe765 100644 --- a/tests/test_activitypub.py +++ b/tests/test_activitypub.py @@ -23,6 +23,7 @@ from .testutil import Fake, TestCase import activitypub from activitypub import ActivityPub, default_signature_user, postprocess_as2 +from atproto import ATProto import common from models import Follower, Object import protocol @@ -428,6 +429,13 @@ class ActivityPubTest(TestCase): **ACTOR_FAKE, }, got.json, ignore=['publicKeyPem']) + def test_actor_no_handle(self, *_): + self.store_object(id='did:plc:user', raw={'foo': 'bar'}) + self.make_user('did:plc:user', cls=ATProto) + got = self.client.get('/ap/did:plc:user', base_url='https://atproto.brid.gy/') + self.assertEqual(200, got.status_code) + self.assertNotIn('preferredUsername', got.json) + def test_actor_handle_user_fetch_fails(self, _, __, ___): got = self.client.get('/ap/fake/fake:handle:nope') self.assertEqual(404, got.status_code)