Skip to content

Commit

Permalink
bluesky.from_as1: populate blobs into external embed thumbs
Browse files Browse the repository at this point in the history
  • Loading branch information
snarfed committed Nov 30, 2024
1 parent 20fe8e2 commit e74a4a4
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 11 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ Standardize function and method names in all modules to `to_as1`, `from_as`, etc
* Bug fix for quote posts with text content that's longer than Bluesky's limit ([snarfed/bridgy-fed#1197](https://github.com/snarfed/bridgy-fed/issues/1197)).
* When a `flag` has multiple objects, use the first one that's an ATProto record.
* Handle URLs more carefully, don't add link facets with invalid `uri`s.
* Populate `blobs` into external embed `thumb`s.
* Bug fix: handle HTML links with `title` in `content` correctly.
* Bug fix: handle attachments with no `id` or `url`.
* `to_as1`:
Expand All @@ -326,11 +327,10 @@ Standardize function and method names in all modules to `to_as1`, `from_as`, etc
* `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)).
* `source`:
* `Source.postprocess_object`: add new `first_link_to_attachment` boolean kwarg to fetch and generate a preview `attachment` for the first link in the HTML `content`, if any.

* `rss`:
* Support image enclosures, both directions.
* `source`:
* `Source.postprocess_object`: add new `first_link_to_attachment` boolean kwarg to fetch and generate a preview `attachment` for the first link in the HTML `content`, if any.

### 7.0 - 2024-06-24

Expand Down
26 changes: 18 additions & 8 deletions granary/bluesky.py
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,7 @@ def from_as1(obj, out_type=None, blobs=None, client=None,
full_text = prefix + full_text
index_offset = len(prefix)

# attachments, including quoted posts
# attachments to embed(s), including quoted posts
record_embed = record_record_embed = external_embed = external_record_embed = None

for att in attachments:
Expand Down Expand Up @@ -778,7 +778,7 @@ def from_as1(obj, out_type=None, blobs=None, client=None,
full_text = QUOTE_RE_SUFFIX.sub('', full_text)
else:
# external link
external_record_embed = _to_external_embed(att)
external_record_embed = _to_external_embed(att, blobs=blobs)
external_embed = {
'$type': f'app.bsky.embed.external#view',
'external': {
Expand Down Expand Up @@ -913,10 +913,10 @@ def from_as1(obj, out_type=None, blobs=None, client=None,
if facet not in facets:
facets.append(facet)

# attachments => embeds for articles/notes
# if we truncated this post's text, override external embed with link to
# original post. (if there are images, we added a link in the text instead,
# and this won't get used.)
if truncated and url:
# override attachments with link to original post. (if there are images,
# we added a link in the text instead, and this won't get used.)
external_record_embed = {
'$type': f'app.bsky.embed.external',
'external': {
Expand Down Expand Up @@ -1002,7 +1002,7 @@ def from_as1(obj, out_type=None, blobs=None, client=None,
ret.update({
'text': '',
'facets': None,
'embed': _to_external_embed(obj, description=full_text),
'embed': _to_external_embed(obj, description=full_text, blobs=blobs),
})
if images_record_embed:
ret['embed']['external']['thumb'] = images_record_embed['images'][0]['image']
Expand Down Expand Up @@ -1076,25 +1076,35 @@ def from_as1(obj, out_type=None, blobs=None, client=None,
return ret


def _to_external_embed(obj, description=None):
def _to_external_embed(obj, description=None, blobs=None):
"""Converts an AS1 object to a Bluesky ``app.bsky.embed.external#external``.
Args:
obj (dict): AS1 object
content (str): if provided, overrides ``summary`` and ``content` in ``obj`
description (str): if provided, overrides ``summary`` and ``content` in ``obj`
Returns:
dict: Bluesky ``app.bsky.embed.external#external`` record
"""
url = obj.get('url') or obj.get('id')
assert url

thumb = None
if blobs:
for img in as1.get_objects(obj, 'image'):
if img_url := img.get('url') or img.get('id'):
if blob := blobs.get(img_url):
thumb = blob
break

return {
'$type': f'app.bsky.embed.external',
'external': {
'$type': f'app.bsky.embed.external#external',
'uri': url,
'title': obj.get('displayName') or '', # required
'description': description or obj.get('summary') or obj.get('content') or '',
'thumb': thumb,
}
}

Expand Down
26 changes: 26 additions & 0 deletions granary/tests/test_bluesky.py
Original file line number Diff line number Diff line change
Expand Up @@ -1735,6 +1735,32 @@ def test_from_as1_attachment_without_url_isnt_embed(self):
}],
}))

def test_from_as1_attachment_to_external_embed_thumb_blob(self):
self.assertEqual({
'$type': 'app.bsky.feed.post',
'text': '',
'createdAt': '2022-01-02T03:04:05.000Z',
'embed': {
'$type': 'app.bsky.embed.external',
'external': {
'$type': 'app.bsky.embed.external#external',
'uri': 'http://my/link',
'title': 'A link',
'description': 'foo bar',
'thumb': BLOB,
},
},
}, from_as1({
'objectType': 'note',
'attachments': [{
'objectType': 'link',
'url': 'http://my/link',
'displayName': 'A link',
'summary': 'foo bar',
'image': 'http://pic',
}],
}, blobs={'http://pic': BLOB}))

def test_from_as1_note_display_name_as_embed(self):
self.assert_equals({
'$type': 'app.bsky.feed.post',
Expand Down

0 comments on commit e74a4a4

Please sign in to comment.