Skip to content

Commit

Permalink
Merge pull request #3257 from dato/prefer_shared_inbox
Browse files Browse the repository at this point in the history
Use shared inboxes for mentions too
  • Loading branch information
mouse-reeve authored Feb 3, 2024
2 parents 438d88d + 8ac8734 commit 0f0420c
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 19 deletions.
25 changes: 13 additions & 12 deletions bookwyrm/models/activitypub_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,9 @@ def get_recipients(self, software=None) -> list[str]:
# find anyone who's tagged in a status, for example
mentions = self.recipients if hasattr(self, "recipients") else []

# we always send activities to explicitly mentioned users' inboxes
recipients = [u.inbox for u in mentions or [] if not u.local]
# we always send activities to explicitly mentioned users (using shared inboxes
# where available to avoid duplicate submissions to a given instance)
recipients = {u.shared_inbox or u.inbox for u in mentions if not u.local}

# unless it's a dm, all the followers should receive the activity
if privacy != "direct":
Expand All @@ -173,18 +174,18 @@ def get_recipients(self, software=None) -> list[str]:
if user:
queryset = queryset.filter(following=user)

# ideally, we will send to shared inboxes for efficiency
shared_inboxes = (
queryset.filter(shared_inbox__isnull=False)
.values_list("shared_inbox", flat=True)
.distinct()
# as above, we prefer shared inboxes if available
recipients.update(
queryset.filter(shared_inbox__isnull=False).values_list(
"shared_inbox", flat=True
)
)
# but not everyone has a shared inbox
inboxes = queryset.filter(shared_inbox__isnull=True).values_list(
"inbox", flat=True
recipients.update(
queryset.filter(shared_inbox__isnull=True).values_list(
"inbox", flat=True
)
)
recipients += list(shared_inboxes) + list(inboxes)
return list(set(recipients))
return list(recipients)

def to_activity_dataclass(self):
"""convert from a model to an activity"""
Expand Down
6 changes: 3 additions & 3 deletions bookwyrm/models/status.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,14 @@ def delete(self, *args, **kwargs): # pylint: disable=unused-argument
@property
def recipients(self):
"""tagged users who definitely need to get this status in broadcast"""
mentions = [u for u in self.mention_users.all() if not u.local]
mentions = {u for u in self.mention_users.all() if not u.local}
if (
hasattr(self, "reply_parent")
and self.reply_parent
and not self.reply_parent.user.local
):
mentions.append(self.reply_parent.user)
return list(set(mentions))
mentions.add(self.reply_parent.user)
return list(mentions)

@classmethod
def ignore_activity(
Expand Down
12 changes: 8 additions & 4 deletions bookwyrm/tests/models/test_activitypub_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,14 +227,18 @@ def test_get_recipients_combine_inboxes(self, *_):
shared_inbox="http://example.com/inbox",
outbox="https://example.com/users/nutria/outbox",
)
MockSelf = namedtuple("Self", ("privacy", "user"))
mock_self = MockSelf("public", self.local_user)
MockSelf = namedtuple("Self", ("privacy", "user", "recipients"))
self.local_user.followers.add(self.remote_user)
self.local_user.followers.add(another_remote_user)

mock_self = MockSelf("public", self.local_user, [])
recipients = ActivitypubMixin.get_recipients(mock_self)
self.assertEqual(len(recipients), 1)
self.assertEqual(recipients[0], "http://example.com/inbox")
self.assertCountEqual(recipients, ["http://example.com/inbox"])

# should also work with recipient that is a follower
mock_self.recipients.append(another_remote_user)
recipients = ActivitypubMixin.get_recipients(mock_self)
self.assertCountEqual(recipients, ["http://example.com/inbox"])

def test_get_recipients_software(self, *_):
"""should differentiate between bookwyrm and other remote users"""
Expand Down

0 comments on commit 0f0420c

Please sign in to comment.