From f78c0e5444a0bf888f03a797dc0a260e5b534ffb Mon Sep 17 00:00:00 2001 From: Tanner Prestegard <tanner.prestegard@ligo.org> Date: Fri, 28 Sep 2018 08:53:39 -0500 Subject: [PATCH] Updates to new phone alert code Switch over to new phone alert code (somewhat improved compared to the old code). Made a few more updates and bugfixes. --- gracedb/alerts/main.py | 57 +++++++++++++++++++---------------------- gracedb/alerts/phone.py | 44 +++++++++++-------------------- 2 files changed, 42 insertions(+), 59 deletions(-) diff --git a/gracedb/alerts/main.py b/gracedb/alerts/main.py index be64aa04d..29ed51821 100644 --- a/gracedb/alerts/main.py +++ b/gracedb/alerts/main.py @@ -17,19 +17,12 @@ from events.permission_utils import is_external from events.query import filter_for_labels from events.shortcuts import is_event from superevents.shortcuts import is_superevent +from userprofile.models import Contact +from .phone import issue_phone_alerts from .xmpp import issue_xmpp_alerts # Set up logger -log = logging.getLogger(__name__) - - -def check_recips(recips_qs): - """ - Make sure only internal users are included. Assumes that the queryset's - model has a foreign key to the user object. - """ - LVC_GROUP = Group.objects.get(name=settings.LVC_GROUP) - return recips_qs.filter(user__groups=LVC_GROUP) +logger = logging.getLogger(__name__) def get_alert_recips(event_or_superevent): @@ -39,18 +32,20 @@ def get_alert_recips(event_or_superevent): pass elif is_event(event_or_superevent): event = event_or_superevent - triggers = event.pipeline.trigger_set.filter(labels=None) \ - .prefetch_related('contacts') - email_recips = [c for t in triggers for c in - t.contacts.all().select_related('user') - if ((not t.farThresh or (event.far and event.far < t.farThresh)) - and r.email)] - phone_recips = [c for t in triggers for c in - t.contacts.all().select_related('user') - if ((not t.farThresh or (event.far and event.far < t.farThresh)) - and r.phone)] - - return check_recips(email_recips), check_recips(phone_recips) + # Queryset of all triggers for this pipeline + triggers = event.pipeline.trigger_set.filter(labels=None) + # Filter on FAR threshold requirements + query = Q(farThresh__isnull=True) + if event.far: + query |= Q(farThresh__lt=event.far) + triggers = triggers.filter(query) + # Contacts for all triggers, make sure user is in LVC group (safeguard) + contacts = Contact.objects.filter(trigger__in=triggers, + user__groups__name=settings.LVC_GROUP).select_related('user') + email_recips = contacts.exclude(email="") + phone_recips = contacts.exclude(phone="") + + return email_recips, phone_recips def get_alert_recips_for_label(event_or_superevent, label): @@ -60,7 +55,8 @@ def get_alert_recips_for_label(event_or_superevent, label): # Construct a queryset containing only this object; needed for # call to filter_for_labels - qs = event_or_superevent.model.objects.filter(id=event_or_superevent.id) + qs = event_or_superevent._meta.model.objects.filter( + pk=event_or_superevent.pk) # Triggers on given label matching pipeline OR with no pipeline; # no pipeline indicates that pipeline is irrelevant @@ -78,7 +74,7 @@ def get_alert_recips_for_label(event_or_superevent, label): # Idea: have filter_for_labels return a Q object generated from the # label query triggers = label.trigger_set.filter(query).prefetch_related('contacts') - for trigger in triggers.related(): + for trigger in triggers: if len(trigger.label_query) > 0: qs_out = filter_for_labels(qs, trigger.label_query) @@ -88,13 +84,14 @@ def get_alert_recips_for_label(event_or_superevent, label): if not qs_out.exists(): continue - # Compile a list of recipients from the trigger's contacts - email_recips |= trigger.contacts.exclude(email="") \ - .select_related('user') - phone_recips |= trigger.contacts.exclude(phone="") \ - .select_related('user') + # Compile a list of recipients from the trigger's contacts. + # Require that the user is in the LVC group as a safeguard + contacts = trigger.contacts.filter(user__groups__name= + settings.LVC_GROUP) + email_recips |= contacts.exclude(email="").select_related('user') + phone_recips |= contacts.exclude(phone="").select_related('user') - return check_recips(email_recips), check_recips(phone_recips) + return email_recips, phone_recips def issue_alerts(event_or_superevent, alert_type, serialized_object, diff --git a/gracedb/alerts/phone.py b/gracedb/alerts/phone.py index 30ea12230..ddaefd826 100644 --- a/gracedb/alerts/phone.py +++ b/gracedb/alerts/phone.py @@ -7,7 +7,7 @@ from django_twilio.client import twilio_client from events.permission_utils import is_external # Set up logger -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) # TODO: generalize to superevents @@ -75,43 +75,29 @@ def issue_phone_alerts(event, contacts, label=None): msg_body = TWILIO_MSG_CONTENT[alert_type].format(**msg_params) # Loop over recipients and make calls and/or texts. - for contact in twilio_recips: - if is_external(recip.user): + for contact in contacts: + if is_external(contact.user): # Only make calls to LVC members (non-LVC members # shouldn't even be able to sign up for phone alerts, # but this is another safety measure. - log.warning("External user {0} is somehow signed up for" - " phone alerts".format(recip.user.username)) + logger.warning("External user {0} is somehow signed up for" + " phone alerts".format(contact.user.username)) continue try: # POST to TwiML bin to make voice call. - if recip.call_phone: - log.debug("Calling {0} at {1}".format(recip.user.username, - recip.phone)) - twilio_client.calls.create(to=recip.phone, from_=from_, + if contact.call_phone: + logger.debug("Calling {0} at {1}".format(contact.user.username, + contact.phone)) + twilio_client.calls.create(to=contact.phone, from_=from_, url=twiml_url, method='GET') # Create Twilio message. - if recip.text_phone: - log.debug("Texting {0} at {1}".format(recip.user.username, - recip.phone)) - twilio_client.messages.create(to=recip.phone, from_=from_, + if contact.text_phone: + logger.debug("Texting {0} at {1}".format(contact.user.username, + contact.phone)) + twilio_client.messages.create(to=contact.phone, from_=from_, body=msg_body) except Exception as e: - log.exception("Failed to contact {0} at {1}.".format( - recip.user.username, recip.phone)) - - -# TODO: update for superevents -def get_phone_recips(event): - triggers = event.pipeline.trigger_set.filter(labels=None) \ - .prefetch_related('contacts') - phone_recips = [c for t in triggers for c in - t.contacts.all().select_related('user') - if ((not t.farThresh or (event.far and event.far < t.farThresh)) and - r.phone)] - - return phone_recips - - + logger.exception("Failed to contact {0} at {1}.".format( + contact.user.username, contact.phone)) -- GitLab