diff --git a/bookwyrm/models/activitypub_mixin.py b/bookwyrm/models/activitypub_mixin.py index de440e425..7d5b5beb2 100644 --- a/bookwyrm/models/activitypub_mixin.py +++ b/bookwyrm/models/activitypub_mixin.py @@ -129,11 +129,16 @@ class ActivitypubMixin: # unless it's a dm, all the followers should receive the activity if privacy != 'direct': + # we will send this out to a subset of all remote users + queryset = user_model.objects.filter( + local=False, + ) # filter users first by whether they're using the desired software # this lets us send book updates only to other bw servers - queryset = user_model.objects.filter( - bookwyrm_user=(software == 'bookwyrm') - ) + if software: + queryset = queryset.filter( + bookwyrm_user=(software == 'bookwyrm') + ) # if there's a user, we only want to send to the user's followers if user: queryset = queryset.filter(following=user) diff --git a/bookwyrm/tests/models/test_activitypub_mixin.py b/bookwyrm/tests/models/test_activitypub_mixin.py index ba6c14894..300e94aad 100644 --- a/bookwyrm/tests/models/test_activitypub_mixin.py +++ b/bookwyrm/tests/models/test_activitypub_mixin.py @@ -8,6 +8,7 @@ from django.test import TestCase from bookwyrm.activitypub.base_activity import ActivityObject from bookwyrm import models from bookwyrm.models import base_model +from bookwyrm.models import activitypub_mixin from bookwyrm.models.activitypub_mixin import ActivitypubMixin from bookwyrm.models.activitypub_mixin import ActivityMixin, ObjectMixin @@ -20,6 +21,14 @@ class ActivitypubMixins(TestCase): local=True, localname='mouse') self.local_user.remote_id = 'http://example.com/a/b' self.local_user.save(broadcast=False) + with patch('bookwyrm.models.user.set_remote_server.delay'): + self.remote_user = models.User.objects.create_user( + 'rat', 'rat@rat.com', 'ratword', + local=False, + remote_id='https://example.com/users/rat', + inbox='https://example.com/users/rat/inbox', + outbox='https://example.com/users/rat/outbox', + ) # ActivitypubMixin @@ -88,12 +97,129 @@ class ActivitypubMixins(TestCase): self.assertEqual(result, book) - def test_get_recipients(self): - ''' determines the recipients for a broadcast ''' + def test_get_recipients_public_object(self): + ''' determines the recipients for an object's broadcast ''' MockSelf = namedtuple('Self', ('privacy')) mock_self = MockSelf('public') - ActivitypubMixin.get_recipients(mock_self) - + recipients = ActivitypubMixin.get_recipients(mock_self) + self.assertEqual(len(recipients), 1) + self.assertEqual(recipients[0], self.remote_user.inbox) + + + def test_get_recipients_public_user_object_no_followers(self): + ''' determines the recipients for a user's object broadcast ''' + MockSelf = namedtuple('Self', ('privacy', 'user')) + mock_self = MockSelf('public', self.local_user) + + recipients = ActivitypubMixin.get_recipients(mock_self) + self.assertEqual(len(recipients), 0) + + + def test_get_recipients_public_user_object(self): + ''' determines the recipients for a user's object broadcast ''' + MockSelf = namedtuple('Self', ('privacy', 'user')) + mock_self = MockSelf('public', self.local_user) + self.local_user.followers.add(self.remote_user) + + recipients = ActivitypubMixin.get_recipients(mock_self) + self.assertEqual(len(recipients), 1) + self.assertEqual(recipients[0], self.remote_user.inbox) + + + def test_get_recipients_public_user_object_with_mention(self): + ''' determines the recipients for a user's object broadcast ''' + MockSelf = namedtuple('Self', ('privacy', 'user')) + mock_self = MockSelf('public', self.local_user) + self.local_user.followers.add(self.remote_user) + with patch('bookwyrm.models.user.set_remote_server.delay'): + another_remote_user = models.User.objects.create_user( + 'nutria', 'nutria@nutria.com', 'nutriaword', + local=False, + remote_id='https://example.com/users/nutria', + inbox='https://example.com/users/nutria/inbox', + outbox='https://example.com/users/nutria/outbox', + ) + MockMentions = namedtuple('Mentions', ('all')) + mock_mentions = MockMentions(lambda: [another_remote_user]) + MockSelf = namedtuple('Self', ('privacy', 'user', 'mention_users')) + mock_self = MockSelf('public', self.local_user, mock_mentions) + + recipients = ActivitypubMixin.get_recipients(mock_self) + self.assertEqual(len(recipients), 2) + self.assertEqual(recipients[0], another_remote_user.inbox) + self.assertEqual(recipients[1], self.remote_user.inbox) + + + def test_get_recipients_direct(self): + ''' determines the recipients for a user's object broadcast ''' + MockSelf = namedtuple('Self', ('privacy', 'user')) + mock_self = MockSelf('public', self.local_user) + self.local_user.followers.add(self.remote_user) + with patch('bookwyrm.models.user.set_remote_server.delay'): + another_remote_user = models.User.objects.create_user( + 'nutria', 'nutria@nutria.com', 'nutriaword', + local=False, + remote_id='https://example.com/users/nutria', + inbox='https://example.com/users/nutria/inbox', + outbox='https://example.com/users/nutria/outbox', + ) + MockMentions = namedtuple('Mentions', ('all')) + mock_mentions = MockMentions(lambda: [another_remote_user]) + MockSelf = namedtuple('Self', ('privacy', 'user', 'mention_users')) + mock_self = MockSelf('direct', self.local_user, mock_mentions) + + recipients = ActivitypubMixin.get_recipients(mock_self) + self.assertEqual(len(recipients), 1) + self.assertEqual(recipients[0], another_remote_user.inbox) + + + def test_get_recipients_combine_inboxes(self): + self.remote_user.shared_inbox = 'http://example.com/inbox' + self.remote_user.save(broadcast=False) + with patch('bookwyrm.models.user.set_remote_server.delay'): + another_remote_user = models.User.objects.create_user( + 'nutria', 'nutria@nutria.com', 'nutriaword', + local=False, + remote_id='https://example.com/users/nutria', + inbox='https://example.com/users/nutria/inbox', + 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) + self.local_user.followers.add(self.remote_user) + self.local_user.followers.add(another_remote_user) + + recipients = ActivitypubMixin.get_recipients(mock_self) + self.assertEqual(len(recipients), 1) + self.assertEqual(recipients[0], 'http://example.com/inbox') + + + def test_get_recipients_software(self): + with patch('bookwyrm.models.user.set_remote_server.delay'): + another_remote_user = models.User.objects.create_user( + 'nutria', 'nutria@nutria.com', 'nutriaword', + local=False, + remote_id='https://example.com/users/nutria', + inbox='https://example.com/users/nutria/inbox', + outbox='https://example.com/users/nutria/outbox', + bookwyrm_user=False, + ) + MockSelf = namedtuple('Self', ('privacy', 'user')) + mock_self = MockSelf('public', self.local_user) + self.local_user.followers.add(self.remote_user) + self.local_user.followers.add(another_remote_user) + + recipients = ActivitypubMixin.get_recipients(mock_self) + self.assertEqual(len(recipients), 2) + + recipients = ActivitypubMixin.get_recipients(mock_self, software='bookwyrm') + self.assertEqual(len(recipients), 1) + self.assertEqual(recipients[0], self.remote_user.inbox) + + recipients = ActivitypubMixin.get_recipients(mock_self, software='other') + self.assertEqual(len(recipients), 1) + self.assertEqual(recipients[0], another_remote_user.inbox) # ObjectMixin diff --git a/bookwyrm/tests/test_broadcast.py b/bookwyrm/tests/test_broadcast.py deleted file mode 100644 index 6344a9f00..000000000 --- a/bookwyrm/tests/test_broadcast.py +++ /dev/null @@ -1,80 +0,0 @@ -from unittest.mock import patch -from django.test import TestCase - -from bookwyrm import models, broadcast - - -class Broadcast(TestCase): - def setUp(self): - self.user = models.User.objects.create_user( - 'mouse', 'mouse@mouse.mouse', 'mouseword', - local=True, localname='mouse') - - local_follower = models.User.objects.create_user( - 'joe', 'joe@mouse.mouse', 'jeoword', - local=True, localname='joe') - self.user.followers.add(local_follower) - - with patch('bookwyrm.models.user.set_remote_server.delay'): - follower = models.User.objects.create_user( - 'rat', 'rat@mouse.mouse', 'ratword', local=False, - remote_id='http://example.com/u/1', - outbox='http://example.com/u/1/o', - shared_inbox='http://example.com/inbox', - inbox='http://example.com/u/1/inbox') - self.user.followers.add(follower) - - no_inbox_follower = models.User.objects.create_user( - 'hamster', 'hamster@mouse.mouse', 'hamword', - shared_inbox=None, local=False, - remote_id='http://example.com/u/2', - outbox='http://example.com/u/2/o', - inbox='http://example.com/u/2/inbox') - self.user.followers.add(no_inbox_follower) - - non_bw_follower = models.User.objects.create_user( - 'gerbil', 'gerb@mouse.mouse', 'gerbword', - remote_id='http://example.com/u/3', - outbox='http://example2.com/u/3/o', - inbox='http://example2.com/u/3/inbox', - shared_inbox='http://example2.com/inbox', - bookwyrm_user=False, local=False) - self.user.followers.add(non_bw_follower) - - models.User.objects.create_user( - 'nutria', 'nutria@mouse.mouse', 'nuword', - remote_id='http://example.com/u/4', - outbox='http://example.com/u/4/o', - shared_inbox='http://example.com/inbox', - inbox='http://example.com/u/4/inbox', - local=False) - - - def test_get_public_recipients(self): - expected = [ - 'http://example2.com/inbox', - 'http://example.com/inbox', - 'http://example.com/u/2/inbox', - ] - - recipients = broadcast.get_public_recipients(self.user) - self.assertEqual(recipients, expected) - - - def test_get_public_recipients_software(self): - expected = [ - 'http://example.com/inbox', - 'http://example.com/u/2/inbox', - ] - - recipients = broadcast.get_public_recipients(self.user, software='bookwyrm') - self.assertEqual(recipients, expected) - - - def test_get_public_recipients_software_other(self): - expected = [ - 'http://example2.com/inbox', - ] - - recipients = broadcast.get_public_recipients(self.user, software='mastodon') - self.assertEqual(recipients, expected)