mirror of
https://github.com/minetest/contentdb.git
synced 2025-01-08 22:17:34 +01:00
Add daily notification digests
This commit is contained in:
parent
35e1659b77
commit
3aa12be544
@ -23,7 +23,7 @@ from wtforms import *
|
||||
from wtforms.validators import *
|
||||
|
||||
from app.models import *
|
||||
from app.tasks.emails import sendVerifyEmail, send_anon_email, sendUnsubscribeVerifyEmail, send_user_email
|
||||
from app.tasks.emails import send_verify_email, send_anon_email, send_unsubscribe_verify, send_user_email
|
||||
from app.utils import randomString, make_flask_login_password, is_safe_url, check_password_hash, addAuditLog
|
||||
from passlib.pwd import genphrase
|
||||
|
||||
@ -126,7 +126,7 @@ def handle_register(form):
|
||||
db.session.add(ver)
|
||||
db.session.commit()
|
||||
|
||||
sendVerifyEmail.delay(form.email.data, token)
|
||||
send_verify_email.delay(form.email.data, token)
|
||||
|
||||
flash("Check your email address to verify your account", "success")
|
||||
return redirect(url_for("homepage.home"))
|
||||
@ -168,7 +168,7 @@ def forgot_password():
|
||||
db.session.add(ver)
|
||||
db.session.commit()
|
||||
|
||||
sendVerifyEmail.delay(form.email.data, token)
|
||||
send_verify_email.delay(form.email.data, token)
|
||||
else:
|
||||
send_anon_email.delay(email, "Unable to find account", """
|
||||
<p>
|
||||
@ -335,7 +335,7 @@ def unsubscribe_verify():
|
||||
|
||||
sub.token = randomString(32)
|
||||
db.session.commit()
|
||||
sendUnsubscribeVerifyEmail.delay(form.email.data)
|
||||
send_unsubscribe_verify.delay(form.email.data)
|
||||
|
||||
flash("Check your email address to continue the unsubscribe", "success")
|
||||
return redirect(url_for("homepage.home"))
|
||||
|
@ -6,7 +6,7 @@ from wtforms.validators import *
|
||||
|
||||
from app.models import *
|
||||
from app.utils import nonEmptyOrNone, addAuditLog, randomString
|
||||
from app.tasks.emails import sendVerifyEmail
|
||||
from app.tasks.emails import send_verify_email
|
||||
from . import bp
|
||||
|
||||
|
||||
@ -141,7 +141,7 @@ def handle_email_notifications(user, prefs: UserNotificationPreferences, is_new,
|
||||
|
||||
flash("Check your email to confirm it", "success")
|
||||
|
||||
sendVerifyEmail.delay(newEmail, token)
|
||||
send_verify_email.delay(newEmail, token)
|
||||
return redirect(url_for("homepage.home"))
|
||||
|
||||
db.session.commit()
|
||||
|
@ -348,10 +348,12 @@ class NotificationType(enum.Enum):
|
||||
else:
|
||||
return ""
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def __lt__(self, other):
|
||||
return self.value < other.value
|
||||
|
||||
@classmethod
|
||||
def choices(cls):
|
||||
return [(choice, choice.getTitle()) for choice in cls]
|
||||
@ -397,6 +399,10 @@ class Notification(db.Model):
|
||||
prefs = self.user.notification_preferences
|
||||
return prefs and self.user.email and prefs.get_can_email(self.type)
|
||||
|
||||
def can_send_digest(self):
|
||||
prefs = self.user.notification_preferences
|
||||
return prefs and self.user.email and prefs.get_can_digest(self.type)
|
||||
|
||||
|
||||
class UserNotificationPreferences(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
|
@ -73,8 +73,12 @@ CELERYBEAT_SCHEDULE = {
|
||||
'schedule': crontab(minute=10, hour=1),
|
||||
},
|
||||
'send_pending_notifications': {
|
||||
'task': 'app.tasks.emails.sendPendingNotifications',
|
||||
'task': 'app.tasks.emails.send_pending_notifications',
|
||||
'schedule': crontab(minute='*/5'),
|
||||
},
|
||||
'send_notification_digests': {
|
||||
'task': 'app.tasks.emails.send_pending_digests',
|
||||
'schedule': crontab(minute=0, hour=14),
|
||||
}
|
||||
}
|
||||
celery.conf.beat_schedule = CELERYBEAT_SCHEDULE
|
||||
|
@ -18,7 +18,7 @@
|
||||
from flask import render_template
|
||||
from flask_mail import Message
|
||||
from app import mail
|
||||
from app.models import Notification, db, EmailSubscription
|
||||
from app.models import Notification, db, EmailSubscription, User
|
||||
from app.tasks import celery
|
||||
from app.utils import abs_url_for, abs_url, randomString
|
||||
|
||||
@ -36,7 +36,7 @@ def get_email_subscription(email):
|
||||
|
||||
|
||||
@celery.task()
|
||||
def sendVerifyEmail(email, token):
|
||||
def send_verify_email(email, token):
|
||||
sub = get_email_subscription(email)
|
||||
if sub.blacklisted:
|
||||
return
|
||||
@ -59,7 +59,7 @@ def sendVerifyEmail(email, token):
|
||||
|
||||
|
||||
@celery.task()
|
||||
def sendUnsubscribeVerifyEmail(email):
|
||||
def send_unsubscribe_verify(email):
|
||||
sub = get_email_subscription(email)
|
||||
if sub.blacklisted:
|
||||
return
|
||||
@ -103,7 +103,7 @@ def send_anon_email(email: str, subject: str, text: str, html=None):
|
||||
"You are receiving this email because someone (hopefully you) entered your email address as a user's email.")
|
||||
|
||||
|
||||
def sendNotificationEmail(notification):
|
||||
def send_single_email(notification):
|
||||
sub = get_email_subscription(notification.user.email)
|
||||
if sub.blacklisted:
|
||||
return
|
||||
@ -125,11 +125,55 @@ def sendNotificationEmail(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)
|
||||
def send_notification_digest(notifications: [Notification]):
|
||||
user = notifications[0].user
|
||||
|
||||
sub = get_email_subscription(user.email)
|
||||
if sub.blacklisted:
|
||||
return
|
||||
|
||||
msg = Message("{} new notifications".format(len(notifications)), recipients=[user.email])
|
||||
|
||||
msg.body = "".join(["<{}> {}\nView: {}\n\n".format(notification.causer.display_name, notification.title, abs_url(notification.url)) for notification in notifications])
|
||||
|
||||
msg.body += "Manage email settings: {}\nUnsubscribe: {}".format(
|
||||
abs_url_for("users.email_notifications", username=user.username),
|
||||
abs_url_for("users.unsubscribe", token=sub.token))
|
||||
|
||||
msg.html = render_template("emails/notification_digest.html", notifications=notifications, user=user, sub=sub)
|
||||
mail.send(msg)
|
||||
|
||||
|
||||
@celery.task()
|
||||
def send_pending_digests():
|
||||
for user in User.query.filter(User.notifications.any(emailed=False)).all():
|
||||
to_send = []
|
||||
for notification in user.notifications:
|
||||
if not notification.emailed and notification.can_send_digest():
|
||||
to_send.append(notification)
|
||||
notification.emailed = True
|
||||
|
||||
if len(to_send) > 0:
|
||||
send_notification_digest(to_send)
|
||||
|
||||
notification.emailed = True
|
||||
db.session.commit()
|
||||
|
||||
|
||||
@celery.task()
|
||||
def send_pending_notifications():
|
||||
for user in User.query.filter(User.notifications.any(emailed=False)).all():
|
||||
to_send = []
|
||||
for notification in user.notifications:
|
||||
if not notification.emailed:
|
||||
if notification.can_send_email():
|
||||
to_send.append(notification)
|
||||
notification.emailed = True
|
||||
elif not notification.can_send_digest():
|
||||
notification.emailed = True
|
||||
|
||||
db.session.commit()
|
||||
|
||||
if len(to_send) > 1:
|
||||
send_notification_digest(to_send)
|
||||
elif len(to_send) > 0:
|
||||
send_single_email(to_send[0])
|
||||
|
39
app/templates/emails/notification_digest.html
Normal file
39
app/templates/emails/notification_digest.html
Normal file
@ -0,0 +1,39 @@
|
||||
{% extends "emails/base.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% for type, group in notifications | groupby("package.title") %}
|
||||
<h2>
|
||||
{{ type or _("Other Notifications") }}
|
||||
</h2>
|
||||
|
||||
<ul>
|
||||
{% for notification in group %}
|
||||
<li>
|
||||
<a href="{{ notification.url | abs_url }}">{{ notification.title }}</a> -
|
||||
{{ _("from %(username)s.", username=notification.causer.display_name) }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endfor %}
|
||||
|
||||
<p style="margin-top: 3em;">
|
||||
<a class="btn" href="{{ abs_url_for('notifications.list_all') }}">
|
||||
View Notifications
|
||||
</a>
|
||||
</p>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block footer %}
|
||||
You are receiving this email because you are a registered user of ContentDB,
|
||||
and have email notifications enabled. <br>
|
||||
|
||||
<a href="{{ abs_url_for('users.email_notifications', username=user.username) }}">
|
||||
{{ _("Manage your preferences") }}
|
||||
</a>
|
||||
|
|
||||
<a href="{{ abs_url_for('users.unsubscribe', token=sub.token) }}">
|
||||
{{ _("Unsubscribe") }}
|
||||
</a> <br>
|
||||
{% endblock %}
|
@ -32,7 +32,6 @@
|
||||
|
||||
<p>
|
||||
Configure whether certain types of notifications are sent immediately, or as part of a daily digest. <br>
|
||||
<i>Note: daily digests aren't implemented yet.</i>
|
||||
</p>
|
||||
|
||||
<table class="table">
|
||||
|
Loading…
Reference in New Issue
Block a user