Send users push notifications when they miss messages

(imported from commit 6c54fe44a82c5796268e56d3f5577bf4cfc8163a)
This commit is contained in:
Leo Franchi
2013-10-23 14:29:07 -04:00
parent 05564ec0e2
commit 410ee44eb6
3 changed files with 75 additions and 40 deletions

View File

@@ -43,6 +43,7 @@ from zerver.lib.utils import log_statsd_event, statsd
from zerver.lib.html_diff import highlight_html_differences from zerver.lib.html_diff import highlight_html_differences
from zerver.lib.alert_words import user_alert_words, add_user_alert_words, \ from zerver.lib.alert_words import user_alert_words, add_user_alert_words, \
remove_user_alert_words, set_user_alert_words remove_user_alert_words, set_user_alert_words
from zerver.lib.push_notifications import num_push_devices_for_user, send_apple_push_notification
import confirmation.settings import confirmation.settings
@@ -1886,57 +1887,77 @@ def build_message_list(user_profile, messages):
return messages_to_render return messages_to_render
@statsd_increment("missed_message_reminders") @statsd_increment("missed_message_reminders")
def do_send_missedmessage_email(user_profile, missed_messages): def do_send_missedmessage_events(user_profile, missed_messages):
""" """
Send a reminder email to a user if she's missed some PMs by being offline Send a reminder email and/or push notifications to a user if she's missed some PMs by being offline
`user_profile` is the user to send the reminder to `user_profile` is the user to send the reminder to
`missed_messages` is a list of Message objects to remind about `missed_messages` is a list of Message objects to remind about
""" """
template_payload = {'name': user_profile.full_name,
'messages': build_message_list(user_profile, missed_messages),
'message_count': len(missed_messages),
'url': 'https://zulip.com',
'reply_warning': False}
senders = set(m.sender.full_name for m in missed_messages) senders = set(m.sender.full_name for m in missed_messages)
sender_str = ", ".join(senders) sender_str = ", ".join(senders)
plural_messages = 's' if len(missed_messages) > 1 else ''
headers = {} if user_profile.enable_offline_email_notifications:
if all(msg.recipient.type in (Recipient.HUDDLE, Recipient.PERSONAL) template_payload = {'name': user_profile.full_name,
for msg in missed_messages): 'messages': build_message_list(user_profile, missed_messages),
# If we have one huddle, set a reply-to to all of the members 'message_count': len(missed_messages),
# of the huddle except the user herself 'url': 'https://zulip.com',
disp_recipients = [", ".join(recipient['email'] 'reply_warning': False}
for recipient in get_display_recipient(mesg.recipient) headers = {}
if recipient['email'] != user_profile.email) if all(msg.recipient.type in (Recipient.HUDDLE, Recipient.PERSONAL)
for mesg in missed_messages] for msg in missed_messages):
if all(msg.recipient.type == Recipient.HUDDLE for msg in missed_messages) and \ # If we have one huddle, set a reply-to to all of the members
len(set(disp_recipients)) == 1: # of the huddle except the user herself
headers['Reply-To'] = disp_recipients[0] disp_recipients = [", ".join(recipient['email']
elif len(senders) == 1: for recipient in get_display_recipient(mesg.recipient)
headers['Reply-To'] = missed_messages[0].sender.email if recipient['email'] != user_profile.email)
for mesg in missed_messages]
if all(msg.recipient.type == Recipient.HUDDLE for msg in missed_messages) and \
len(set(disp_recipients)) == 1:
headers['Reply-To'] = disp_recipients[0]
elif len(senders) == 1:
headers['Reply-To'] = missed_messages[0].sender.email
else:
template_payload['reply_warning'] = True
else: else:
# There are some @-mentions mixed in with personals
template_payload['mention'] = True
template_payload['reply_warning'] = True template_payload['reply_warning'] = True
else: headers['Reply-To'] = "Nobody <noreply@zulip.com>"
# There are some @-mentions mixed in with personals
template_payload['mention'] = True
template_payload['reply_warning'] = True
headers['Reply-To'] = "Nobody <noreply@zulip.com>"
subject = "Missed Zulip%s from %s" % ('s' if len(senders) > 1 else '', sender_str) subject = "Missed Zulip%s from %s" % (plural_messages, sender_str)
from_email = "%s (via Zulip) <noreply@zulip.com>" % (sender_str) from_email = "%s (via Zulip) <noreply@zulip.com>" % (sender_str)
text_content = loader.render_to_string('zerver/missed_message_email.txt', template_payload) text_content = loader.render_to_string('zerver/missed_message_email.txt', template_payload)
html_content = loader.render_to_string('zerver/missed_message_email_html.txt', template_payload) html_content = loader.render_to_string('zerver/missed_message_email_html.txt', template_payload)
msg = EmailMultiAlternatives(subject, text_content, from_email, [user_profile.email], msg = EmailMultiAlternatives(subject, text_content, from_email, [user_profile.email],
headers = headers) headers = headers)
msg.attach_alternative(html_content, "text/html") msg.attach_alternative(html_content, "text/html")
msg.send() msg.send()
user_profile.last_reminder = datetime.datetime.now() user_profile.last_reminder = datetime.datetime.now()
user_profile.save(update_fields=['last_reminder']) user_profile.save(update_fields=['last_reminder'])
if user_profile.enable_offline_push_notifications:
if num_push_devices_for_user(user_profile) == 0:
return
badge_count = len(missed_messages)
# Determine what alert string to display based on the missed messages
if all(msg.recipient.type == Recipient.HUDDLE for msg in missed_messages):
alert = "New private group message%s from %s" % (plural_messages, sender_str)
elif all(msg.recipient.type == Recipient.PERSONAL for msg in missed_messages):
alert = "New private message%s from %s" % (plural_messages, sender_str)
elif all(msg.recipient.type == Recipient.STREAM for msg in missed_messages):
alert = "New mention%s from %s" % (plural_messages, sender_str)
else:
alert = "New Zulip mentions and private messages from %s" % (sender_str,)
extra_data = {'message_ids': [amsg.id for amsg in missed_messages]}
send_apple_push_notification(user_profile, alert, badge=badge_count, zulip=extra_data)
def handle_missedmessage_emails(user_profile_id, missed_email_events): def handle_missedmessage_emails(user_profile_id, missed_email_events):
message_ids = [event.get('message_id') for event in missed_email_events] message_ids = [event.get('message_id') for event in missed_email_events]
@@ -1947,7 +1968,7 @@ def handle_missedmessage_emails(user_profile_id, missed_email_events):
flags=~UserMessage.flags.read)] flags=~UserMessage.flags.read)]
if messages: if messages:
do_send_missedmessage_email(user_profile, messages) do_send_missedmessage_events(user_profile, messages)
def user_email_is_unique(value): def user_email_is_unique(value):
try: try:

