Browse Source

automatically subscribe to started/replied threads

Rafał Pitoń 8 years ago
parent
commit
5c5f63e291

+ 1 - 0
misago/conf/defaults.py

@@ -137,6 +137,7 @@ MISAGO_POSTING_MIDDLEWARES = (
     # 'misago.threads.api.postingendpoint.recordedit.RecordEditMiddleware',
     'misago.threads.api.postingendpoint.updatestats.UpdateStatsMiddleware',
     'misago.threads.api.postingendpoint.mentions.MentionsMiddleware',
+    'misago.threads.api.postingendpoint.subscribe.SubscribeMiddleware',
     # Note: always keep SaveChangesMiddleware middleware last one
     'misago.threads.api.postingendpoint.savechanges.SaveChangesMiddleware',
 )

+ 50 - 0
misago/threads/api/postingendpoint/subscribe.py

@@ -0,0 +1,50 @@
+from misago.users.models import (
+    AUTO_SUBSCRIBE_NONE, AUTO_SUBSCRIBE_NOTIFY, AUTO_SUBSCRIBE_NOTIFY_AND_EMAIL)
+
+from ...models import Subscription
+from . import PostingEndpoint, PostingMiddleware
+
+
+class SubscribeMiddleware(PostingMiddleware):
+    def use_this_middleware(self):
+        return self.mode != PostingEndpoint.EDIT
+
+    def post_save(self, serializer):
+        self.subscribe_new_thread()
+        self.subscribe_replied_thread()
+
+    def subscribe_new_thread(self):
+        if self.mode != PostingEndpoint.START:
+            return
+
+        if self.user.subscribe_to_started_threads == AUTO_SUBSCRIBE_NONE:
+            return
+
+        self.user.subscription_set.create(
+            category=self.thread.category,
+            thread=self.thread,
+            send_email=self.user.subscribe_to_started_threads == AUTO_SUBSCRIBE_NOTIFY_AND_EMAIL
+        )
+
+    def subscribe_replied_thread(self):
+        if self.mode != PostingEndpoint.REPLY:
+            return
+
+        if self.user.subscribe_to_replied_threads == AUTO_SUBSCRIBE_NONE:
+            return
+
+        try:
+            subscription = self.user.subscription_set.get(thread=self.thread)
+            return
+        except Subscription.DoesNotExist:
+            pass
+
+        # we are replying to thread again?
+        if self.user.post_set.filter(thread=self.thread).count() > 1:
+            return
+
+        self.user.subscription_set.create(
+            category=self.thread.category,
+            thread=self.thread,
+            send_email=self.user.subscribe_to_replied_threads == AUTO_SUBSCRIBE_NOTIFY_AND_EMAIL
+        )

+ 167 - 0
misago/threads/tests/test_subscription_middleware.py

