Skip to content

Commit

Permalink
AP users: generalize receiving class in Protocol.receive
Browse files Browse the repository at this point in the history
for #512
  • Loading branch information
snarfed committed Jun 13, 2023
1 parent f951c14 commit 3448ec7
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 26 deletions.
10 changes: 10 additions & 0 deletions activitypub.py
Expand Up @@ -95,6 +95,16 @@ def send(cls, obj, url, log_data=True):
def fetch(cls, obj):
"""Tries to fetch an AS2 object.
Assumes obj.id is a URL. Any fragment at the end is stripped before
loading. This is currently underspecified and somewhat inconsistent
across AP implementations:
https://socialhub.activitypub.rocks/t/problems-posting-to-mastodon-inbox/801/11
https://socialhub.activitypub.rocks/t/problems-posting-to-mastodon-inbox/801/23
https://socialhub.activitypub.rocks/t/s2s-create-activity/1647/5
https://github.com/mastodon/mastodon/issues/13879 (open!)
https://github.com/w3c/activitypub/issues/224
Uses HTTP content negotiation via the Content-Type header. If the url is
HTML and it has a rel-alternate link with an AS2 content type, fetches and
returns that URL.
Expand Down
3 changes: 2 additions & 1 deletion follow.py
Expand Up @@ -116,7 +116,8 @@ def finish(self, auth_entity, state=None):
flash(f"Couldn't find ActivityPub profile link for {addr}")
return redirect(g.user.user_page_path('following'))

# TODO(#512): generalize all this across protocols
# TODO(#512): follower will always be Web here, but we should generalize
# followee support in UI and here across protocols
followee = ActivityPub.load(as2_url)
followee_id = followee.as1.get('id')
inbox = followee.as2.get('inbox')
Expand Down
32 changes: 8 additions & 24 deletions protocol.py
Expand Up @@ -139,7 +139,7 @@ def serve(cls, obj):
For example, an HTML string and `'text/html'` for :class:`Web`,
or a dict with AS2 JSON and `'application/activity+json'` for
:class:`ActivityPub.
:class:`ActivityPub`.
To be implemented by subclasses.
Expand Down Expand Up @@ -250,10 +250,8 @@ def receive(cls, id, **props):

# assume this is an actor
# https://github.com/snarfed/bridgy-fed/issues/63
# TODO(#512): generalize across protocols
logger.info(f'Deactivating Followers from or to = {inner_obj_id}')
from activitypub import ActivityPub
deleted_user = ActivityPub(id=inner_obj_id).key
deleted_user = cls(id=inner_obj_id).key
followers = Follower.query(OR(Follower.to == deleted_user,
Follower.from_ == deleted_user)
).fetch()
Expand Down Expand Up @@ -284,8 +282,7 @@ def receive(cls, id, **props):
if (actor and actor_id and
(obj.type == 'share' or obj.type in ('create', 'post') and not is_reply)):
logger.info(f'Delivering to followers of {actor_id}')
from activitypub import ActivityPub
for f in Follower.query(Follower.to == ActivityPub(id=actor_id).key,
for f in Follower.query(Follower.to == cls(id=actor_id).key,
Follower.status == 'active'):
if f.from_ not in obj.users:
obj.users.append(f.from_)
Expand Down Expand Up @@ -315,17 +312,14 @@ def accept_follow(cls, obj):
if not inbox or not follower_id:
error(f'Follow actor requires id and inbox. Got: {follower}')

# store Follower and follower ActivityPub user.
# store Follower and follower User
#
# If followee user is already direct, AP follower may not know they're
# interacting with a bridge. If followee user is indirect though, AP
# follower should know, so they're direct.
#
# TODO(#512): generalize across protocols
from activitypub import ActivityPub
from_ = ActivityPub.get_or_create(id=follower_id,
actor_as2=as2.from_as1(follower),
direct=not g.user.direct)
from_ = cls.get_or_create(id=follower_id,
actor_as2=as2.from_as1(follower),
direct=not g.user.direct)
follower_obj = Follower.get_or_create(to=g.user, from_=from_, follow=obj.key,
status='active')

Expand Down Expand Up @@ -373,7 +367,7 @@ def deliver(cls, obj):
targets = util.dedupe_urls(util.get_url(t) for t in targets)
targets = common.remove_blocklisted(t.lower() for t in targets)
if not targets:
logger.info("Couldn't find any IndieWeb target URLs in inReplyTo, object, or mention tags")
logger.info("Couldn't find any target URLs in inReplyTo, object, or mention tags")
return

logger.info(f'targets: {targets}')
Expand Down Expand Up @@ -442,16 +436,6 @@ def deliver(cls, obj):
def load(cls, id, refresh=False, **kwargs):
"""Loads and returns an Object from memory cache, datastore, or HTTP fetch.
Assumes id is a URL. Any fragment at the end is stripped before loading.
This is currently underspecified and somewhat inconsistent across AP
implementations:
https://socialhub.activitypub.rocks/t/problems-posting-to-mastodon-inbox/801/11
https://socialhub.activitypub.rocks/t/problems-posting-to-mastodon-inbox/801/23
https://socialhub.activitypub.rocks/t/s2s-create-activity/1647/5
https://github.com/mastodon/mastodon/issues/13879 (open!)
https://github.com/w3c/activitypub/issues/224
Note that :meth:`Object._post_put_hook` updates the cache.
Args:
Expand Down
2 changes: 1 addition & 1 deletion webfinger.py
Expand Up @@ -140,7 +140,7 @@ def template_vars(self):
# https://github.com/snarfed/bridgy-fed/issues/60#issuecomment-1325589750
{
'rel': 'http://ostatus.org/schema/1.0/subscribe',
# TODO(#512) switch to:
# TODO: switch to:
# 'template': common.host_url(g.user.user_page_path('?url={uri}')),
# the problem is that user_page_path() uses readable_id, which uses
# custom username instead of domain, which may not be unique
Expand Down

0 comments on commit 3448ec7

Please sign in to comment.