diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 53eb756ad..c1c548d29 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -187,22 +187,34 @@ def add_status_on_create(sender, instance, created, *args, **kwargs): if not issubclass(sender, models.Status): return - if not created and instance.deleted: + if instance.deleted: for stream in streams.values(): stream.remove_status(instance) return + if not created: + return + # iterates through Home, Local, Federated for stream in streams.values(): stream.add_status(instance) +@receiver(signals.post_delete, sender=models.Boost) +# pylint: disable=unused-argument +def remove_boost_on_delete(sender, instance, *args, **kwargs): + """ boosts are deleted """ + # we're only interested in new statuses + for stream in streams.values(): + stream.remove_status(instance) + + @receiver(signals.post_save, sender=models.UserFollows) # pylint: disable=unused-argument def add_statuses_on_follow(sender, instance, created, *args, **kwargs): """ add a newly followed user's statuses to feeds """ - if not created: - return # idk when this would ever happen though + if not created or not instance.user_subject.local: + return HomeStream().add_user_statuses(instance.user_subject, instance.user_object) @@ -210,6 +222,8 @@ def add_statuses_on_follow(sender, instance, created, *args, **kwargs): # pylint: disable=unused-argument def remove_statuses_on_unfollow(sender, instance, *args, **kwargs): """ remove statuses from a feed on unfollow """ + if not instance.user_subject.local: + return HomeStream().remove_user_statuses(instance.user_subject, instance.user_object) @@ -218,10 +232,30 @@ def remove_statuses_on_unfollow(sender, instance, *args, **kwargs): def remove_statuses_on_block(sender, instance, *args, **kwargs): """ remove statuses from all feeds on block """ # blocks apply ot all feeds - for stream in streams.values(): - # and in both directions - stream.remove_user_statuses(instance.user_subject, instance.user_object) - stream.remove_user_statuses(instance.user_object, instance.user_subject) + if instance.user_subject.local: + for stream in streams.values(): + stream.remove_user_statuses(instance.user_subject, instance.user_object) + + # and in both directions + if instance.user_object.local: + for stream in streams.values(): + stream.remove_user_statuses(instance.user_object, instance.user_subject) + + +@receiver(signals.post_delete, sender=models.UserBlocks) +# pylint: disable=unused-argument +def add_statuses_on_unblock(sender, instance, *args, **kwargs): + """ remove statuses from all feeds on block """ + public_streams = [LocalStream(), FederatedStream()] + # add statuses back to streams with statuses from anyone + if instance.user_subject.local: + for stream in public_streams: + stream.add_user_statuses(instance.user_subject, instance.user_object) + + # add statuses back to streams with statuses from anyone + if instance.user_object.local: + for stream in public_streams: + stream.add_user_statuses(instance.user_object, instance.user_subject) @receiver(signals.post_save, sender=models.User) diff --git a/bookwyrm/tests/views/test_inbox.py b/bookwyrm/tests/views/test_inbox.py index 10f55f89b..7d08a1e49 100644 --- a/bookwyrm/tests/views/test_inbox.py +++ b/bookwyrm/tests/views/test_inbox.py @@ -38,11 +38,12 @@ class Inbox(TestCase): outbox="https://example.com/users/rat/outbox", ) with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): - self.status = models.Status.objects.create( - user=self.local_user, - content="Test status", - remote_id="https://example.com/status/1", - ) + with patch("bookwyrm.activitystreams.ActivityStream.add_status"): + self.status = models.Status.objects.create( + user=self.local_user, + content="Test status", + remote_id="https://example.com/status/1", + ) self.create_json = { "id": "hi", @@ -139,7 +140,9 @@ class Inbox(TestCase): activity = self.create_json activity["object"] = status_data - views.inbox.activity_task(activity) + with patch("bookwyrm.activitystreams.ActivityStream.add_status") as redis_mock: + views.inbox.activity_task(activity) + self.assertTrue(redis_mock.called) status = models.Quotation.objects.get() self.assertEqual( @@ -166,7 +169,9 @@ class Inbox(TestCase): activity = self.create_json activity["object"] = status_data - views.inbox.activity_task(activity) + with patch("bookwyrm.activitystreams.ActivityStream.add_status") as redis_mock: + views.inbox.activity_task(activity) + self.assertTrue(redis_mock.called) status = models.Status.objects.last() self.assertEqual(status.content, "test content in note") self.assertEqual(status.mention_users.first(), self.local_user) @@ -187,7 +192,9 @@ class Inbox(TestCase): activity = self.create_json activity["object"] = status_data - views.inbox.activity_task(activity) + with patch("bookwyrm.activitystreams.ActivityStream.add_status") as redis_mock: + views.inbox.activity_task(activity) + self.assertTrue(redis_mock.called) status = models.Status.objects.last() self.assertEqual(status.content, "test content in note") self.assertEqual(status.reply_parent, self.status) @@ -218,7 +225,7 @@ class Inbox(TestCase): self.assertEqual(book_list.description, "summary text") self.assertEqual(book_list.remote_id, "https://example.com/list/22") - def test_handle_follow_x(self): + def test_handle_follow(self): """ remote user wants to follow local user """ activity = { "@context": "https://www.w3.org/ns/activitystreams", @@ -436,7 +443,11 @@ class Inbox(TestCase): "actor": self.remote_user.remote_id, "object": {"id": self.status.remote_id, "type": "Tombstone"}, } - views.inbox.activity_task(activity) + with patch( + "bookwyrm.activitystreams.ActivityStream.remove_status" + ) as redis_mock: + views.inbox.activity_task(activity) + self.assertTrue(redis_mock.called) # deletion doens't remove the status, it turns it into a tombstone status = models.Status.objects.get() self.assertTrue(status.deleted) @@ -465,7 +476,11 @@ class Inbox(TestCase): "actor": self.remote_user.remote_id, "object": {"id": self.status.remote_id, "type": "Tombstone"}, } - views.inbox.activity_task(activity) + with patch( + "bookwyrm.activitystreams.ActivityStream.remove_status" + ) as redis_mock: + views.inbox.activity_task(activity) + self.assertTrue(redis_mock.called) # deletion doens't remove the status, it turns it into a tombstone status = models.Status.objects.get() self.assertTrue(status.deleted) @@ -535,7 +550,8 @@ class Inbox(TestCase): views.inbox.activity_task(activity) self.assertEqual(models.Favorite.objects.count(), 0) - def test_handle_boost(self): + @patch("bookwyrm.activitystreams.ActivityStream.add_status") + def test_handle_boost(self, _): """ boost a status """ self.assertEqual(models.Notification.objects.count(), 0) activity = { @@ -560,7 +576,8 @@ class Inbox(TestCase): content="hi", user=self.remote_user, ) - status.save(broadcast=False) + with patch("bookwyrm.activitystreams.ActivityStream.add_status"): + status.save(broadcast=False) activity = { "type": "Announce", "id": "http://www.faraway.com/boost/12", @@ -575,9 +592,10 @@ class Inbox(TestCase): def test_handle_unboost(self): """ undo a boost """ - boost = models.Boost.objects.create( - boosted_status=self.status, user=self.remote_user - ) + with patch("bookwyrm.activitystreams.ActivityStream.add_status"): + boost = models.Boost.objects.create( + boosted_status=self.status, user=self.remote_user + ) activity = { "type": "Undo", "actor": "hi", @@ -591,7 +609,11 @@ class Inbox(TestCase): "object": self.status.remote_id, }, } - views.inbox.activity_task(activity) + with patch( + "bookwyrm.activitystreams.ActivityStream.remove_status" + ) as redis_mock: + views.inbox.activity_task(activity) + self.assertTrue(redis_mock.called) def test_handle_unboost_unknown_boost(self): """ undo a boost """ @@ -863,6 +885,11 @@ class Inbox(TestCase): "object": "https://example.com/user/mouse", } + with patch( + "bookwyrm.activitystreams.ActivityStream.remove_user_statuses" + ) as redis_mock: + views.inbox.activity_task(activity) + self.assertTrue(redis_mock.called) views.inbox.activity_task(activity) block = models.UserBlocks.objects.get() self.assertEqual(block.user_subject, self.remote_user) @@ -896,5 +923,9 @@ class Inbox(TestCase): "object": "https://example.com/user/mouse", }, } - views.inbox.activity_task(activity) + with patch( + "bookwyrm.activitystreams.ActivityStream.add_user_statuses" + ) as redis_mock: + views.inbox.activity_task(activity) + self.assertTrue(redis_mock.called) self.assertFalse(models.UserBlocks.objects.exists())