Activity => Object: fully populate labels, source_protocol webmention

#286
activity-redesign
Ryan Barrett 2023-01-31 21:00:07 -08:00
rodzic a76fe45891
commit 4d2fcdd76f
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 6BE31FDF4776E9D4
8 zmienionych plików z 40 dodań i 23 usunięć

Wyświetl plik

@ -150,7 +150,7 @@ def inbox(domain=None):
key = Object(id=source, source_protocol='activitypub', domains=domains, key = Object(id=source, source_protocol='activitypub', domains=domains,
status='complete', as2=activity_as2_str, as1=activity_as1_str, status='complete', as2=activity_as2_str, as1=activity_as1_str,
type=as1_type, object_ids=as1.get_ids(activity_as1, 'object'), type=as1_type, object_ids=as1.get_ids(activity_as1, 'object'),
).put() labels=['feed']).put()
logging.info(f'Wrote Object {key} with {len(domains)} follower domains') logging.info(f'Wrote Object {key} with {len(domains)} follower domains')
return '' return ''

Wyświetl plik

@ -300,7 +300,9 @@ def send_webmentions(activity_wrapped, proxy=None, **object_props):
logger.info(f'Skipping same-domain webmention from {source} to {target}') logger.info(f'Skipping same-domain webmention from {source} to {target}')
continue continue
obj = Object(id=source, domains=[domain], **object_props) # TODO: unify across targets
obj = Object(id=source, domains=[domain], labels=['notification'],
**object_props)
obj.put() obj.put()
wm_source = (obj.proxy_url() wm_source = (obj.proxy_url()
if verb in ('follow', 'like', 'share') or proxy if verb in ('follow', 'like', 'share') or proxy

Wyświetl plik

@ -167,7 +167,7 @@ class FollowCallback(indieauth.Callback):
follow_json = json_dumps(follow_as2, sort_keys=True) follow_json = json_dumps(follow_as2, sort_keys=True)
Follower.get_or_create(dest=id, src=domain, status='active', Follower.get_or_create(dest=id, src=domain, status='active',
last_follow=follow_json) last_follow=follow_json)
Object(id=follow_id, domains=[domain], labels=['notification'], Object(id=follow_id, domains=[domain], labels=['user'],
source_protocol='ui', status='complete', as2=follow_json, source_protocol='ui', status='complete', as2=follow_json,
as1=json_dumps(as2.to_as1(follow_as2), sort_keys=True), as1=json_dumps(as2.to_as1(follow_as2), sort_keys=True),
).put() ).put()
@ -193,7 +193,7 @@ class UnfollowStart(indieauth.Start):
class UnfollowCallback(indieauth.Callback): class UnfollowCallback(indieauth.Callback):
"""IndieAuth callback to add a follower to an existing user.""" """IndieAuth callback to remove a follower."""
def finish(self, auth_entity, state=None): def finish(self, auth_entity, state=None):
if not auth_entity: if not auth_entity:
return return
@ -224,7 +224,7 @@ class UnfollowCallback(indieauth.Callback):
follower.status = 'inactive' follower.status = 'inactive'
follower.put() follower.put()
Object(id=unfollow_id, domains=[domain], labels=['notification'], Object(id=unfollow_id, domains=[domain], labels=['user'],
source_protocol='ui', status='complete', source_protocol='ui', status='complete',
as2=json_dumps(unfollow_as2, sort_keys=True), as2=json_dumps(unfollow_as2, sort_keys=True),
as1=json_dumps(as2.to_as1(unfollow_as2), sort_keys=True), as1=json_dumps(as2.to_as1(unfollow_as2), sort_keys=True),

Wyświetl plik

@ -233,8 +233,8 @@ class Object(StringIdModel):
Key name is the id. We synthesize ids if necessary. Key name is the id. We synthesize ids if necessary.
""" """
STATUSES = ('new', 'in progress', 'complete', 'failed', 'ignored') STATUSES = ('new', 'in progress', 'complete', 'failed', 'ignored')
PROTOCOLS = ('activitypub', 'bluesky', 'webmention', 'ui') PROTOCOLS = ('activitypub', 'bluesky', 'ostatus', 'webmention', 'ui')
LABELS = ('feed', 'notification') LABELS = ('feed', 'notification', 'user')
# domains of the Bridgy Fed users this activity is to or from # domains of the Bridgy Fed users this activity is to or from
domains = ndb.StringProperty(repeated=True) domains = ndb.StringProperty(repeated=True)
@ -251,7 +251,7 @@ class Object(StringIdModel):
mf2 = ndb.TextProperty() # HTML microformats2 mf2 = ndb.TextProperty() # HTML microformats2
type = ndb.StringProperty() # AS1 objectType, or verb if it's an activity type = ndb.StringProperty() # AS1 objectType, or verb if it's an activity
deleted = ndb.BooleanProperty(default=False) deleted = ndb.BooleanProperty()
object_ids = ndb.StringProperty(repeated=True) # id(s) of inner objects object_ids = ndb.StringProperty(repeated=True) # id(s) of inner objects
# ActivityPub inbox delivery # ActivityPub inbox delivery

Wyświetl plik

@ -332,6 +332,7 @@ class ActivityPubTest(testutil.TestCase):
source_protocol='activitypub', source_protocol='activitypub',
status='complete', status='complete',
as1=as2.to_as1(expected_props['as2']), as1=as2.to_as1(expected_props['as2']),
labels=['notification'],
**expected_props) **expected_props)
def test_inbox_reply_to_self_domain(self, mock_head, mock_get, mock_post): def test_inbox_reply_to_self_domain(self, mock_head, mock_get, mock_post):
@ -379,6 +380,7 @@ class ActivityPubTest(testutil.TestCase):
as1=as2.to_as1(expected_as2), as1=as2.to_as1(expected_as2),
domains=['foo.com', 'baz.com'], domains=['foo.com', 'baz.com'],
type='post', type='post',
labels=['feed'],
object_ids=[NOTE_OBJECT['id']]) object_ids=[NOTE_OBJECT['id']])
def test_inbox_not_public(self, mock_head, mock_get, mock_post): def test_inbox_not_public(self, mock_head, mock_get, mock_post):
@ -440,6 +442,7 @@ class ActivityPubTest(testutil.TestCase):
status='complete', status='complete',
as2=expected_as2, as2=expected_as2,
as1=as2.to_as1(expected_as2), as1=as2.to_as1(expected_as2),
labels=['notification'],
**expected_props) **expected_props)
def test_inbox_like(self, mock_head, mock_get, mock_post): def test_inbox_like(self, mock_head, mock_get, mock_post):
@ -464,7 +467,6 @@ class ActivityPubTest(testutil.TestCase):
args, kwargs = mock_post.call_args args, kwargs = mock_post.call_args
self.assertEqual(('http://or.ig/webmention',), args) self.assertEqual(('http://or.ig/webmention',), args)
self.assertEqual({ self.assertEqual({
# TODO
'source': 'http://localhost/render?id=http%3A%2F%2Fth.is%2Flike%23ok', 'source': 'http://localhost/render?id=http%3A%2F%2Fth.is%2Flike%23ok',
'target': 'http://or.ig/post', 'target': 'http://or.ig/post',
}, kwargs['data']) }, kwargs['data'])
@ -476,6 +478,7 @@ class ActivityPubTest(testutil.TestCase):
as2=LIKE_WITH_ACTOR, as2=LIKE_WITH_ACTOR,
as1=as2.to_as1(LIKE_WITH_ACTOR), as1=as2.to_as1(LIKE_WITH_ACTOR),
type='like', type='like',
labels=['notification'],
object_ids=[LIKE['object']]) object_ids=[LIKE['object']])
def test_inbox_follow_accept_with_id(self, mock_head, mock_get, mock_post): def test_inbox_follow_accept_with_id(self, mock_head, mock_get, mock_post):
@ -492,6 +495,7 @@ class ActivityPubTest(testutil.TestCase):
as2=follow, as2=follow,
as1=as2.to_as1(follow), as1=as2.to_as1(follow),
type='follow', type='follow',
labels=['notification'],
object_ids=[FOLLOW['object']]) object_ids=[FOLLOW['object']])
follower = Follower.query().get() follower = Follower.query().get()
@ -534,6 +538,7 @@ class ActivityPubTest(testutil.TestCase):
as2=follow, as2=follow,
as1=as2.to_as1(follow), as1=as2.to_as1(follow),
type='follow', type='follow',
labels=['notification'],
object_ids=[FOLLOW['object']]) object_ids=[FOLLOW['object']])
def _test_inbox_follow_accept(self, follow_as2, accept_as2, def _test_inbox_follow_accept(self, follow_as2, accept_as2,
@ -745,6 +750,7 @@ class ActivityPubTest(testutil.TestCase):
as2=LIKE_WITH_ACTOR, as2=LIKE_WITH_ACTOR,
as1=as2.to_as1(LIKE_WITH_ACTOR), as1=as2.to_as1(LIKE_WITH_ACTOR),
type='like', type='like',
labels=['notification'],
object_ids=[LIKE['object']]) object_ids=[LIKE['object']])
def test_followers_collection_unknown_user(self, *args): def test_followers_collection_unknown_user(self, *args):

