def _contact_from_args(first_name, last_name, email, text, voice): messages = [] info = {'first_name': first_name, 'last_name': last_name, 'methods': [], "type": "p", "notes": ""} def _add_phone_number(number, type_): phone, messages = validate_and_standardize_phone(number) if phone: info['methods'].append({'type': type_, 'value': phone}) else: messages.extend(messages) info['methods'].append({'type': type_, 'value': ''}) if email and valid_email(email): info['methods'].append({'type': 'e', 'value': email}) else: messages.append("Invalid email address %s" % (email,)) error = "Invalid email address %s" % (email) create_error_log(error, 'ERR') info['methods'].append({'type': 'e', 'value': ''}) if voice: _add_phone_number(voice, 'p') if text: _add_phone_number(text, 't') return info, messages
def broadcast_call(number, text_message, play_audio): """Send a message to a given phone number.""" from twilio.rest import TwilioRestClient import settings import urllib import re logging.debug("Call notice to %s via twilio.", number) client = TwilioRestClient(settings.TWILIO_ACCOUNT, settings.TWILIO_TOKEN) try: message = re.sub("<[^<]+?>", "", text_message) params = {"textMessage": message.encode("utf-8")} broadcast_url = ( "http://5.sos-beacon-dev.appspot.com/broadcast/record?" + urllib.urlencode(params) + "&playUrl=" + play_audio ) client.calls.create(to=number, from_=settings.TWILIO_FROM, url=broadcast_url, if_machine="Continue") except: logging.info("call error") error = "Can not make a call to phone number: %s" % number create_error_log(error, "ERR")
def broadcast_call(number, text_message, play_audio): """Send a message to a given phone number.""" from twilio.rest import TwilioRestClient import settings import urllib import re logging.debug('Call notice to %s via twilio.', number) client = TwilioRestClient(settings.TWILIO_ACCOUNT, settings.TWILIO_TOKEN) try: message = re.sub('<[^<]+?>', '', text_message) params = {'textMessage': message.encode('utf-8')} broadcast_url = "http://5.sos-beacon-dev.appspot.com/broadcast/record?" + urllib.urlencode( params) + "&playUrl=" + play_audio client.calls.create( to=number, from_=settings.TWILIO_FROM, url=broadcast_url, if_machine='Continue', ) except: logging.info("call error") error = 'Can not make a call to phone number: %s' % number create_error_log(error, 'ERR')
def import_student(school_urlsafe, is_direct, student_array, group_lookup=None): messages = [] if group_lookup is None: group_lookup = {} #expected CSV format #Group, Student name, contact name parent 1, contact email, #voice phone, text phone, space, contact name parent 2 #contact email, voice phone, text phone group_name = unicode(student_array[0], 'utf8').strip() if not group_name: #TODO: add bad message logging.error("Invalid group name %s", group_name) error = "Invalid group name %s", group_name create_error_log(error, 'ERR') return None, None, messages group_key, group_future = _get_group(group_name, group_lookup, school_urlsafe) #TODO: look for existing student by name? student_first_name = unicode(student_array[1], 'utf8') student_last_name = unicode(student_array[2], 'utf8') if not student_first_name: #TODO: add bad message logging.error("Invalid student name %s", student_first_name) error = "Invalid student name %s", student_first_name create_error_log(error, 'ERR') return None, None, messages #Ideally they have an ID in the sheet to import in # student = Student(identifier=uuid.uuid4().hex[:6], name=student_name, is_direct=is_direct) student = Student(first_name=student_first_name, last_name=student_last_name, last_name_=student_last_name.lower(), is_direct=is_direct) if is_direct: student.contacts = _build_direct_contacts(student_array) else: student.contacts = _build_student_contacts(student_array) if group_future: group_key = group_future.get_result() if group_name.lower() not in group_lookup: group_lookup[group_name.lower()] = group_key if group_key not in student.groups: school_key = ndb.Key(urlsafe=school_urlsafe) student.groups.append(group_key) student.school = school_key logging.info("Saving student %s", student) future = student.put_async() return student, future, messages
def _contact_from_args(first_name, last_name, email, text, voice): messages = [] info = { 'first_name': first_name, 'last_name': last_name, 'methods': [], "type": "p", "notes": "" } def _add_phone_number(number, type_): phone, messages = validate_and_standardize_phone(number) if phone: info['methods'].append({'type': type_, 'value': phone}) else: messages.extend(messages) info['methods'].append({'type': type_, 'value': ''}) if email and valid_email(email): info['methods'].append({'type': 'e', 'value': email}) else: messages.append("Invalid email address %s" % (email, )) error = "Invalid email address %s" % (email) create_error_log(error, 'ERR') info['methods'].append({'type': 'e', 'value': ''}) if voice: _add_phone_number(voice, 'p') if text: _add_phone_number(text, 't') return info, messages
def _get_group(group_name, group_lookup, school_urlsafe): """Return a group for the group name passed in. Checks the group cache first if not there then queries by the lower case name. If not there then creates a new group. """ #check for existing group by name if group_name.lower() in group_lookup: logging.debug("group found in cache") error = "group found in cache" create_error_log(error, 'ERR') return group_lookup[group_name.lower()], None from .group import Group school_key = ndb.Key(urlsafe=school_urlsafe) group = Group.query(Group.name_ == group_name, Group.school == school_key, namespace='_x_').get() if group: logging.debug("group found in datastore") error = "group found in datastore" create_error_log(error, 'ERR') group_lookup[group_name.lower()] = group.key return group.key, None logging.debug("No group found for %s, creating a new one", group_name) group = Group(name=group_name) school_key = ndb.Key(urlsafe=school_urlsafe) group.school = school_key future = group.put_async() return group.key, future
def email_broadcast_message(self, user_key, title, query_messages): body = """ <table style='border:1px solid #607298;width:540px;max-width:600px'> <thead> <tr> <th colspan="2" style="background:#607298;color:#fff;min-height:30px;line-height:30px;text-align:center;font-size:20px">%s</th> </tr> </thead> <tbody> """ % (title) try: for query_message in query_messages: sms_content = query_message.message['sms'] email_content = query_message.message['email'] create_at = query_message.added.strftime('%Y-%m-%d %H:%M') body += self.format_email_message(user_key.name, user_key.phone, user_key.email, create_at, sms_content, email_content) except: error = "Can not query message." create_error_log(error, 'ERR') body += """</tbody></table><br><br><br>""" return body
def _get_group(group_name, group_lookup, school_urlsafe): """Return a group for the group name passed in. Checks the group cache first if not there then queries by the lower case name. If not there then creates a new group. """ #check for existing group by name if group_name.lower() in group_lookup: logging.debug("group found in cache") error = "group found in cache" create_error_log(error, 'ERR') return group_lookup[group_name.lower()], None from .group import Group school_key = ndb.Key(urlsafe = school_urlsafe) group = Group.query(Group.name_ == group_name, Group.school == school_key, namespace = '_x_').get() if group: logging.debug("group found in datastore") error = "group found in datastore" create_error_log(error, 'ERR') group_lookup[group_name.lower()] = group.key return group.key, None logging.debug("No group found for %s, creating a new one", group_name) group = Group(name=group_name) school_key = ndb.Key(urlsafe = school_urlsafe) group.school = school_key future = group.put_async() return group.key, future
def import_student(school_urlsafe, is_direct, student_array, group_lookup=None): messages = [] if group_lookup is None: group_lookup = {} #expected CSV format #Group, Student name, contact name parent 1, contact email, #voice phone, text phone, space, contact name parent 2 #contact email, voice phone, text phone group_name = unicode(student_array[0], 'utf8').strip() if not group_name: #TODO: add bad message logging.error("Invalid group name %s", group_name) error = "Invalid group name %s", group_name create_error_log(error, 'ERR') return None, None, messages group_key, group_future = _get_group(group_name, group_lookup, school_urlsafe) #TODO: look for existing student by name? student_first_name = unicode(student_array[1], 'utf8') student_last_name = unicode(student_array[2], 'utf8') if not student_first_name: #TODO: add bad message logging.error("Invalid student name %s", student_first_name) error = "Invalid student name %s", student_first_name create_error_log(error, 'ERR') return None, None, messages #Ideally they have an ID in the sheet to import in # student = Student(identifier=uuid.uuid4().hex[:6], name=student_name, is_direct=is_direct) student = Student(first_name=student_first_name, last_name=student_last_name, last_name_=student_last_name.lower(), is_direct=is_direct) if is_direct: student.contacts = _build_direct_contacts(student_array) else: student.contacts = _build_student_contacts(student_array) if group_future: group_key = group_future.get_result() if group_name.lower() not in group_lookup: group_lookup[group_name.lower()] = group_key if group_key not in student.groups: school_key = ndb.Key(urlsafe = school_urlsafe) student.groups.append(group_key) student.school = school_key logging.info("Saving student %s", student) future = student.put_async() return student, future, messages
def post(self): event_urlsafe = self.request.get('event') event_key = ndb.Key(urlsafe=event_urlsafe) event = event_key.get() if not event: logging.error('Event %s not found!', event_key) error = 'Event %s not found!' % event_key create_error_log(error, 'ERR') return is_direct = self.request.get('is_direct') robocall_start(event_urlsafe, is_direct)
def broadcast_email(address, message, url, user, school): """Send an email to a given email address.""" logging.info("Sending notice to %s via mail api.", address) # if message.message['title']: # subject = message.message['title'] # else: if message.message_type == "em": subject = "Emergency Alert from %s (%s)" % ( user.get().first_name + " " + user.get().last_name, school.get().name, ) else: subject = "School Notice message from %s (%s)" % ( user.get().first_name + " " + user.get().last_name, school.get().name, ) if message.message["email"]: body = "%s (%s) sent a Event Broadcast. Detail here: <a href='%s'>%s</a>. \nMessage: %s" % ( user.get().first_name + " " + user.get().last_name, school.get().name, url, url, message.message["email"], ) else: body = "%s (%s) sent a Event Broadcast. Detail here: %s. \nMessage: %s" % ( user.get().first_name + " " + user.get().last_name, school.get().name, url, message.message["sms"], ) # TODO: it might make sense to group emails as we can add more than one to # address per email sent import sendgrid import settings s = sendgrid.Sendgrid(settings.SENDGRID_ACCOUNT, settings.SENDGRID_PASSWORD, secure=True) try: message = sendgrid.Message(user.get().email, subject, body, body) message.add_to(address) s.web.send(message) except: error = "The 'To' email %s is not a valid email" % address create_error_log(error, "ERR")
def validate_and_standardize_phone(number): import string messages = [] logging.info(number) try: stuff = string.maketrans('', '') non_digits = stuff.translate(None, string.digits) number = number.translate(None, non_digits) logging.info(number) except Exception, e: logging.exception("Invalid phone number %s", number) messages.append("Invalid phone number %s, %s", number, e.message) error = "Invalid phone number %s", number create_error_log(error, 'ERR') return None, messages
def broadcast_sms(number, message, url, user_name, school_name): """Send a message to a given phone number.""" from twilio.rest import TwilioRestClient import settings logging.debug("Sending notice to %s via twilio.", number) logging.info("Sending notice to %s via twilio.", number) body = message.message["sms"] body = "Broadcast from %s (School %s). Link %s. Message: %s" % (user_name, school_name, url, body) client = TwilioRestClient(settings.TWILIO_ACCOUNT, settings.TWILIO_TOKEN) try: client.sms.messages.create(to="+%s" % (number), from_=settings.TWILIO_FROM, body=body) except: error = "The 'To' number %s is not a valid phone number" % number create_error_log(error, "ERR")
def broadcast_email(address, message, url, user, school): """Send an email to a given email address.""" logging.info('Sending notice to %s via mail api.', address) # if message.message['title']: # subject = message.message['title'] # else: if message.message_type == 'em': subject = "Emergency Alert from %s (%s)" % (user.get().first_name + " " + user.get().last_name, school.get().name) else: subject = "School Notice message from %s (%s)" % ( user.get().first_name + " " + user.get().last_name, school.get().name) if message.message['email']: body = "%s (%s) sent a Event Broadcast. Detail here: <a href='%s'>%s</a>. \nMessage: %s" %\ (user.get().first_name + " " + user.get().last_name, school.get().name, url, url,message.message['email']) else: body = "%s (%s) sent a Event Broadcast. Detail here: %s. \nMessage: %s" %\ (user.get().first_name + " " + user.get().last_name, school.get().name, url, message.message['sms']) #TODO: it might make sense to group emails as we can add more than one to # address per email sent import sendgrid import settings s = sendgrid.Sendgrid(settings.SENDGRID_ACCOUNT, settings.SENDGRID_PASSWORD, secure=True) try: message = sendgrid.Message(user.get().email, subject, body, body) message.add_to(address) s.web.send(message) except: error = "The 'To' email %s is not a valid email" % address create_error_log(error, 'ERR')
def broadcast_sms(number, message, url, user_name, school_name): """Send a message to a given phone number.""" from twilio.rest import TwilioRestClient import settings logging.debug('Sending notice to %s via twilio.', number) logging.info('Sending notice to %s via twilio.', number) body = message.message['sms'] body = "Broadcast from %s (School %s). Link %s. Message: %s" % ( user_name, school_name, url, body) client = TwilioRestClient(settings.TWILIO_ACCOUNT, settings.TWILIO_TOKEN) try: client.sms.messages.create(to="+%s" % (number), from_=settings.TWILIO_FROM, body=body) except: error = "The 'To' number %s is not a valid phone number" % number create_error_log(error, 'ERR')
def responder_messages(self, user_key, title, list_comment): """List comment messages of current event""" body = """ <table style='border:1px solid #607298;width:540px;max-width:600px'> <thead> <tr> <th colspan="2" style="background:#607298;color:#fff;min-height:30px;line-height:30px;text-align:center;font-size:20px">%s</th> </tr> </thead> <tbody> """ % (title) try: for comment in list_comment: message = comment.message['body'] create_at = comment.added.strftime('%Y-%m-%d %H:%M') body += self.format_email_comment_message(comment.user_name, create_at, message) except: error = "Can not query comment message." create_error_log(error, 'ERR') body += """</tbody></table><br><br><br>""" return body
def post(self): from sosbeacon.event.event import EVENT_STATUS_CLOSED event_urlsafe = self.request.get('event') user_urlsafe = self.request.get('user') message_urlsafe = self.request.get('message') method = self.request.get('method') if not event_urlsafe: logging.error('No event key given.') return # TODO: Use event id rather than key here for namespacing purposes? event_key = ndb.Key(urlsafe=event_urlsafe) event = event_key.get() if not event: logging.error('Event %s not found!', event_key) error = 'Event %s not found!' % event_key create_error_log(error, 'ERR') return if event.status == EVENT_STATUS_CLOSED: logging.error('Event %s closed!', event_key) error = 'Event %s not found!' % event_key create_error_log(error, 'ERR') return user_key = ndb.Key(urlsafe = user_urlsafe) user = user_key.get() if not user: logging.error('User %s not found!', user_key) error = 'User %s not found!' % user_key create_error_log(error, 'ERR') return message_key = ndb.Key(urlsafe = message_urlsafe) message = message_key.get() if not message: logging.error('Message %s not found!', message_key) error = 'Message %s not found!' % message_key create_error_log(error, 'ERR') return broadcast_to_method(event_key, message_key, user_key.id(), method)
def responder_messages(self, user_key, title, list_comment): """List comment messages of current event""" body = """ <table style='border:1px solid #607298;width:540px;max-width:600px'> <thead> <tr> <th colspan="2" style="background:#607298;color:#fff;min-height:30px;line-height:30px;text-align:center;font-size:20px">%s</th> </tr> </thead> <tbody> """ % (title) try: for comment in list_comment: message = comment.message['body'] create_at = comment.added.strftime('%Y-%m-%d %H:%M') body += self.format_email_comment_message( comment.user_name, create_at, message) except: error = "Can not query comment message." create_error_log(error, 'ERR') body += """</tbody></table><br><br><br>""" return body
def robocall_phone(event_urlsafe, phone_markers, message_urlsafe, timezone): from .message import broadcast_call from webapp2_extras import sessions if not event_urlsafe: logging.error('No event key given.') return # TODO: Use event id rather than key here for namespacing purposes? event_key = ndb.Key(urlsafe=event_urlsafe) event = event_key.get() message_key = ndb.Key(urlsafe=message_urlsafe) message = message_key.get() if not event: logging.error('Event %s not found!', event_key) error = 'Event %s not found!' % event_key create_error_log(error, 'ERR') return if event.status == EVENT_STATUS_CLOSED: logging.error('Event %s closed!', event_key) error = 'Event %s not found!' % event_key create_error_log(error, 'ERR') return if not phone_markers: logging.error('No phone marker given.') error = 'Event %s not found!' % event_key create_error_log(error, 'ERR') return time = message.added.strftime("%B %d, %Y at %I:%M %p") convert_time = convertTimeZone(timezone, time) logging.info(timezone) # number = message.user.get().phone # number = " ".join(number[i:i+1] for i in range(0, len(number), 1)) # text_message = message.user.get().name + " at " + string_date +". Message " + message.message['email'] text_message = "from " + event.school.get( ).name + " by " + message.user.get().first_name + " " + message.user.get( ).last_name + " on " + convert_time + ". Message " + message.message[ 'email'] broadcast_call(phone_markers, text_message, message.link_audio)
def robocall_phone(event_urlsafe, phone_markers, message_urlsafe, timezone): from .message import broadcast_call from webapp2_extras import sessions if not event_urlsafe: logging.error('No event key given.') return # TODO: Use event id rather than key here for namespacing purposes? event_key = ndb.Key(urlsafe=event_urlsafe) event = event_key.get() message_key = ndb.Key(urlsafe=message_urlsafe) message = message_key.get() if not event: logging.error('Event %s not found!', event_key) error = 'Event %s not found!' % event_key create_error_log(error, 'ERR') return if event.status == EVENT_STATUS_CLOSED: logging.error('Event %s closed!', event_key) error = 'Event %s not found!' % event_key create_error_log(error, 'ERR') return if not phone_markers: logging.error('No phone marker given.') error = 'Event %s not found!' % event_key create_error_log(error, 'ERR') return time = message.added.strftime("%B %d, %Y at %I:%M %p") convert_time = convertTimeZone(timezone, time) logging.info(timezone) # number = message.user.get().phone # number = " ".join(number[i:i+1] for i in range(0, len(number), 1)) # text_message = message.user.get().name + " at " + string_date +". Message " + message.message['email'] text_message = "from " + event.school.get().name + " by " + message.user.get().first_name + " " + message.user.get().last_name + " on " + convert_time + ". Message " + message.message['email'] broadcast_call(phone_markers, text_message, message.link_audio)
def post(self): from sosbeacon.event.message import send_email_robocall_to_user from sosbeacon.event.event import EVENT_STATUS_CLOSED event_urlsafe = self.request.get('event') message_urlsafe = self.request.get('message') if not event_urlsafe: logging.error('No event key given.') return # TODO: Use event id rather than key here for namespacing purposes? event_key = ndb.Key(urlsafe=event_urlsafe) event = event_key.get() if not event: logging.error('Event %s not found!', event_key) error = 'Event %s not found!' % event_key create_error_log(error, 'ERR') return if event.status == EVENT_STATUS_CLOSED: logging.error('Event %s closed!', event_key) error = 'Event %s not found!' % event_key create_error_log(error, 'ERR') return message_key = ndb.Key(urlsafe = message_urlsafe) message = message_key.get() if not message: logging.error('Message %s not found!', message_key) error = 'Message %s not found!' % message_key create_error_log(error, 'ERR') return send_email_robocall_to_user(message_key, event_key)
def send_email_robocall_to_user(event_urlsafe, user_urlsafe, message_urlsafe, phones): from sosbeacon.event.contact_marker import ContactMarker import sendgrid import settings if not event_urlsafe: logging.error('No event key given.') return # TODO: Use event id rather than key here for namespacing purposes? event_key = ndb.Key(urlsafe=event_urlsafe) event = event_key.get() user_key = ndb.Key(urlsafe = user_urlsafe) user = user_key.get() message_key = ndb.Key(urlsafe = message_urlsafe) message = message_key.get() if not event: logging.error('Event %s not found!', event_key) error = 'Event %s not found!' % event_key create_error_log(error, 'ERR') return if event.status == EVENT_STATUS_CLOSED: logging.error('Event %s closed!', event_key) error = 'Event %s not found!' % event_key create_error_log(error, 'ERR') return if not user: logging.error('User %s not found!', user_key) error = 'User %s not found!' % user_key create_error_log(error, 'ERR') return if not message: logging.error('Message %s not found!', message_key) error = 'Message %s not found!' % message_key create_error_log(error, 'ERR') return logging.info('Sending notice to %s via mail api.', user.email) # contact_markers = ContactMarker.query(ContactMarker.event == event_key, # ContactMarker.acknowledged == False) string_date = "%s %s, %s at %s:%s %s (GMT)" % (event.added.strftime("%B"), event.added.strftime("%d"), event.added.strftime("%Y"),event.added.strftime("%I"), event.added.strftime("%M"), event.added.strftime("%p")) subject = "School Beacon ROBOCALL service for alert %s was requested by you" % event_key.id() body = "School Beacon ROBOCALL service for alert <span style='color: red'>%s</span> was requested by you" % event_key.id() body = body + " on " + "<br><span style='color:red'>" + string_date + "</span>.<br><br>" + " The following numbers were called: <br>" # for contact_marker in contact_markers: # logging.info(contact_marker) # logging.info(contact_marker.methods) # for method in contact_marker.methods: # logging.info(method) # if '@' not in method: # body += str(method) + '<br>' for phone in phones: body += str(phone) + '<br>' body += "<br><br>The following text was delivered:<br> <span style='color:red'>%s</span>" % message.message['email'] s = sendgrid.Sendgrid(settings.SENDGRID_ACCOUNT, settings.SENDGRID_PASSWORD, secure=True) email = sendgrid.Message( user.email, subject, body, body) email.add_to(user.email) s.web.send(email)
def get(self, event_id, number, *args, **kwargs): import sendgrid import settings from datetime import datetime from sosbeacon.event.message import Message from sosbeacon.event.student_marker import StudentMarker session_store = sessions.get_store() session = session_store.get_session() user_urlsafe = session.get('u') user_key = ndb.Key(urlsafe = user_urlsafe).get() event_key = ndb.Key(urlsafe = event_id) query_messages = Message.query(Message.event == event_key).fetch() body = "" for i in number: # list comment message if i == "1": list_comment = Message.query(Message.event == event_key, Message.message_type == 'c') title = "Responder messages" body += str(self.responder_messages(user_key, title, list_comment)) # list student marker Responders if i == "2": query_response = StudentMarker.query(StudentMarker.event == event_key, StudentMarker.is_direct == True, StudentMarker.acknowledged == True) student_markers = query_response.fetch() title = "Responder List" body += str(self.email_student_marker(student_markers, title)) # list student marker Non Responders if i == "3": query_response = StudentMarker.query(StudentMarker.event == event_key, StudentMarker.acknowledged == False, StudentMarker.is_direct == True) student_markers = query_response.fetch() title = "No Responder List" body += str(self.email_student_marker(student_markers, title)) # list message email if i == "4": title = "Alert Messages" body += str(self.email_broadcast_message(user_key, title, query_messages)) today = datetime.today() today = today.strftime('%Y-%m-%d %H:%M') subject = "Download data sent from SOSbeacon Message Center %s" % today email = user_key.email s = sendgrid.Sendgrid(settings.SENDGRID_ACCOUNT, settings.SENDGRID_PASSWORD, secure=True) message = sendgrid.Message( settings.SENDGRID_SENDER, subject, body, body) message.add_to(str(email)) try: s.web.send(message) except: error = "Can not download email." create_error_log(error, 'ERR')
except Exception, e: logging.exception("Invalid phone number %s", number) messages.append("Invalid phone number %s, %s", number, e.message) error = "Invalid phone number %s", number create_error_log(error, 'ERR') return None, messages logging.info(number) if not number.startswith('1'): number = '1' + number if not len(number) == 11: logging.error("Invalid phone number %s", number) messages.append("Invalide number %s, not 11 characters" % (number,)) error = "Invalid phone number %s", number create_error_log(error, 'ERR') return None, messages number = "%s (%s) %s-%s" % ( number[0], number[1:4], number[4:7], number[7:11]) return number, messages def _get_group(group_name, group_lookup, school_urlsafe): """Return a group for the group name passed in. Checks the group cache first if not there then queries by the lower case name. If not there then creates a new group. """ #check for existing group by name if group_name.lower() in group_lookup:
def import_students(file_, school_urlsafe, is_direct): import csv import StringIO from collections import namedtuple results = {'success': [], 'failures': []} ResultItemDirect = namedtuple('ResultItemDirect', [ 'first_name', 'last_name', 'group', 'email', 'text_phone', 'voice_phone', 'messages' ]) ResultItemStudent = namedtuple('ResultItemStudent', [ 'first_name', 'last_name', 'group', 'parent_first_name_1', 'parent_last_name_1', 'parent_email_1', 'parent_text_phone_1', 'parent_voice_phone_1', 'parent_first_name_2', 'parent_last_name_2', 'parent_email_2', 'parent_text_phone_2', 'parent_voice_phone_2', 'messages' ]) students = csv.reader(StringIO.StringIO(file_), delimiter=',') #TODO: check size and move to tasks #expected CSV format #Group, Student name, contact name parent 1, contact email, #voice phone, text phone, space, contact name parent 2 #contact email, voice phone, text phone groups = {} futures = [] for student_array in students: if student_array[0] and student_array[0].lower() == 'group': #assume it has a header continue first_name = unicode(student_array[1], 'utf8').strip() last_name = unicode(student_array[2], 'utf8').strip() group = unicode(student_array[0], 'utf8').strip() if is_direct: email = unicode(student_array[3], 'utf8').strip() text_phone = unicode(student_array[4], 'utf8').strip() voice_phone = unicode(student_array[5], 'utf8').strip() try: student, future, messages = import_student( school_urlsafe, is_direct, student_array, groups) result = ResultItemDirect(first_name=first_name, last_name=last_name, group=group, email=email, text_phone=text_phone, voice_phone=voice_phone, messages=messages) results['success'].append(result) except Exception, e: logging.exception("Unable to import direct contact") result = ResultItemDirect(first_name=first_name, last_name=last_name, group=group, email=email, text_phone=text_phone, voice_phone=voice_phone, messages=[e.message]) results['failures'].append(result) error = "Unable to import direct contact" create_error_log(error, 'ERR') # if not student and future: # futures.append(future) else: parent_first_name_1 = unicode(student_array[3], 'utf8').strip() parent_last_name_1 = unicode(student_array[4], 'utf8').strip() parent_email_1 = unicode(student_array[5], 'utf8').strip() parent_text_phone_1 = unicode(student_array[5], 'utf8').strip() parent_voice_phone_1 = unicode(student_array[6], 'utf8').strip() if len(student_array) > 7: parent_first_name_2 = unicode(student_array[7], 'utf8').strip() parent_last_name_2 = unicode(student_array[8], 'utf8').strip() parent_email_2 = unicode(student_array[9], 'utf8').strip() parent_text_phone_2 = unicode(student_array[10], 'utf8').strip() parent_voice_phone_2 = unicode(student_array[11], 'utf8').strip() else: parent_first_name_2 = parent_last_name_2 = parent_text_phone_2 = parent_voice_phone_2 = '' try: student, future, messages = import_student( school_urlsafe, is_direct, student_array, groups) result = ResultItemStudent( first_name=first_name, last_name=last_name, group=group, parent_first_name_1=parent_first_name_1, parent_last_name_1=parent_last_name_1, parent_email_1=parent_email_1, parent_text_phone_1=parent_text_phone_1, parent_voice_phone_1=parent_voice_phone_1, parent_first_name_2=parent_first_name_2, parent_last_name_2=parent_last_name_2, parent_email_2=parent_email_2, parent_text_phone_2=parent_text_phone_2, parent_voice_phone_2=parent_voice_phone_2, messages='') results['success'].append(result) except Exception, e: logging.exception("Unable to import direct contact") result = ResultItemStudent( first_name=first_name, last_name=last_name, group=group, parent_first_name_1=parent_first_name_1, parent_last_name_1=parent_last_name_1, parent_email_1=parent_email_1, parent_text_phone_1=parent_text_phone_1, parent_voice_phone_1=parent_voice_phone_1, parent_first_name_2=parent_first_name_2, parent_last_name_2=parent_last_name_2, parent_email_2=parent_email_2, parent_text_phone_2=parent_text_phone_2, parent_voice_phone_2=parent_voice_phone_2, messages=[e.message]) results['failures'].append(result) error = "Unable to import direct contact" create_error_log(error, 'ERR')
except Exception, e: logging.exception("Invalid phone number %s", number) messages.append("Invalid phone number %s, %s", number, e.message) error = "Invalid phone number %s", number create_error_log(error, 'ERR') return None, messages logging.info(number) if not number.startswith('1'): number = '1' + number if not len(number) == 11: logging.error("Invalid phone number %s", number) messages.append("Invalide number %s, not 11 characters" % (number, )) error = "Invalid phone number %s", number create_error_log(error, 'ERR') return None, messages number = "%s (%s) %s-%s" % (number[0], number[1:4], number[4:7], number[7:11]) return number, messages def _get_group(group_name, group_lookup, school_urlsafe): """Return a group for the group name passed in. Checks the group cache first if not there then queries by the lower case name. If not there then creates a new group. """ #check for existing group by name if group_name.lower() in group_lookup:
def import_students(file_, school_urlsafe, is_direct): import csv import StringIO from collections import namedtuple results = {'success': [], 'failures': []} ResultItemDirect = namedtuple('ResultItemDirect', ['first_name', 'last_name', 'group', 'email', 'text_phone', 'voice_phone','messages']) ResultItemStudent = namedtuple('ResultItemStudent', ['first_name', 'last_name','group', 'parent_first_name_1', 'parent_last_name_1','parent_email_1', 'parent_text_phone_1', 'parent_voice_phone_1', 'parent_first_name_2', 'parent_last_name_2','parent_email_2', 'parent_text_phone_2', 'parent_voice_phone_2','messages']) students = csv.reader(StringIO.StringIO(file_), delimiter=',') #TODO: check size and move to tasks #expected CSV format #Group, Student name, contact name parent 1, contact email, #voice phone, text phone, space, contact name parent 2 #contact email, voice phone, text phone groups = {} futures = [] for student_array in students: if student_array[0] and student_array[0].lower() == 'group': #assume it has a header continue first_name = unicode(student_array[1], 'utf8').strip() last_name = unicode(student_array[2], 'utf8').strip() group = unicode(student_array[0], 'utf8').strip() if is_direct: email = unicode(student_array[3], 'utf8').strip() text_phone = unicode(student_array[4], 'utf8').strip() voice_phone = unicode(student_array[5], 'utf8').strip() try: student, future, messages = import_student(school_urlsafe, is_direct, student_array, groups) result = ResultItemDirect(first_name=first_name, last_name=last_name, group=group, email=email, text_phone=text_phone, voice_phone=voice_phone, messages=messages) results['success'].append(result) except Exception, e: logging.exception("Unable to import direct contact") result = ResultItemDirect(first_name=first_name, last_name=last_name, group=group, email=email, text_phone=text_phone, voice_phone=voice_phone, messages=[e.message]) results['failures'].append(result) error = "Unable to import direct contact" create_error_log(error, 'ERR') # if not student and future: # futures.append(future) else: parent_first_name_1 = unicode(student_array[3], 'utf8').strip() parent_last_name_1 = unicode(student_array[4], 'utf8').strip() parent_email_1 = unicode(student_array[5], 'utf8').strip() parent_text_phone_1 = unicode(student_array[5], 'utf8').strip() parent_voice_phone_1 = unicode(student_array[6], 'utf8').strip() if len(student_array) > 7: parent_first_name_2 = unicode(student_array[7], 'utf8').strip() parent_last_name_2 = unicode(student_array[8], 'utf8').strip() parent_email_2 = unicode(student_array[9], 'utf8').strip() parent_text_phone_2 = unicode(student_array[10], 'utf8').strip() parent_voice_phone_2 = unicode(student_array[11], 'utf8').strip() else: parent_first_name_2 = parent_last_name_2 = parent_text_phone_2 = parent_voice_phone_2 = '' try: student, future, messages = import_student(school_urlsafe, is_direct, student_array, groups) result = ResultItemStudent(first_name=first_name, last_name=last_name, group=group, parent_first_name_1 = parent_first_name_1, parent_last_name_1 = parent_last_name_1, parent_email_1 = parent_email_1, parent_text_phone_1 = parent_text_phone_1, parent_voice_phone_1 = parent_voice_phone_1, parent_first_name_2 = parent_first_name_2, parent_last_name_2 = parent_last_name_2, parent_email_2 = parent_email_2, parent_text_phone_2 = parent_text_phone_2, parent_voice_phone_2 = parent_voice_phone_2, messages='') results['success'].append(result) except Exception, e: logging.exception("Unable to import direct contact") result = ResultItemStudent(first_name=first_name, last_name=last_name, group=group, parent_first_name_1 = parent_first_name_1, parent_last_name_1 = parent_last_name_1, parent_email_1 = parent_email_1, parent_text_phone_1 = parent_text_phone_1, parent_voice_phone_1 = parent_voice_phone_1, parent_first_name_2 = parent_first_name_2, parent_last_name_2 = parent_last_name_2, parent_email_2 = parent_email_2, parent_text_phone_2 = parent_text_phone_2, parent_voice_phone_2 = parent_voice_phone_2, messages=[e.message]) results['failures'].append(result) error = "Unable to import direct contact" create_error_log(error, 'ERR')
def get(self, event_id, number, *args, **kwargs): import sendgrid import settings from datetime import datetime from sosbeacon.event.message import Message from sosbeacon.event.student_marker import StudentMarker session_store = sessions.get_store() session = session_store.get_session() user_urlsafe = session.get('u') user_key = ndb.Key(urlsafe=user_urlsafe).get() event_key = ndb.Key(urlsafe=event_id) query_messages = Message.query(Message.event == event_key).fetch() body = "" for i in number: # list comment message if i == "1": list_comment = Message.query(Message.event == event_key, Message.message_type == 'c') title = "Responder messages" body += str( self.responder_messages(user_key, title, list_comment)) # list student marker Responders if i == "2": query_response = StudentMarker.query( StudentMarker.event == event_key, StudentMarker.is_direct == True, StudentMarker.acknowledged == True) student_markers = query_response.fetch() title = "Responder List" body += str(self.email_student_marker(student_markers, title)) # list student marker Non Responders if i == "3": query_response = StudentMarker.query( StudentMarker.event == event_key, StudentMarker.acknowledged == False, StudentMarker.is_direct == True) student_markers = query_response.fetch() title = "No Responder List" body += str(self.email_student_marker(student_markers, title)) # list message email if i == "4": title = "Alert Messages" body += str( self.email_broadcast_message(user_key, title, query_messages)) today = datetime.today() today = today.strftime('%Y-%m-%d %H:%M') subject = "Download data sent from SOSbeacon Message Center %s" % today email = user_key.email s = sendgrid.Sendgrid(settings.SENDGRID_ACCOUNT, settings.SENDGRID_PASSWORD, secure=True) message = sendgrid.Message(settings.SENDGRID_SENDER, subject, body, body) message.add_to(str(email)) try: s.web.send(message) except: error = "Can not download email." create_error_log(error, 'ERR')
def send_email_robocall_to_user(event_urlsafe, user_urlsafe, message_urlsafe, phones): from sosbeacon.event.contact_marker import ContactMarker import sendgrid import settings if not event_urlsafe: logging.error('No event key given.') return # TODO: Use event id rather than key here for namespacing purposes? event_key = ndb.Key(urlsafe=event_urlsafe) event = event_key.get() user_key = ndb.Key(urlsafe=user_urlsafe) user = user_key.get() message_key = ndb.Key(urlsafe=message_urlsafe) message = message_key.get() if not event: logging.error('Event %s not found!', event_key) error = 'Event %s not found!' % event_key create_error_log(error, 'ERR') return if event.status == EVENT_STATUS_CLOSED: logging.error('Event %s closed!', event_key) error = 'Event %s not found!' % event_key create_error_log(error, 'ERR') return if not user: logging.error('User %s not found!', user_key) error = 'User %s not found!' % user_key create_error_log(error, 'ERR') return if not message: logging.error('Message %s not found!', message_key) error = 'Message %s not found!' % message_key create_error_log(error, 'ERR') return logging.info('Sending notice to %s via mail api.', user.email) # contact_markers = ContactMarker.query(ContactMarker.event == event_key, # ContactMarker.acknowledged == False) string_date = "%s %s, %s at %s:%s %s (GMT)" % ( event.added.strftime("%B"), event.added.strftime("%d"), event.added.strftime("%Y"), event.added.strftime("%I"), event.added.strftime("%M"), event.added.strftime("%p")) subject = "School Beacon ROBOCALL service for alert %s was requested by you" % event_key.id( ) body = "School Beacon ROBOCALL service for alert <span style='color: red'>%s</span> was requested by you" % event_key.id( ) body = body + " on " + "<br><span style='color:red'>" + string_date + "</span>.<br><br>" + " The following numbers were called: <br>" # for contact_marker in contact_markers: # logging.info(contact_marker) # logging.info(contact_marker.methods) # for method in contact_marker.methods: # logging.info(method) # if '@' not in method: # body += str(method) + '<br>' for phone in phones: body += str(phone) + '<br>' body += "<br><br>The following text was delivered:<br> <span style='color:red'>%s</span>" % message.message[ 'email'] s = sendgrid.Sendgrid(settings.SENDGRID_ACCOUNT, settings.SENDGRID_PASSWORD, secure=True) email = sendgrid.Message(user.email, subject, body, body) email.add_to(user.email) s.web.send(email)