improve rendering of ATProto interactions on user pages

for #825
pull/953/head
Ryan Barrett 2024-04-11 15:02:15 -07:00
rodzic 817ef1d5d6
commit 133d640f1d
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 6BE31FDF4776E9D4
3 zmienionych plików z 51 dodań i 20 usunięć

Wyświetl plik

@ -54,6 +54,8 @@ _INSTANCE_ACTOR = None
# populated in User.status # populated in User.status
WEB_OPT_OUT_DOMAINS = None WEB_OPT_OUT_DOMAINS = None
FEDI_URL_RE = re.compile(r'https://[^/]+/(@|users/)([^/@]+)(@[^/@]+)?(/(?:statuses/)?[0-9]+)?')
def instance_actor(): def instance_actor():
global _INSTANCE_ACTOR global _INSTANCE_ACTOR

Wyświetl plik

@ -47,6 +47,14 @@ appview = Client(f'https://{os.environ["APPVIEW_HOST"]}',
headers={'User-Agent': USER_AGENT}) headers={'User-Agent': USER_AGENT})
LEXICONS = appview.defs LEXICONS = appview.defs
# https://atproto.com/guides/applications#record-types
COLLECTION_TO_TYPE = {
'app.bsky.actor.profile': 'profile',
'app.bsky.feed.like': 'like',
'app.bsky.feed.post': 'post',
'app.bsky.feed.repost': 'repost',
'app.bsky.graph.follow': 'follow',
}
DNS_GCP_PROJECT = 'brid-gy' DNS_GCP_PROJECT = 'brid-gy'
DNS_ZONE = 'brid-gy' DNS_ZONE = 'brid-gy'
@ -55,6 +63,22 @@ logger.info(f'Using GCP DNS project {DNS_GCP_PROJECT} zone {DNS_ZONE}')
dns_client = dns.Client(project=DNS_GCP_PROJECT) dns_client = dns.Client(project=DNS_GCP_PROJECT)
def did_to_handle(did):
"""Resolves a DID to a handle _if_ we have the DID doc stored locally.
Args:
did (str)
Returns:
str: handle, or None
"""
if did_obj := ATProto.load(did, did_doc=True):
if aka := util.get_first(did_obj.raw, 'alsoKnownAs', ''):
handle, _, _ = parse_at_uri(aka)
if handle:
return handle
class ATProto(User, Protocol): class ATProto(User, Protocol):
"""AT Protocol class. """AT Protocol class.
@ -86,11 +110,7 @@ class ATProto(User, Protocol):
@ndb.ComputedProperty @ndb.ComputedProperty
def handle(self): def handle(self):
"""Returns handle if the DID document includes one, otherwise None.""" """Returns handle if the DID document includes one, otherwise None."""
if did_obj := ATProto.load(self.key.id(), did_doc=True): return did_to_handle(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): def web_url(self):
return bluesky.Bluesky.user_url(self.handle_or_id()) return bluesky.Bluesky.user_url(self.handle_or_id())

Wyświetl plik

@ -15,7 +15,7 @@ from Crypto.PublicKey import RSA
from flask import g, request from flask import g, request
from google.cloud import ndb from google.cloud import ndb
from granary import as1, as2, atom, bluesky, microformats2 from granary import as1, as2, atom, bluesky, microformats2
from granary.bluesky import BSKY_APP_URL_RE from granary.bluesky import AT_URI_PATTERN, BSKY_APP_URL_RE
from granary.source import html_to_text from granary.source import html_to_text
from oauth_dropins.webutil import util from oauth_dropins.webutil import util
from oauth_dropins.webutil.appengine_info import DEBUG from oauth_dropins.webutil.appengine_info import DEBUG
@ -1272,23 +1272,32 @@ def fetch_objects(query, by=None, user=None):
'url': id, 'url': id,
}) })
elif url: elif url:
# heuristics for sniffing Mastodon and similar fediverse URLs and # heuristics for sniffing URLs and converting them to more friendly
# converting them to more friendly @-names # phrases and user handles.
# TODO: standardize this into granary.as2 somewhere? # TODO: standardize this into granary.as2 somewhere?
if not content: if not content:
fedi_url = re.match( from activitypub import FEDI_URL_RE
r'https://[^/]+/(@|users/)([^/@]+)(@[^/@]+)?(/(?:statuses/)?[0-9]+)?', url) from atproto import COLLECTION_TO_TYPE, did_to_handle
if fedi_url:
content = '@' + fedi_url.group(2)
if fedi_url.group(4):
content += "'s post"
if not content: if match := FEDI_URL_RE.match(url):
if bsky_url := BSKY_APP_URL_RE.match(url): content = '@' + match.group(2)
if handle := bsky_url.group('id'): # or DID if match.group(4):
content = '@' + handle
if bsky_url.group('tid'):
content += "'s post" content += "'s post"
elif match := BSKY_APP_URL_RE.match(url):
id = match.group('id')
if id.startswith('did:'):
id = ATdid_to_handle(id) or id
content = '@' + id
if match.group('tid'):
content += "'s post"
elif match := AT_URI_PATTERN.match(url):
id = match.group('repo')
if id.startswith('did:'):
id = did_to_handle(id) or id
content = '@' + id
if coll := match.group('collection'):
content += f"'s {COLLECTION_TO_TYPE.get(coll) or 'post'}"
url = bluesky.at_uri_to_web_url(url)
content = common.pretty_link(url, text=content, user=user) content = common.pretty_link(url, text=content, user=user)