diff options
author | Stephen Finucane <stephenfinucane@hotmail.com> | 2016-08-22 15:06:48 +0100 |
---|---|---|
committer | Stephen Finucane <stephenfinucane@hotmail.com> | 2016-09-07 21:17:41 +0100 |
commit | ff4a10f47d9839056c67f50d07044e2ce05386a0 (patch) | |
tree | 4006b5c5a7bd74eb18e9e1484e142c244370ddbb /patchwork/notifications.py | |
parent | 804ff045e0893249bc80d0bd96de3e963faf7a46 (diff) | |
download | patchwork-ff4a10f47d9839056c67f50d07044e2ce05386a0.tar patchwork-ff4a10f47d9839056c67f50d07044e2ce05386a0.tar.gz |
utils: Rename to 'notifications'
Every function in this file is related to notifications. Rename the
file and functions therein to something more meaningful.
Signed-off-by: Stephen Finucane <stephenfinucane@hotmail.com>
Diffstat (limited to 'patchwork/notifications.py')
-rw-r--r-- | patchwork/notifications.py | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/patchwork/notifications.py b/patchwork/notifications.py new file mode 100644 index 0000000..5420401 --- /dev/null +++ b/patchwork/notifications.py @@ -0,0 +1,116 @@ +# Patchwork - automated patch tracking system +# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> +# +# This file is part of the Patchwork package. +# +# Patchwork is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Patchwork is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Patchwork; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +import datetime +import itertools + +from django.conf import settings +from django.contrib.auth.models import User +from django.contrib.sites.models import Site +from django.core.mail import EmailMessage +from django.db.models import Count, Q, F + +from patchwork.compat import render_to_string +from patchwork.models import EmailConfirmation +from patchwork.models import EmailOptout +from patchwork.models import PatchChangeNotification + + +def send_notifications(): + date_limit = datetime.datetime.now() - datetime.timedelta( + minutes=settings.NOTIFICATION_DELAY_MINUTES) + + # We delay sending notifications to a user if they have other + # notifications that are still in the "pending" state. To do this, + # we compare the total number of patch change notifications queued + # for each user against the number of "ready" notifications. + qs = PatchChangeNotification.objects.all() + qs2 = PatchChangeNotification.objects\ + .filter(last_modified__lt=date_limit)\ + .values('patch__submitter')\ + .annotate(count=Count('patch__submitter')) + qs2 = {elem['patch__submitter']: elem['count'] for elem in qs2} + + groups = itertools.groupby(qs.order_by('patch__submitter'), + lambda n: n.patch.submitter) + + errors = [] + + for (recipient, notifications) in groups: + notifications = list(notifications) + + if recipient.id not in qs2 or qs2[recipient.id] < len(notifications): + continue + + projects = set([n.patch.project.linkname for n in notifications]) + + def delete_notifications(): + pks = [n.pk for n in notifications] + PatchChangeNotification.objects.filter(pk__in=pks).delete() + + if EmailOptout.is_optout(recipient.email): + delete_notifications() + continue + + context = { + 'site': Site.objects.get_current(), + 'notifications': notifications, + 'projects': projects, + } + + subject = render_to_string( + 'patchwork/patch-change-notification-subject.text', + context).strip() + content = render_to_string('patchwork/patch-change-notification.mail', + context) + + message = EmailMessage(subject=subject, body=content, + from_email=settings.NOTIFICATION_FROM_EMAIL, + to=[recipient.email], + headers={'Precedence': 'bulk'}) + + try: + message.send() + except Exception as ex: + errors.append((recipient, ex)) + continue + + delete_notifications() + + return errors + + +def expire_notifications(): + """Expire any pending confirmations. + + Users whose registration confirmation has expired are removed. + """ + # expire any invalid confirmations + q = (Q(date__lt=datetime.datetime.now() - EmailConfirmation.validity) | + Q(active=False)) + EmailConfirmation.objects.filter(q).delete() + + # remove inactive users with no pending confirmation + pending_confs = EmailConfirmation.objects.values('user') + users = User.objects.filter(is_active=False, + last_login=F('date_joined')).exclude( + id__in=pending_confs) + + # delete users + users.delete() |