kopia lustrzana https://github.com/snarfed/bridgy-fed
atproto: handle bsky.app URLs in load, not fetch
rodzic
9b2bb9ef37
commit
878bbde328
22
atproto.py
22
atproto.py
|
@ -362,15 +362,22 @@ class ATProto(User, Protocol):
|
|||
|
||||
@classmethod
|
||||
def load(cls, id, did_doc=False, **kwargs):
|
||||
"""Thin wrapper that converts DIDs to profile URIs.
|
||||
"""Thin wrapper that converts DIDs and bsky.app URLs to at:// URIs.
|
||||
|
||||
Args:
|
||||
did_doc (bool): if True, loads and returns a DID document object
|
||||
instead of an ``app.bsky.actor.profile/self``.
|
||||
"""
|
||||
if not did_doc and id.startswith('did:'):
|
||||
if id.startswith('did:') and not did_doc:
|
||||
id = cls.profile_at_uri(id)
|
||||
|
||||
elif id.startswith('https://bsky.app/'):
|
||||
try:
|
||||
id = bluesky.web_url_to_at_uri(id)
|
||||
except ValueError as e:
|
||||
logger.warning(f"Couldn't convert {id} to at:// URI: {e}")
|
||||
return None
|
||||
|
||||
return super().load(id, **kwargs)
|
||||
|
||||
@classmethod
|
||||
|
@ -394,6 +401,8 @@ class ATProto(User, Protocol):
|
|||
logger.info(f"ATProto can't fetch {id}")
|
||||
return False
|
||||
|
||||
assert not id.startswith('https://bsky.app/') # handled in load
|
||||
|
||||
# did:plc, did:web
|
||||
if id.startswith('did:'):
|
||||
try:
|
||||
|
@ -403,15 +412,6 @@ class ATProto(User, Protocol):
|
|||
util.interpret_http_exception(e)
|
||||
return False
|
||||
|
||||
if id.startswith('https://bsky.app/'):
|
||||
try:
|
||||
id = bluesky.web_url_to_at_uri(id)
|
||||
except ValueError:
|
||||
return False
|
||||
if not id:
|
||||
return False
|
||||
obj.key = ndb.Key(Object, id)
|
||||
|
||||
# at:// URI. if it has a handle, resolve and replace with DID.
|
||||
# examples:
|
||||
# at://did:plc:s2koow7r6t7tozgd4slc3dsg/app.bsky.feed.post/3jqcpv7bv2c2q
|
||||
|
|
|
@ -1112,6 +1112,7 @@ class Protocol:
|
|||
Raises:
|
||||
requests.HTTPError: anything that :meth:`fetch` raises
|
||||
"""
|
||||
assert id
|
||||
assert local or remote is not False
|
||||
# logger.debug(f'Loading Object {id} local={local} remote={remote}')
|
||||
|
||||
|
|
|
@ -283,37 +283,16 @@ class ATProtoTest(TestCase):
|
|||
'https://api.bsky-sandbox.dev/xrpc/com.atproto.repo.getRecord?repo=did%3Aplc%3Aabc&collection=app.bsky.feed.post&rkey=123',
|
||||
json=None, data=None, headers=ANY)
|
||||
|
||||
@patch('dns.resolver.resolve', side_effect=dns.resolver.NXDOMAIN())
|
||||
@patch('requests.get', side_effect=[
|
||||
# resolving handle, HTTPS method
|
||||
requests_response('did:plc:abc', content_type='text/plain'),
|
||||
# AppView getRecord
|
||||
requests_response({
|
||||
'cid': 'bafy...',
|
||||
'value': {'foo': 'bar'},
|
||||
}),
|
||||
])
|
||||
def test_fetch_bsky_app_url(self, mock_get, _):
|
||||
obj = Object(id='https://bsky.app/profile/han.dull/post/789')
|
||||
self.assertTrue(ATProto.fetch(obj))
|
||||
|
||||
self.assertEqual('at://did:plc:abc/app.bsky.feed.post/789', obj.key.id())
|
||||
self.assertEqual({
|
||||
'foo': 'bar',
|
||||
'cid': 'bafy...',
|
||||
}, obj.bsky)
|
||||
mock_get.assert_called_with(
|
||||
'https://api.bsky-sandbox.dev/xrpc/com.atproto.repo.getRecord?repo=did%3Aplc%3Aabc&collection=app.bsky.feed.post&rkey=789',
|
||||
json=None, data=None, headers={
|
||||
'Content-Type': 'application/json',
|
||||
'User-Agent': common.USER_AGENT,
|
||||
},
|
||||
)
|
||||
def test_fetch_bsky_app_url_fails(self):
|
||||
for uri in ('https://bsky.app/profile/han.dull',
|
||||
'https://bsky.app/profile/han.dull/post/789'):
|
||||
with self.assertRaises(AssertionError):
|
||||
ATProto.fetch(Object(id=uri))
|
||||
|
||||
@patch('dns.resolver.resolve', side_effect=dns.resolver.NXDOMAIN())
|
||||
@patch('requests.get', return_value=requests_response(status=404))
|
||||
def test_fetch_resolve_handle_fails(self, mock_get, _):
|
||||
obj = Object(id='https://bsky.app/profile/bad.com/post/789')
|
||||
obj = Object(id='at://bad.com/app.bsky.feed.post/789')
|
||||
self.assertFalse(ATProto.fetch(obj))
|
||||
|
||||
def test_load_did_doc(self):
|
||||
|
@ -326,6 +305,59 @@ class ATProtoTest(TestCase):
|
|||
bsky=ACTOR_PROFILE_BSKY)
|
||||
self.assert_entities_equal(profile, ATProto.load('did:plc:user'))
|
||||
|
||||
@patch('dns.resolver.resolve', side_effect=dns.resolver.NXDOMAIN())
|
||||
@patch('requests.get', side_effect=[
|
||||
# resolving handle, HTTPS method
|
||||
requests_response('did:plc:user', content_type='text/plain'),
|
||||
# AppView getRecord
|
||||
requests_response({
|
||||
'cid': 'bafy...',
|
||||
'value': {'$type': 'app.bsky.actor.profile', 'bar': 'baz'},
|
||||
}),
|
||||
# fetching DID doc
|
||||
requests_response(DID_DOC),
|
||||
])
|
||||
def test_load_bsky_app_post_url(self, mock_get, _):
|
||||
obj = ATProto.load('https://bsky.app/profile/han.dull/post/789')
|
||||
self.assertEqual('at://did:plc:user/app.bsky.feed.post/789', obj.key.id())
|
||||
self.assertEqual({
|
||||
'$type': 'app.bsky.actor.profile',
|
||||
'bar': 'baz',
|
||||
'cid': 'bafy...',
|
||||
}, obj.bsky)
|
||||
|
||||
mock_get.assert_any_call(
|
||||
'https://api.bsky-sandbox.dev/xrpc/com.atproto.repo.getRecord?repo=did%3Aplc%3Auser&collection=app.bsky.feed.post&rkey=789',
|
||||
json=None, data=None, headers={
|
||||
'Content-Type': 'application/json',
|
||||
'User-Agent': common.USER_AGENT,
|
||||
})
|
||||
self.assert_req(mock_get, 'https://plc.local/did:plc:user')
|
||||
|
||||
@patch('requests.get', return_value=requests_response({
|
||||
'cid': 'bafy...',
|
||||
'value': {'$type': 'app.bsky.actor.profile', 'bar': 'baz'},
|
||||
}))
|
||||
def test_load_bsky_profile_url(self, mock_get):
|
||||
self.store_object(id='did:plc:user', raw=DID_DOC)
|
||||
self.make_user('did:plc:user', cls=ATProto)
|
||||
|
||||
obj = ATProto.load('https://bsky.app/profile/han.dull')
|
||||
self.assertEqual('at://did:plc:user/app.bsky.actor.profile/self', obj.key.id())
|
||||
self.assertEqual({
|
||||
'$type': 'app.bsky.actor.profile',
|
||||
'bar': 'baz',
|
||||
'cid': 'bafy...',
|
||||
}, obj.bsky)
|
||||
|
||||
mock_get.assert_called_with(
|
||||
'https://api.bsky-sandbox.dev/xrpc/com.atproto.repo.getRecord?repo=did%3Aplc%3Auser&collection=app.bsky.actor.profile&rkey=self',
|
||||
json=None, data=None, headers={
|
||||
'Content-Type': 'application/json',
|
||||
'User-Agent': common.USER_AGENT,
|
||||
},
|
||||
)
|
||||
|
||||
def test_convert_bsky_pass_through(self):
|
||||
self.assertEqual({
|
||||
'foo': 'bar',
|
||||
|
|
Ładowanie…
Reference in New Issue