From 40ba007e9ecc0d40c4dc919dc6db58051362949d Mon Sep 17 00:00:00 2001 From: Ryan Barrett Date: Mon, 25 Sep 2023 10:27:08 -0700 Subject: [PATCH] add User.handle() --- activitypub.py | 4 +++- atproto.py | 2 ++ ids.py | 10 +++++----- models.py | 12 +++++++++++- tests/test_web.py | 5 ++++- tests/testutil.py | 3 +++ web.py | 14 +++++++++----- 7 files changed, 37 insertions(+), 13 deletions(-) diff --git a/activitypub.py b/activitypub.py index 1a031d5..18edddf 100644 --- a/activitypub.py +++ b/activitypub.py @@ -91,7 +91,7 @@ class ActivityPub(User, Protocol): return self.ap_actor() def ap_address(self): - """Returns this user's ActivityPub address, eg '@user@foo.com'.""" + """Returns this user's ActivityPub address, eg ``@user@foo.com``.""" if self.obj and self.obj.as1: addr = as2.address(self.as2()) if addr: @@ -99,6 +99,8 @@ class ActivityPub(User, Protocol): return as2.address(self.key.id()) + handle = ap_address + def ap_actor(self, rest=None): """Returns this user's ActivityPub actor id URL. diff --git a/atproto.py b/atproto.py index ec6539a..11e9d2a 100644 --- a/atproto.py +++ b/atproto.py @@ -80,6 +80,8 @@ class ATProto(User, Protocol): if handle: return handle + handle = atproto_handle + def web_url(self): return bluesky.Bluesky.user_url(self.readable_id) diff --git a/ids.py b/ids.py index 976c045..dc78849 100644 --- a/ids.py +++ b/ids.py @@ -8,12 +8,12 @@ from common import host_url, SUPERDOMAIN def convert_id(*, id, from_proto, to_proto): - """Converts an id (not necessarily handle) from one protocol to another. + """Converts an id from one protocol to another. Args: id (str) - from_proto (protocols.Protocol) - to_proto (protocols.Protocol) + from_proto (Protocol) + to_proto (Protocol) Returns: str: the corresponding id in ``to_proto`` @@ -49,8 +49,8 @@ def convert_handle(*, handle, from_proto, to_proto): Args: handle (str) - from_proto (protocols.Protocol) - to_proto (protocols.Protocol) + from_proto (Protocol) + to_proto (Protocol) Returns: str: the corresponding handle in ``to_proto`` diff --git a/models.py b/models.py index 5e5e067..40b8c6e 100644 --- a/models.py +++ b/models.py @@ -25,6 +25,7 @@ from oauth_dropins.webutil.util import json_dumps, json_loads import common from common import add, base64_to_long, long_to_base64, redirect_unwrap +import ids # maps string label to Protocol subclass. populated by ProtocolUserMeta. # seed with old and upcoming protocols that don't have their own classes (yet). @@ -286,12 +287,21 @@ class User(StringIdModel, metaclass=ProtocolUserMeta): @ndb.ComputedProperty def readable_id(self): - """This user's human-readable unique id, eg '@me@snarfed.org'. + """This user's human-readable unique id, eg ``@me@snarfed.org``. + + TODO: rename to handle? Need to backfill then. To be implemented by subclasses. """ return None + def handle(self): + """Returns this user's handle, eg ``@me@snarfed.org``. + + To be implemented by subclasses. + """ + raise NotImplementedError() + def readable_or_key_id(self): """Returns readable_id if set, otherwise key id.""" return self.readable_id or self.key.id() diff --git a/tests/test_web.py b/tests/test_web.py index a02ce47..4f687ba 100644 --- a/tests/test_web.py +++ b/tests/test_web.py @@ -1869,7 +1869,7 @@ class WebUtilTest(TestCase): def setUp(self): super().setUp() - g.user = self.make_user('user.com') + g.user = self.make_user('user.com', cls=Web) def test_key_for(self, *_): for id in 'user.com', 'http://user.com', 'https://user.com/': @@ -1882,6 +1882,9 @@ class WebUtilTest(TestCase): with self.subTest(bad=bad): self.assertIsNone(Web.key_for(bad)) + def test_handle(self, *_): + self.assertEqual('user.com', g.user.handle()) + def test_owns_id(self, *_): self.assertIsNone(Web.owns_id('http://foo.com')) self.assertIsNone(Web.owns_id('https://bar.com/')) diff --git a/tests/testutil.py b/tests/testutil.py index 52e66e9..5d3b3da 100644 --- a/tests/testutil.py +++ b/tests/testutil.py @@ -70,6 +70,9 @@ class Fake(User, protocol.Protocol): # in-order list of ids fetched = [] + def handle(self): + return self.key.id().replace('fake:', 'fake:handle:') + def web_url(self): return self.key.id() diff --git a/web.py b/web.py index 0ad7342..2912a37 100644 --- a/web.py +++ b/web.py @@ -100,8 +100,12 @@ class Web(User, Protocol): """ return super().get_or_create(id.lower().strip('.'), **kwargs) + def handle(self): + """Returns this user's domain, eg ``user.com``.""" + return self.key.id() + def web_url(self): - """Returns this user's web URL aka web_url, eg 'https://foo.com/'.""" + """Returns this user's web URL aka web_url, eg ``https://foo.com/``.""" return f'https://{self.key.id()}/' profile_id = web_url @@ -119,10 +123,10 @@ class Web(User, Protocol): def ap_actor(self, rest=None): """Returns this user's ActivityPub/AS2 actor id. - Eg 'https://fed.brid.gy/foo.com' + Eg ``https://fed.brid.gy/foo.com`` - Web users are special cased to not have an /ap/web/ prefix, for backward - compatibility. + Web users are special cased to not have an ``/ap/web/`` prefix, for + backward compatibility. """ url = common.host_url(self.key.id()) if rest: @@ -130,7 +134,7 @@ class Web(User, Protocol): return url def atproto_handle(self): - """Returns `[DOMAIN].web.brid.gy`.""" + """Returns ``[DOMAIN].web.brid.gy``.""" return f'{self.key.id()}.{self.ABBREV}{common.SUPERDOMAIN}' def user_page_path(self, rest=None):