From 9c10e190bc5fe4b617c85af29873f9fab498eeb7 Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Sat, 5 Dec 2020 19:15:33 +0000 Subject: [PATCH] Implement email notifications --- app/blueprints/users/settings.py | 2 +- app/models.py | 4 ++-- app/tasks/__init__.py | 4 ++++ app/tasks/emails.py | 30 +++++++++++++++++++++++++- app/template_filters.py | 6 +++++- app/templates/emails/notification.html | 30 ++++++++++++++++++++++++++ 6 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 app/templates/emails/notification.html diff --git a/app/blueprints/users/settings.py b/app/blueprints/users/settings.py index 2fcd118..7b06198 100644 --- a/app/blueprints/users/settings.py +++ b/app/blueprints/users/settings.py @@ -158,7 +158,7 @@ def email_notifications(username): return redirect(url_for("tasks.check", id=task.id, r=url_for("users.profile", username=username))) db.session.commit() - return redirect(url_for("notifications.settings")) + return redirect(url_for("users.email_notifications", username=username)) return render_template("users/settings_email.html", form=form, user=user, types=types, is_new=is_new, diff --git a/app/models.py b/app/models.py index c9a1609..288756c 100644 --- a/app/models.py +++ b/app/models.py @@ -380,7 +380,7 @@ class Notification(db.Model): def can_send_email(self): prefs = self.user.notification_preferences - return prefs and getattr(prefs, "pref_" + self.type.toName()) == 2 + return prefs and self.user.email and prefs.get_can_email(self.type) class UserNotificationPreferences(db.Model): @@ -407,7 +407,7 @@ class UserNotificationPreferences(db.Model): self.pref_package_edit = 1 self.pref_package_approval = 2 self.pref_new_thread = 2 - self.pref_new_review = 1 + self.pref_new_review = 2 self.pref_thread_reply = 2 self.pref_maintainer = 2 self.pref_editor_alert = 2 diff --git a/app/tasks/__init__.py b/app/tasks/__init__.py index 4166924..e9a01ce 100644 --- a/app/tasks/__init__.py +++ b/app/tasks/__init__.py @@ -71,6 +71,10 @@ CELERYBEAT_SCHEDULE = { 'package_score_update': { 'task': 'app.tasks.pkgtasks.updatePackageScores', 'schedule': crontab(minute=10, hour=1), + }, + 'send_pending_notifications': { + 'task': 'app.tasks.emails.sendPendingNotifications', + 'schedule': crontab(minute='*/5'), } } celery.conf.beat_schedule = CELERYBEAT_SCHEDULE diff --git a/app/tasks/emails.py b/app/tasks/emails.py index 9be6622..0b4967d 100644 --- a/app/tasks/emails.py +++ b/app/tasks/emails.py @@ -18,8 +18,10 @@ from flask import render_template from flask_mail import Message from app import mail +from app.models import Notification, db from app.tasks import celery -from app.utils import abs_url_for +from app.utils import abs_url_for, abs_url + @celery.task() def sendVerifyEmail(newEmail, token): @@ -48,3 +50,29 @@ def sendEmailRaw(to, subject, text, html=None): html = html or text msg.html = render_template("emails/base.html", subject=subject, content=html) mail.send(msg) + + +def sendNotificationEmail(notification): + msg = Message(notification.title, recipients=[notification.user.email]) + + msg.body = """ + New notification: {} + + View: {} + + Manage email settings: {} + """.format(notification.title, abs_url(notification.url), + abs_url_for("users.email_notifications", username=notification.user.username)) + + msg.html = render_template("emails/notification.html", notification=notification) + mail.send(msg) + + +@celery.task() +def sendPendingNotifications(): + for notification in Notification.query.filter_by(emailed=False).all(): + if notification.can_send_email(): + sendNotificationEmail(notification) + + notification.emailed = True + db.session.commit() diff --git a/app/template_filters.py b/app/template_filters.py index 230daa2..3a972d1 100644 --- a/app/template_filters.py +++ b/app/template_filters.py @@ -1,4 +1,4 @@ -from . import app +from . import app, utils from .models import Permission, Package, PackageState, PackageRelease from .utils import abs_url_for, url_set_query from flask_login import current_user @@ -42,3 +42,7 @@ def datetime(value): @app.template_filter() def timedelta(value): return format_timedelta(value) + +@app.template_filter() +def abs_url(url): + return utils.abs_url(url) diff --git a/app/templates/emails/notification.html b/app/templates/emails/notification.html new file mode 100644 index 0000000..1ca295e --- /dev/null +++ b/app/templates/emails/notification.html @@ -0,0 +1,30 @@ +{% extends "emails/base.html" %} + +{% block content %} +

+ {% if notification.package %} + {{ _("New notification on package %(package)s", package=notification.package.title) }} + {% else %} + {{ _("New notification") }} + {% endif %} +

+ +

{{ _("Triggered by %(username)s", username=notification.causer.display_name) }}

+ +

+ {{ notification.title }} +

+ +

+ + View Notification + +

+ +

+ + {{ _("Edit notification settings") }} + +

+ +{% endblock %}