View File

@@ -261,7 +261,8 @@ def update_pointer(user_profile_id, new_pointer):
def receives_offline_notifications(user_profile): def receives_offline_notifications(user_profile):
return (user_profile.enable_offline_email_notifications and return ((user_profile.enable_offline_email_notifications or
user_profile.enable_offline_push_notifications) and
not user_profile.is_bot) not user_profile.is_bot)
def receives_offline_notifications_by_id(user_profile_id): def receives_offline_notifications_by_id(user_profile_id):

View File

@@ -102,3 +102,16 @@ else:
TWITTER_CONSUMER_SECRET = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" TWITTER_CONSUMER_SECRET = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
TWITTER_ACCESS_TOKEN_KEY = "xxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" TWITTER_ACCESS_TOKEN_KEY = "xxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
TWITTER_ACCESS_TOKEN_SECRET = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" TWITTER_ACCESS_TOKEN_SECRET = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
if STAGING_DEPLOYED:
APNS_SANDBOX = "push_sandbox"
APNS_FEEDBACK = "feedback_sandbox"
APNS_CERT_FILE = "/etc/ssl/django-private/apns-dev.pem"
elif DEPLOYED:
APNS_SANDBOX = "push_production"
APNS_FEEDBACK = "feedback_production"
APNS_CERT_FILE = "/etc/ssl/django-private/apns-dist.pem"
else:
APNS_SANDBOX = "push_sandbox"
APNS_FEEDBACK = "feedback_sandbox"
APNS_CERT_FILE = "/etc/ssl/django-private/apns-dev.pem"