diff --git a/atproto.py b/atproto.py index d7a56bed..9c76f252 100644 --- a/atproto.py +++ b/atproto.py @@ -833,6 +833,8 @@ def _convert(cls, obj, fetch_blobs=False, from_user=None): return {} obj_as1 = obj.as1 + blobs = {} # maps str URL to dict blob object + aspect_ratios = {} # maps str URL to (int width, int height) tuple def fetch_blob(url, blob_field, name, check_size=True, check_type=True): if url and url not in blobs: @@ -843,10 +845,11 @@ def fetch_blob(url, blob_field, name, check_size=True, check_type=True): url=url, get_fn=util.requests_get, max_size=max_size, accept_types=accept) blobs[url] = blob.as_object() + if blob.width and blob.height: + aspect_ratios[url] = (blob.width, blob.height) except (RequestException, ValidationError) as e: logger.info(f'failed, skipping {url} : {e}') - blobs = {} # maps str URL to dict blob object if fetch_blobs: for o in obj.as1, as1.get_object(obj.as1): for url in util.get_urls(o, 'image'): @@ -878,8 +881,8 @@ def fetch_blob(url, blob_field, name, check_size=True, check_type=True): as_embed = obj.atom or obj.rss try: ret = bluesky.from_as1(cls.translate_ids(obj.as1), blobs=blobs, - client=client, original_fields_prefix='bridgy', - as_embed=as_embed) + aspects=aspect_ratios, client=client, + original_fields_prefix='bridgy', as_embed=as_embed) except (ValueError, RequestException): logger.info(f"Couldn't convert to ATProto", exc_info=True) return {} diff --git a/tests/activitypub_logo.png b/tests/activitypub_logo.png new file mode 100644 index 00000000..d2ec7928 Binary files /dev/null and b/tests/activitypub_logo.png differ diff --git a/tests/test_atproto.py b/tests/test_atproto.py index 6ad46bcc..681791ab 100644 --- a/tests/test_atproto.py +++ b/tests/test_atproto.py @@ -1,6 +1,7 @@ """Unit tests for atproto.py.""" import base64 import copy +from pathlib import Path from unittest import skip from unittest.mock import ANY, call, MagicMock, patch @@ -736,6 +737,38 @@ def test_convert_fetch_blobs_true_video_type_not_in_accept(self, mock_get): self.assertEqual(0, AtpRemoteBlob.query().count()) mock_get.assert_has_calls([self.req('https://my/vid')]) + @patch('requests.get', return_value=requests_response( + Path(__file__).with_name('activitypub_logo.png').read_bytes(), + content_type='image/png')) + def test_convert_fetch_blobs_true_image_aspect_ratio(self, mock_get): + cid = CID.decode('bafkreiefedbx7vctqxskqog5o3x2s4hnkchx7ml5aqwdbccgkzuis2ptya') + self.assertEqual({ + '$type': 'app.bsky.feed.post', + 'text': '', + 'createdAt': '2022-01-02T03:04:05.000Z', + 'embed': { + '$type': 'app.bsky.embed.images', + 'images': [{ + '$type': 'app.bsky.embed.images#image', + 'alt': '', + 'image': { + '$type': 'blob', + 'mimeType': 'image/png', + 'ref': cid, + 'size': 8644, + }, + 'aspectRatio': { + 'width': 260, + 'height': 164, + }, + }], + }, + }, ATProto.convert(Object(our_as1={ + 'objectType': 'note', + 'image': [{'url': 'http://my/pic/1'}], + }), fetch_blobs=True)) + mock_get.assert_has_calls([self.req('http://my/pic/1')]) + @patch('requests.get', side_effect=[ requests_response(status=404), requests_response('second blob contents', content_type='image/png')