Wyświetl plik

@ -193,7 +193,7 @@ class FollowTest(testutil.TestCase):
objects = Object.query().fetch() objects = Object.query().fetch()
self.assert_entities_equal( self.assert_entities_equal(
[Object(id=id, domains=['snarfed.org'], status='complete', [Object(id=id, domains=['snarfed.org'], status='complete',
labels=['notification'], source_protocol='ui', labels=['user'], source_protocol='ui',
as1=follow_as1, as2=follow_as2)], as1=follow_as1, as2=follow_as2)],
objects, objects,
ignore=['created', 'updated']) ignore=['created', 'updated'])
@ -288,7 +288,7 @@ class UnfollowTest(testutil.TestCase):
self.assert_entities_equal( self.assert_entities_equal(
[Object(id='http://localhost/user/snarfed.org/following#undo-2022-01-02T03:04:05-https://bar/id', [Object(id='http://localhost/user/snarfed.org/following#undo-2022-01-02T03:04:05-https://bar/id',
domains=['snarfed.org'], status='complete', domains=['snarfed.org'], status='complete',
source_protocol='ui', labels=['notification'], source_protocol='ui', labels=['user'],
as2=json_dumps(UNDO_FOLLOW, sort_keys=True), as2=json_dumps(UNDO_FOLLOW, sort_keys=True),
as1=json_dumps(as2.to_as1(UNDO_FOLLOW), sort_keys=True), as1=json_dumps(as2.to_as1(UNDO_FOLLOW), sort_keys=True),
)], )],

Wyświetl plik

@ -491,12 +491,13 @@ class WebmentionTest(testutil.TestCase):
self.assert_object('http://a/reply', self.assert_object('http://a/reply',
domains=['a'], domains=['a'],
source_protocol='activitypub', source_protocol='webmention',
status='complete', status='complete',
ap_delivered=['https://foo.com/inbox'], ap_delivered=['https://foo.com/inbox'],
mf2=self.reply_mf2, mf2=self.reply_mf2,
as1=self.reply_as1, as1=self.reply_as1,
type='comment', type='comment',
labels=['user'],
) )
def test_update_reply(self, mock_get, mock_post): def test_update_reply(self, mock_get, mock_post):
@ -616,13 +617,14 @@ class WebmentionTest(testutil.TestCase):
self.assert_object('http://a/repost', self.assert_object('http://a/repost',
domains=['a'], domains=['a'],
source_protocol='activitypub', source_protocol='webmention',
status='complete', status='complete',
mf2=self.repost_mf2, mf2=self.repost_mf2,
as1=self.repost_as1, as1=self.repost_as1,
ap_delivered=['https://foo.com/inbox'], ap_delivered=['https://foo.com/inbox'],
type='share', type='share',
object_ids=['https://orig/post'], object_ids=['https://orig/post'],
labels=['user'],
) )
def test_link_rel_alternate_as2(self, mock_get, mock_post): def test_link_rel_alternate_as2(self, mock_get, mock_post):
@ -768,12 +770,13 @@ class WebmentionTest(testutil.TestCase):
self.assert_object(f'https://orig/post', self.assert_object(f'https://orig/post',
domains=['orig'], domains=['orig'],
source_protocol='activitypub', source_protocol='webmention',
status='complete', status='complete',
mf2=self.create_mf2, mf2=self.create_mf2,
as1=self.create_as1, as1=self.create_as1,
ap_delivered=inboxes, ap_delivered=inboxes,
type='note', type='note',
labels=['user'],
) )
def test_create_post_run_task_resume(self, mock_get, mock_post): def test_create_post_run_task_resume(self, mock_get, mock_post):
@ -809,12 +812,13 @@ class WebmentionTest(testutil.TestCase):
self.assert_object(f'https://orig/post', self.assert_object(f'https://orig/post',
domains=['orig'], domains=['orig'],
source_protocol='activitypub', source_protocol='webmention',
status='complete', status='complete',
mf2=self.create_mf2, mf2=self.create_mf2,
as1=self.create_as1, as1=self.create_as1,
ap_delivered=inboxes + ['https://skipped/inbox'], ap_delivered=inboxes + ['https://skipped/inbox'],
type='note', type='note',
labels=['user'],
) )
def test_create_post_run_task_update(self, mock_get, mock_post): def test_create_post_run_task_update(self, mock_get, mock_post):
@ -850,12 +854,13 @@ class WebmentionTest(testutil.TestCase):
self.assert_object(f'https://orig/post', self.assert_object(f'https://orig/post',
domains=['orig'], domains=['orig'],
source_protocol='activitypub', source_protocol='webmention',
status='complete', status='complete',
mf2=self.create_mf2, mf2=self.create_mf2,
as1=self.create_as1, as1=self.create_as1,
ap_delivered=inboxes, ap_delivered=inboxes,
type='note', type='note',
labels=['user'],
) )
def test_create_with_image(self, mock_get, mock_post): def test_create_with_image(self, mock_get, mock_post):
@ -912,13 +917,14 @@ class WebmentionTest(testutil.TestCase):
self.assert_object('http://a/follow', self.assert_object('http://a/follow',
domains=['a'], domains=['a'],
source_protocol='activitypub', source_protocol='webmention',
status='complete', status='complete',
mf2=self.follow_mf2, mf2=self.follow_mf2,
as1=self.follow_as1, as1=self.follow_as1,
ap_delivered=['https://foo.com/inbox'], ap_delivered=['https://foo.com/inbox'],
type='follow', type='follow',
object_ids=['http://followee'], object_ids=['http://followee'],
labels=['user'],
) )
followers = Follower.query().fetch() followers = Follower.query().fetch()
@ -978,13 +984,14 @@ class WebmentionTest(testutil.TestCase):
self.assert_object('http://a/follow#2', self.assert_object('http://a/follow#2',
domains=['a'], domains=['a'],
source_protocol='activitypub', source_protocol='webmention',
status='complete', status='complete',
mf2=self.follow_fragment_mf2, mf2=self.follow_fragment_mf2,
as1=self.follow_fragment_as1, as1=self.follow_fragment_as1,
ap_delivered=['https://foo.com/inbox'], ap_delivered=['https://foo.com/inbox'],
type='follow', type='follow',
object_ids=['http://followee'], object_ids=['http://followee'],
labels=['user'],
) )
followers = Follower.query().fetch() followers = Follower.query().fetch()
@ -1034,13 +1041,14 @@ class WebmentionTest(testutil.TestCase):
self.assert_object('http://a/follow', self.assert_object('http://a/follow',
domains=['a'], domains=['a'],
source_protocol='activitypub', source_protocol='webmention',
status='failed', status='failed',
mf2=self.follow_mf2, mf2=self.follow_mf2,
as1=self.follow_as1, as1=self.follow_as1,
ap_failed=['https://foo.com/inbox'], ap_failed=['https://foo.com/inbox'],
type='follow', type='follow',
object_ids=['http://followee'], object_ids=['http://followee'],
labels=['user'],
) )
def test_repost_blocklisted_error(self, mock_get, mock_post): def test_repost_blocklisted_error(self, mock_get, mock_post):
@ -1119,11 +1127,12 @@ class WebmentionTest(testutil.TestCase):
} }
self.assert_object(f'https://orig/', self.assert_object(f'https://orig/',
domains=['orig'], domains=['orig'],
source_protocol='activitypub', source_protocol='webmention',
status='complete', status='complete',
mf2=ACTOR_MF2, mf2=ACTOR_MF2,
as1=expected_as1, as1=expected_as1,
ap_delivered=['https://inbox', 'https://shared/inbox'], ap_delivered=['https://inbox', 'https://shared/inbox'],
type='update', type='update',
object_ids=['https://orig'], object_ids=['https://orig'],
labels=['user'],
) )

Wyświetl plik

@ -156,16 +156,16 @@ class Webmention(View):
else: else:
obj = Object(id=self.source_url, obj = Object(id=self.source_url,
ap_undelivered=list(inboxes_to_targets.keys()), ap_undelivered=list(inboxes_to_targets.keys()),
ap_delivered=[], ap_delivered=[], ap_failed=[])
ap_failed=[])
logging.info(f'Storing new {obj}') logging.info(f'Storing new {obj}')
obj.domains = [self.source_domain] obj.domains = [self.source_domain]
obj.source_protocol = 'activitypub' obj.source_protocol = 'webmention'
obj.mf2 = json_dumps(self.source_mf2) obj.mf2 = json_dumps(self.source_mf2)
obj.as1 = json_dumps(self.source_as1) obj.as1 = json_dumps(self.source_as1)
obj.type = type obj.type = type
obj.object_ids = as1.get_ids(self.source_as1, 'object') obj.object_ids = as1.get_ids(self.source_as1, 'object')
obj.labels = ['user']
obj.put() obj.put()
# TODO: collect by inbox, add 'to' fields, de-dupe inboxes and recipients # TODO: collect by inbox, add 'to' fields, de-dupe inboxes and recipients