kopia lustrzana https://github.com/snarfed/bridgy-fed
rodzic
db2668ffab
commit
579f55d965
|
@ -883,6 +883,8 @@ def follower_collection(id, collection):
|
||||||
* https://www.w3.org/TR/activitypub/#followers
|
* https://www.w3.org/TR/activitypub/#followers
|
||||||
* https://www.w3.org/TR/activitypub/#collections
|
* https://www.w3.org/TR/activitypub/#collections
|
||||||
* https://www.w3.org/TR/activitystreams-core/#paging
|
* https://www.w3.org/TR/activitystreams-core/#paging
|
||||||
|
|
||||||
|
TODO: unify page generation with outbox()
|
||||||
"""
|
"""
|
||||||
protocol = Protocol.for_request(fed='web')
|
protocol = Protocol.for_request(fed='web')
|
||||||
assert protocol
|
assert protocol
|
||||||
|
@ -932,6 +934,10 @@ def follower_collection(id, collection):
|
||||||
@app.get(f'/<regex("{DOMAIN_RE}"):id>/outbox')
|
@app.get(f'/<regex("{DOMAIN_RE}"):id>/outbox')
|
||||||
@flask_util.cached(cache, CACHE_TIME)
|
@flask_util.cached(cache, CACHE_TIME)
|
||||||
def outbox(id):
|
def outbox(id):
|
||||||
|
"""Serves a user's AP outbox.
|
||||||
|
|
||||||
|
TODO: unify page generation with follower_collection()
|
||||||
|
"""
|
||||||
protocol = Protocol.for_request(fed='web')
|
protocol = Protocol.for_request(fed='web')
|
||||||
if not protocol:
|
if not protocol:
|
||||||
error(f"Couldn't determine protocol", status=404)
|
error(f"Couldn't determine protocol", status=404)
|
||||||
|
@ -941,18 +947,34 @@ def outbox(id):
|
||||||
error(f'User {id} not found', status=404)
|
error(f'User {id} not found', status=404)
|
||||||
|
|
||||||
query = Object.query(Object.users == g.user.key)
|
query = Object.query(Object.users == g.user.key)
|
||||||
objects, before, after = fetch_objects(query, by=Object.updated, user=g.user)
|
objects, new_before, new_after = fetch_objects(query, by=Object.updated,
|
||||||
|
user=g.user)
|
||||||
|
|
||||||
|
# page
|
||||||
|
page = {
|
||||||
|
'type': 'CollectionPage',
|
||||||
|
'partOf': request.base_url,
|
||||||
|
'items': util.trim_nulls([ActivityPub.convert(obj) for obj in objects]),
|
||||||
|
}
|
||||||
|
if new_before:
|
||||||
|
page['next'] = f'{request.base_url}?before={new_before}'
|
||||||
|
if new_after:
|
||||||
|
page['prev'] = f'{request.base_url}?after={new_after}'
|
||||||
|
|
||||||
|
if 'before' in request.args or 'after' in request.args:
|
||||||
|
page.update({
|
||||||
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||||
|
'id': request.url,
|
||||||
|
})
|
||||||
|
logger.info(f'Returning {json_dumps(page, indent=2)}')
|
||||||
|
return page, {'Content-Type': as2.CONTENT_TYPE}
|
||||||
|
|
||||||
|
# collection
|
||||||
return {
|
return {
|
||||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||||
'id': request.url,
|
'id': request.url,
|
||||||
'summary': f"{id}'s outbox",
|
|
||||||
'type': 'OrderedCollection',
|
'type': 'OrderedCollection',
|
||||||
# TODO. needs to handle deleted
|
'summary': f"{id}'s outbox",
|
||||||
# 'totalItems': query.count(),
|
'totalItems': query.count(),
|
||||||
'first': {
|
'first': page,
|
||||||
'type': 'CollectionPage',
|
|
||||||
'partOf': request.base_url,
|
|
||||||
'items': [ActivityPub.convert(obj) for obj in objects],
|
|
||||||
},
|
|
||||||
}, {'Content-Type': as2.CONTENT_TYPE}
|
}, {'Content-Type': as2.CONTENT_TYPE}
|
||||||
|
|
|
@ -1568,6 +1568,7 @@ class ActivityPubTest(TestCase):
|
||||||
'id': 'https://fa.brid.gy/ap/fake:foo/outbox',
|
'id': 'https://fa.brid.gy/ap/fake:foo/outbox',
|
||||||
'summary': "fake:foo's outbox",
|
'summary': "fake:foo's outbox",
|
||||||
'type': 'OrderedCollection',
|
'type': 'OrderedCollection',
|
||||||
|
'totalItems': 0,
|
||||||
'first': {
|
'first': {
|
||||||
'type': 'CollectionPage',
|
'type': 'CollectionPage',
|
||||||
'partOf': 'https://fa.brid.gy/ap/fake:foo/outbox',
|
'partOf': 'https://fa.brid.gy/ap/fake:foo/outbox',
|
||||||
|
@ -1575,26 +1576,55 @@ class ActivityPubTest(TestCase):
|
||||||
},
|
},
|
||||||
}, resp.json)
|
}, resp.json)
|
||||||
|
|
||||||
|
def store_outbox_objects(self, user):
|
||||||
|
for i, obj in enumerate([REPLY, MENTION, LIKE, DELETE]):
|
||||||
|
self.store_object(id=obj['id'], users=[user.key], as2=obj)
|
||||||
|
|
||||||
|
@patch('models.PAGE_SIZE', 2)
|
||||||
def test_outbox_fake_objects(self, *_):
|
def test_outbox_fake_objects(self, *_):
|
||||||
user = self.make_user('fake:foo', cls=Fake)
|
user = self.make_user('fake:foo', cls=Fake)
|
||||||
for i, obj in enumerate([REPLY, MENTION, LIKE, DELETE]):
|
self.store_outbox_objects(user)
|
||||||
self.store_object(id=str(i), users=[user.key], as2=obj)
|
|
||||||
|
|
||||||
resp = self.client.get(f'/ap/fake:foo/outbox',
|
resp = self.client.get(f'/ap/fake:foo/outbox',
|
||||||
base_url='https://fa.brid.gy')
|
base_url='https://fa.brid.gy')
|
||||||
self.assertEqual(200, resp.status_code)
|
self.assertEqual(200, resp.status_code)
|
||||||
|
|
||||||
|
after = Object.get_by_id(LIKE['id']).updated.isoformat()
|
||||||
self.assertEqual({
|
self.assertEqual({
|
||||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||||
'id': 'https://fa.brid.gy/ap/fake:foo/outbox',
|
'id': 'https://fa.brid.gy/ap/fake:foo/outbox',
|
||||||
'summary': "fake:foo's outbox",
|
'summary': "fake:foo's outbox",
|
||||||
'type': 'OrderedCollection',
|
'type': 'OrderedCollection',
|
||||||
|
'totalItems': 4,
|
||||||
'first': {
|
'first': {
|
||||||
'type': 'CollectionPage',
|
'type': 'CollectionPage',
|
||||||
'partOf': 'https://fa.brid.gy/ap/fake:foo/outbox',
|
'partOf': 'https://fa.brid.gy/ap/fake:foo/outbox',
|
||||||
'items': [DELETE, LIKE, MENTION, REPLY],
|
'items': [DELETE, LIKE],
|
||||||
|
'next': f'https://fa.brid.gy/ap/fake:foo/outbox?before={after}',
|
||||||
},
|
},
|
||||||
}, resp.json)
|
}, resp.json)
|
||||||
|
|
||||||
|
@patch('models.PAGE_SIZE', 2)
|
||||||
|
def test_outbox_fake_objects_page(self, *_):
|
||||||
|
user = self.make_user('fake:foo', cls=Fake)
|
||||||
|
self.store_outbox_objects(user)
|
||||||
|
|
||||||
|
after = datetime(1900, 1, 1).isoformat()
|
||||||
|
resp = self.client.get(f'/ap/fake:foo/outbox?after={after}',
|
||||||
|
base_url='https://fa.brid.gy')
|
||||||
|
self.assertEqual(200, resp.status_code)
|
||||||
|
|
||||||
|
prev = Object.get_by_id(MENTION['id']).updated.isoformat()
|
||||||
|
self.assertEqual({
|
||||||
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||||
|
'id': f'https://fa.brid.gy/ap/fake:foo/outbox?after={after}',
|
||||||
|
'type': 'CollectionPage',
|
||||||
|
'partOf': 'https://fa.brid.gy/ap/fake:foo/outbox',
|
||||||
|
'prev': f'https://fa.brid.gy/ap/fake:foo/outbox?after={prev}',
|
||||||
|
'next': f'https://fa.brid.gy/ap/fake:foo/outbox?before={after}',
|
||||||
|
'items': [MENTION, REPLY],
|
||||||
|
}, resp.json)
|
||||||
|
|
||||||
def test_outbox_web_empty(self, *_):
|
def test_outbox_web_empty(self, *_):
|
||||||
resp = self.client.get(f'/user.com/outbox')
|
resp = self.client.get(f'/user.com/outbox')
|
||||||
self.assertEqual(200, resp.status_code)
|
self.assertEqual(200, resp.status_code)
|
||||||
|
@ -1603,6 +1633,7 @@ class ActivityPubTest(TestCase):
|
||||||
'id': 'http://localhost/user.com/outbox',
|
'id': 'http://localhost/user.com/outbox',
|
||||||
'summary': "user.com's outbox",
|
'summary': "user.com's outbox",
|
||||||
'type': 'OrderedCollection',
|
'type': 'OrderedCollection',
|
||||||
|
'totalItems': 0,
|
||||||
'first': {
|
'first': {
|
||||||
'type': 'CollectionPage',
|
'type': 'CollectionPage',
|
||||||
'partOf': 'http://localhost/user.com/outbox',
|
'partOf': 'http://localhost/user.com/outbox',
|
||||||
|
|
Ładowanie…
Reference in New Issue