From 36a9f94cb801179df12f0c9cf8a8116a1c58cc98 Mon Sep 17 00:00:00 2001 From: Ryan Barrett Date: Tue, 10 Sep 2024 16:44:18 -0700 Subject: [PATCH] add fallback kwargs to User.user_link, Protocol.bridged_web_url_for for #966 --- atproto.py | 8 +------- models.py | 8 ++++++-- protocol.py | 7 +++++-- tests/test_models.py | 6 ++++++ tests/test_protocol.py | 5 +++++ tests/testutil.py | 2 +- 6 files changed, 24 insertions(+), 12 deletions(-) diff --git a/atproto.py b/atproto.py index 189326e7..ac5815d8 100644 --- a/atproto.py +++ b/atproto.py @@ -281,17 +281,11 @@ class ATProto(User, Protocol): return did.resolve_handle(handle, get_fn=util.requests_get) @classmethod - def bridged_web_url_for(cls, user): + def bridged_web_url_for(cls, user, fallback=False): """Returns a bridged user's profile URL on bsky.app. For example, returns ``https://bsky.app/profile/alice.com.web.brid.gy`` for Web user ``alice.com``. - - Args: - user (models.User) - - Returns: - str, or None if there isn't a canonical URL """ if not isinstance(user, ATProto): if did := user.get_copy(ATProto): diff --git a/models.py b/models.py index dca749ee..c363fa45 100644 --- a/models.py +++ b/models.py @@ -710,7 +710,8 @@ Welcome to Bridgy Fed! Your account will soon be bridged to {to_proto.PHRASE} at if copy.protocol in (proto.LABEL, proto.ABBREV): return copy.uri - def user_link(self, name=True, handle=True, pictures=False, proto=None): + def user_link(self, name=True, handle=True, pictures=False, proto=None, + proto_fallback=False): """Returns a pretty HTML link to the user's profile. Can optionally include display name, handle, profile @@ -724,12 +725,15 @@ Welcome to Bridgy Fed! Your account will soon be bridged to {to_proto.PHRASE} at pictures (bool): include profile picture and protocol logo proto (protocol.Protocol): link to this protocol instead of the user's native protocol + proto_fallback (bool): if True, and ``proto`` is provided and has no + no canonical profile URL for bridged users, uses the user's profile + URL in their native protocol """ img = name_str = handle_str = dot = logo = a_open = a_close = '' if proto: assert self.is_enabled(proto), f"{proto.LABEL} isn't enabled" - url = proto.bridged_web_url_for(self) + url = proto.bridged_web_url_for(self, fallback=proto_fallback) else: proto = self.__class__ url = self.web_url() diff --git a/protocol.py b/protocol.py index 78a87ff6..0dc778e8 100644 --- a/protocol.py +++ b/protocol.py @@ -414,7 +414,7 @@ class Protocol: return (None, None) @classmethod - def bridged_web_url_for(cls, user): + def bridged_web_url_for(cls, user, fallback=False): """Returns the web URL for a user's bridged profile in this protocol. For example, for Web user ``alice.com``, :meth:`ATProto.bridged_web_url_for` @@ -422,11 +422,14 @@ class Protocol: Args: user (models.User) + fallback (bool): if True, and bridged users have no canonical user + profile URL in this protocol, return the native protocol's profile URL Returns: str, or None if there isn't a canonical URL """ - return None + if fallback: + return user.web_url() @classmethod def actor_key(cls, obj): diff --git a/tests/test_models.py b/tests/test_models.py index 3eb3c6f5..798a0f68 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -220,6 +220,12 @@ class UserTest(TestCase): 'Mrs. ☕ Foo · fake:handle:y.za', self.user.user_link(proto=Fake, handle=True)) + def test_user_link_proto_fallback(self): + self.user.obj = Object(id='y.za', as2=ACTOR) + self.assert_multiline_equals( + 'Mrs. ☕ Foo · @y.za@web.brid.gy', + self.user.user_link(proto=ActivityPub, proto_fallback=True, handle=True)) + def test_user_link_proto_not_enabled(self): with self.assertRaises(AssertionError): self.user.user_link(proto=ExplicitEnableFake) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index fb916b54..1a2c8952 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -409,6 +409,11 @@ class ProtocolTest(TestCase): self.user.obj.put() self.assertIsNone(Protocol.key_for(self.user.key.id())) + def test_bridged_web_url_for(self): + self.assertIsNone(Protocol.bridged_web_url_for(self.user)) + self.assertEqual('https://foo.com/', + Protocol.bridged_web_url_for(self.user, fallback=True)) + def test_targets_checks_blocklisted_per_protocol(self): """_targets should call the target protocol's is_blocklisted().""" # non-ATProto account, ATProto target (PDS) is bsky.brid.gy diff --git a/tests/testutil.py b/tests/testutil.py index 840851b7..2df9c920 100644 --- a/tests/testutil.py +++ b/tests/testutil.py @@ -98,7 +98,7 @@ class Fake(User, protocol.Protocol): return f'web:{self.key.id()}' @classmethod - def bridged_web_url_for(cls, user): + def bridged_web_url_for(cls, user, fallback=False): return f'web:{cls.LABEL}:{user.key.id()}' @classmethod