From 14c965340fdd75424f682d1bdb22168a9b9e07c0 Mon Sep 17 00:00:00 2001 From: Ryan Barrett Date: Tue, 17 Dec 2024 13:55:43 -0800 Subject: [PATCH] bluesky.to_as1: link hashtags to bsky.app hashtag search pages for snarfed/bridgy-fed#1634 --- README.md | 1 + granary/as2.py | 7 ++++--- granary/bluesky.py | 4 +++- granary/tests/test_as2.py | 28 +++++++++++++++++++++++++++- granary/tests/test_bluesky.py | 1 + 5 files changed, 36 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b041feb4..95f8989f 100644 --- a/README.md +++ b/README.md @@ -325,6 +325,7 @@ Standardize function and method names in all modules to `to_as1`, `from_as`, etc * Bug fix: first URL (singular) goes in `url`, list of URLs goes in `urls`. * Bug fix: handle hashtags with regexp special characters. * Support string and bytes CIDs in blob `ref`s as well as `CID` instances. + * Link hashtags to bsky.app hashtag search pages ([bridgy-fed#1634](https://github.com/snarfed/bridgy-fed/issues/1634)). * `Bluesky.get_activities`: skip unknown record types instead of raising `ValueError`. * `microformats2`: * `object_to_json`: Improve handling of items with multiple types by removing `inReplyTo` from likes, shares, etc ([snarfed/bridgy-fed#941](https://github.com/snarfed/bridgy-fed/issues/941)). diff --git a/granary/as2.py b/granary/as2.py index 26422a34..e69f889c 100644 --- a/granary/as2.py +++ b/granary/as2.py @@ -89,7 +89,8 @@ def _invert(d): ACTOR_TYPES = {as2_type for as1_type, as2_type in OBJECT_TYPE_TO_TYPE.items() if as1_type in as1.ACTOR_TYPES} # https://www.w3.org/TR/activitystreams-vocabulary/#object-types -URL_TYPES = ['Article', 'Audio', 'Image', 'Mention', 'Video'] +URL_AS2_TYPES = ['Article', 'Audio', 'Image', 'Mention', 'Video'] +LINK_AS1_TYPES = ['hashtag', 'link', 'mention'] VERB_TO_TYPE = { 'accept': 'Accept', @@ -166,7 +167,7 @@ def from_as1(obj, type=None, context=CONTEXT, top_level=True): if not obj: return {} elif isinstance(obj, str): - if type in URL_TYPES: + if type in URL_AS2_TYPES: obj = {'type': type, 'url': obj} else: return obj @@ -372,7 +373,7 @@ def all_from_as1(field, type=None, top_level=False, compact=False): obj['image'] = obj['image'][0] # other type-specific fields - if obj_type == 'mention': + if obj_type in LINK_AS1_TYPES: obj['href'] = util.get_first(obj, 'url') obj.pop('url', None) diff --git a/granary/bluesky.py b/granary/bluesky.py index 9f4bdba3..88c7fc31 100644 --- a/granary/bluesky.py +++ b/granary/bluesky.py @@ -1272,9 +1272,11 @@ def to_as1(obj, type=None, uri=None, repo_did=None, repo_handle=None, 'url': Bluesky.user_url(feat.get('did')), }) elif feat.get('$type') == 'app.bsky.richtext.facet#tag': + name = feat.get('tag') tag.update({ 'objectType': 'hashtag', - 'displayName': feat.get('tag') + 'displayName': name, + 'url': f'https://bsky.app/search?q=%23{urllib.parse.quote(name)}', }) index = facet.get('index', {}) diff --git a/granary/tests/test_as2.py b/granary/tests/test_as2.py index 8405651a..17fda009 100644 --- a/granary/tests/test_as2.py +++ b/granary/tests/test_as2.py @@ -159,7 +159,7 @@ def test_from_as1_link_attachment(self): 'type': 'Note', 'attachment': [{ 'type': 'Link', - 'url': 'http://a/link', + 'href': 'http://a/link', }], }, as2.from_as1({ 'objectType': 'note', @@ -479,6 +479,32 @@ def test_from_as1_sensitive(self): 'sensitive': True, })) + def test_from_as1_link_type_href(self): + self.assert_equals({ + 'type': 'Tag', + 'href': 'http://foo/bar', + }, as2.from_as1({ + 'objectType': 'hashtag', + 'url': 'http://foo/bar', + }), ignore=['@context']) + + def test_from_as1_tag_url_to_href(self): + self.assert_equals({ + 'type' : 'Note', + 'tag': [{ + 'type': 'Tag', + 'name': 'hache', + 'href': 'https://bsky.app/search?q=%23hache', + }], + }, as2.from_as1({ + 'objectType' : 'note', + 'tags': [{ + 'objectType': 'hashtag', + 'displayName': 'hache', + 'url': 'https://bsky.app/search?q=%23hache', + }], + }), ignore=['@context']) + def test_to_as1_stop_following_object_id(self): self.assertEqual({ 'objectType': 'activity', diff --git a/granary/tests/test_bluesky.py b/granary/tests/test_bluesky.py index 2dbac527..403721bd 100644 --- a/granary/tests/test_bluesky.py +++ b/granary/tests/test_bluesky.py @@ -185,6 +185,7 @@ 'displayName': 'hache-☕', 'startIndex': 4, 'length': 8, + 'url': 'https://bsky.app/search?q=%23hache-%E2%98%95', }], } FACET_MENTION = {