Mercurial > public > sg101
comparison gpp/forums/views/subscriptions.py @ 301:ee451ad46af1
Fixing #140; limit topic notification emails to at most 1 per day, or more if the user visits the topic.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Thu, 13 Jan 2011 03:27:42 +0000 |
parents | a46788862737 |
children | b2b37cdd020a |
comparison
equal
deleted
inserted
replaced
300:58e9b8b2965f | 301:ee451ad46af1 |
---|---|
1 """This module handles the subscriptions of users to forum topics.""" | 1 """This module handles the subscriptions of users to forum topics.""" |
2 import datetime | |
3 | |
2 from django.conf import settings | 4 from django.conf import settings |
3 from django.contrib.auth.decorators import login_required | 5 from django.contrib.auth.decorators import login_required |
4 from django.contrib.sites.models import Site | 6 from django.contrib.sites.models import Site |
5 from django.core.paginator import InvalidPage | 7 from django.core.paginator import InvalidPage |
6 from django.core.urlresolvers import reverse | 8 from django.core.urlresolvers import reverse |
10 from django.shortcuts import get_object_or_404 | 12 from django.shortcuts import get_object_or_404 |
11 from django.shortcuts import render_to_response | 13 from django.shortcuts import render_to_response |
12 from django.template import RequestContext | 14 from django.template import RequestContext |
13 from django.views.decorators.http import require_POST | 15 from django.views.decorators.http import require_POST |
14 | 16 |
15 from forums.models import Topic | 17 from forums.models import Topic, TopicLastVisit, Subscription |
16 from core.functions import send_mail | 18 from core.functions import send_mail |
17 from core.paginator import DiggPaginator | 19 from core.paginator import DiggPaginator |
18 | 20 |
19 | 21 |
22 # This constant is the minimum amount of time a user will be | |
23 # notified of new posts in a topic. Currently it is set to 1 day. | |
24 # Thus a user will be notified at most once per day of new posts. | |
25 TOPIC_NOTIFY_DELAY = datetime.timedelta(days=1) | |
26 | |
27 | |
20 def notify_topic_subscribers(post): | 28 def notify_topic_subscribers(post): |
21 """The argument post is a newly created post. Send out an email | 29 """ |
22 notification to all subscribers of the post's parent Topic.""" | 30 The argument post is a newly created post. Send out an email |
31 notification to all subscribers of the post's parent Topic. | |
32 The emails are throttled such that unless the user visits the topic, | |
33 only 1 email will be sent per TOPIC_NOTIFY_DELAY period. | |
34 Visiting the topic will reset this delay. | |
35 | |
36 """ | |
37 #TODO: consider moving this function of the HTTP request/response cycle. | |
23 | 38 |
24 topic = post.topic | 39 topic = post.topic |
25 recipients = topic.subscribers.exclude( | 40 subscriptions = Subscription.objects.filter(topic=post.topic).exclude( |
26 id=post.user.id).values_list('email', flat=True) | 41 user=post.user).select_related() |
42 | |
43 if not subscriptions: | |
44 return | |
45 | |
46 subscriber_ids = [sub.user.id for sub in subscriptions] | |
47 tlvs = dict(TopicLastVisit.objects.filter(topic=topic, | |
48 user__in=subscriber_ids).values_list('user', 'last_visit')) | |
49 | |
50 recipients = [] | |
51 for sub in subscriptions: | |
52 if (sub.notify_date is None or | |
53 post.creation_date - sub.notify_date > TOPIC_NOTIFY_DELAY or | |
54 tlvs.get(sub.user.id, datetime.datetime.min) > sub.notify_date): | |
55 | |
56 recipients.append(sub.user.email) | |
57 sub.notify_date = post.creation_date | |
58 sub.save() | |
27 | 59 |
28 if recipients: | 60 if recipients: |
29 site = Site.objects.get_current() | 61 site = Site.objects.get_current() |
30 subject = "[%s] Topic Reply: %s" % (site.name, topic.name) | 62 subject = "[%s] Topic Reply: %s" % (site.name, topic.name) |
31 url_prefix = "http://%s" % site.domain | 63 url_prefix = "http://%s" % site.domain |
46 @require_POST | 78 @require_POST |
47 def subscribe_topic(request, topic_id): | 79 def subscribe_topic(request, topic_id): |
48 """Subscribe the user to the requested topic.""" | 80 """Subscribe the user to the requested topic.""" |
49 topic = get_object_or_404(Topic.objects.select_related(), id=topic_id) | 81 topic = get_object_or_404(Topic.objects.select_related(), id=topic_id) |
50 if topic.forum.category.can_access(request.user): | 82 if topic.forum.category.can_access(request.user): |
51 topic.subscribers.add(request.user) | 83 sub = Subscription(topic=topic, user=request.user) |
84 sub.save() | |
52 return HttpResponseRedirect( | 85 return HttpResponseRedirect( |
53 reverse("forums-subscription_status", args=[topic.id])) | 86 reverse("forums-subscription_status", args=[topic.id])) |
54 raise Http404 # TODO return HttpResponseForbidden instead | 87 raise Http404 # TODO return HttpResponseForbidden instead |
55 | 88 |
56 | 89 |
57 @login_required | 90 @login_required |
58 @require_POST | 91 @require_POST |
59 def unsubscribe_topic(request, topic_id): | 92 def unsubscribe_topic(request, topic_id): |
60 """Unsubscribe the user to the requested topic.""" | 93 """Unsubscribe the user to the requested topic.""" |
61 topic = get_object_or_404(Topic, id=topic_id) | 94 topic = get_object_or_404(Topic, id=topic_id) |
62 topic.subscribers.remove(request.user) | 95 try: |
96 sub = Subscription.objects.get(topic=topic, user=request.user) | |
97 except Subscriptions.DoesNotExist: | |
98 pass | |
99 else: | |
100 sub.delete() | |
63 return HttpResponseRedirect( | 101 return HttpResponseRedirect( |
64 reverse("forums-subscription_status", args=[topic.id])) | 102 reverse("forums-subscription_status", args=[topic.id])) |
65 | 103 |
66 | 104 |
67 @login_required | 105 @login_required |