@@ -0,0 +1,167 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.core.urlresolvers import reverse
+
+from misago.acl.testutils import override_acl
+from misago.categories.models import Category
+from misago.users.models import (
+    AUTO_SUBSCRIBE_NONE, AUTO_SUBSCRIBE_NOTIFY, AUTO_SUBSCRIBE_NOTIFY_AND_EMAIL)
+from misago.users.testutils import AuthenticatedUserTestCase
+
+from .. import testutils
+
+
+class SubscriptionMiddlewareTestCase(AuthenticatedUserTestCase):
+    def setUp(self):
+        super(SubscriptionMiddlewareTestCase, self).setUp()
+        self.category = Category.objects.get(slug='first-category')
+        self.override_acl()
+
+    def override_acl(self):
+        new_acl = self.user.acl
+        new_acl['can_omit_flood_protection'] = True
+        new_acl['categories'][self.category.pk].update({
+            'can_see': 1,
+            'can_browse': 1,
+            'can_start_threads': 1,
+            'can_reply_threads': 1
+        })
+
+        override_acl(self.user, new_acl)
+
+
+class SubscribeStartedThreadTests(SubscriptionMiddlewareTestCase):
+    def setUp(self):
+        super(SubscribeStartedThreadTests, self).setUp()
+        self.api_link = reverse('misago:api:thread-list')
+
+    def test_dont_subscribe(self):
+        """middleware makes no subscription to thread"""
+        self.user.subscribe_to_started_threads = AUTO_SUBSCRIBE_NONE
+        self.user.subscribe_to_replied_threads = AUTO_SUBSCRIBE_NOTIFY
+        self.user.save()
+
+        response = self.client.post(self.api_link, data={
+            'category': self.category.id,
+            'title': "This is an test thread!",
+            'post': "This is test response!"
+        })
+        self.assertEqual(response.status_code, 200)
+
+        # user has no subscriptions
+        self.assertEqual(self.user.subscription_set.count(), 0)
+
+    def test_subscribe(self):
+        """middleware subscribes thread"""
+        self.user.subscribe_to_started_threads = AUTO_SUBSCRIBE_NOTIFY
+        self.user.save()
+
+        response = self.client.post(self.api_link, data={
+            'category': self.category.id,
+            'title': "This is an test thread!",
+            'post': "This is test response!"
+        })
+        self.assertEqual(response.status_code, 200)
+
+        # user has subscribed to thread
+        thread = self.user.thread_set.order_by('id').last()
+        subscription = self.user.subscription_set.get(thread=thread)
+
+        self.assertEqual(subscription.category_id, self.category.id)
+        self.assertFalse(subscription.send_email)
+
+    def test_email_subscribe(self):
+        """middleware subscribes thread with an email"""
+        self.user.subscribe_to_started_threads = AUTO_SUBSCRIBE_NOTIFY_AND_EMAIL
+        self.user.save()
+
+        response = self.client.post(self.api_link, data={
+            'category': self.category.id,
+            'title': "This is an test thread!",
+            'post': "This is test response!"
+        })
+        self.assertEqual(response.status_code, 200)
+
+        # user has subscribed to thread
+        thread = self.user.thread_set.order_by('id').last()
+        subscription = self.user.subscription_set.get(thread=thread)
+
+        self.assertEqual(subscription.category_id, self.category.id)
+        self.assertTrue(subscription.send_email)
+
+
+class SubscribeRepliedThreadTests(SubscriptionMiddlewareTestCase):
+    def setUp(self):
+        super(SubscribeRepliedThreadTests, self).setUp()
+        self.thread = testutils.post_thread(self.category)
+        self.api_link = reverse('misago:api:thread-post-list', kwargs={
+            'thread_pk': self.thread.pk
+        })
+
+    def test_dont_subscribe(self):
+        """middleware makes no subscription to thread"""
+        self.user.subscribe_to_started_threads = AUTO_SUBSCRIBE_NOTIFY
+        self.user.subscribe_to_replied_threads = AUTO_SUBSCRIBE_NONE
+        self.user.save()
+
+        response = self.client.post(self.api_link, data={
+            'post': "This is test response!"
+        })
+        self.assertEqual(response.status_code, 200)
+
+        # user has no subscriptions
+        self.assertEqual(self.user.subscription_set.count(), 0)
+
+    def test_subscribe(self):
+        """middleware subscribes thread"""
+        self.user.subscribe_to_replied_threads = AUTO_SUBSCRIBE_NOTIFY
+        self.user.save()
+
+        response = self.client.post(self.api_link, data={
+            'post': "This is test response!"
+        })
+        self.assertEqual(response.status_code, 200)
+
+        # user has subscribed to thread
+        subscription = self.user.subscription_set.get(thread=self.thread)
+
+        self.assertEqual(subscription.category_id, self.category.id)
+        self.assertFalse(subscription.send_email)
+
+    def test_email_subscribe(self):
+        """middleware subscribes thread with an email"""
+        self.user.subscribe_to_replied_threads = AUTO_SUBSCRIBE_NOTIFY_AND_EMAIL
+        self.user.save()
+
+        response = self.client.post(self.api_link, data={
+            'post': "This is test response!"
+        })
+        self.assertEqual(response.status_code, 200)
+
+        # user has subscribed to thread
+        subscription = self.user.subscription_set.get(thread=self.thread)
+
+        self.assertEqual(subscription.category_id, self.category.id)
+        self.assertTrue(subscription.send_email)
+
+    def test_dont_subscribe_replied(self):
+        """middleware omits threads user already replied"""
+        self.user.subscribe_to_replied_threads = AUTO_SUBSCRIBE_NOTIFY_AND_EMAIL
+        self.user.save()
+
+        response = self.client.post(self.api_link, data={
+            'post': "This is test response!"
+        })
+        self.assertEqual(response.status_code, 200)
+
+        # clear subscription
+        self.user.subscription_set.all().delete()
+        # reply again
+        response = self.client.post(self.api_link, data={
+            'post': "This is test response!"
+        })
+        self.assertEqual(response.status_code, 200)
+
+        # user has no subscriptions
+        self.assertEqual(self.user.subscription_set.count(), 0)