def send_alert(self): ''' This method sends alerts to people who need to get one via sms, phone, or email. ''' logging.debug("Sending alert: %s" % self.id) try: oncall_users_raw = User.on_call(self.team) team_users = User.team_entities(self.team) if len(oncall_users_raw) > 0: oncall_users = [] self.tries += 1 self.lastAlertSent = datetime.datetime.now() self.save_alert() # grouping users into 2D arrays by state oncall_users = User.sort_by_state(oncall_users_raw) # filtering on call list with only ones to alert if "alert_escalation" in conf and conf['alert_escalation'] > 0: escalate = float(conf['alert_escalation']) num = int(math.ceil(self.tries / escalate)) if num == 0: num = 1 alert_users = oncall_users[:num] else: # just grabbing the primary users (state == 1) alert_users = oncall_users[0] # going through list of users (2-dimensional list) to send alerts to and send alerts for au in alert_users: for u in au: if "call_failover" in conf: if conf['call_failover'] == 0: twilio.make_call(u, self) else: # check to see if enough tries have been made to this user to switch to calls instead of SMS if int(math.ceil(self.tries / float( u.state))) > conf['call_failover']: twilio.make_call(u, self) else: twilio.send_sms( u, self.id, self.subject + "\n" + self.message) else: twilio.send_sms(u, self.id, self.subject + "\n" + self.message) # check if enough tries have been made to send a team notification via email if "team_failover" in conf and ( conf['team_failover'] == 0 or conf['team_failover'] >= self.tries): for t in team_users: e = Email.Email(t, self) e.send_alert_email() else: #oops no one is on call at the moment. Fall back to a team alert via email logging.error("No one is currently on call") for t in team_users: e = Email.Email(t, self) e.send_alert_email() except Exception, e: logging.error(e.__str__())
def send_alert(self): ''' This method sends alerts to people who need to get one via sms, phone, or email. ''' logging.debug("Sending alert: %s" % self.id) try: oncall_users_raw = User.on_call(self.team) team_users = User.team_entities(self.team) if len(oncall_users_raw) > 0: oncall_users = [] self.tries += 1 self.lastAlertSent = datetime.datetime.now() self.save_alert() # grouping users into 2D arrays by state oncall_users = User.sort_by_state(oncall_users_raw) # filtering on call list with only ones to alert if "alert_escalation" in conf and conf['alert_escalation'] > 0: escalate = float(conf['alert_escalation']) num = int(math.ceil(self.tries/escalate)) if num == 0: num = 1 alert_users = oncall_users[:num] else: # just grabbing the primary users (state == 1) alert_users = oncall_users[0] # going through list of users (2-dimensional list) to send alerts to and send alerts for au in alert_users: for u in au: if "call_failover" in conf: if conf['call_failover'] == 0: twilio.make_call(u, self) else: # check to see if enough tries have been made to this user to switch to calls instead of SMS if int(math.ceil(self.tries/float(u.state))) > conf['call_failover']: twilio.make_call(u, self) else: twilio.send_sms(u, self.id, self.subject + "\n" + self.message) else: twilio.send_sms(u, self.id, self.subject + "\n" + self.message) # check if enough tries have been made to send a team notification via email if "team_failover" in conf and (conf['team_failover'] == 0 or conf['team_failover'] >= self.tries): for t in team_users: e = Email.Email(t,self) e.send_alert_email() else: #oops no one is on call at the moment. Fall back to a team alert via email logging.error("No one is currently on call") for t in team_users: e = Email.Email(t,self) e.send_alert_email() except Exception, e: logging.error(e.__str__())
def oncall_status(opts): ''' Get a list of people oncall for a specific team ''' users = User.on_call(opts.team) oncall_users = [] for u in users: if u.state > 0 and u.state < 9: oncall_users.append(u) if len(oncall_users) == 0: return "No one is on call on the %s team." % (opts.team) output = '' for user in oncall_users: output=output + "%s" % (user.print_user(opts.mobile)) return output
def POST(self, name): d = web.input(init="true", Digits=0) logging.info("Receiving phone call\n%s" % (d)) web.header('Content-Type', 'text/xml') r = twilio.twiml.Response() # the message to say when a timeout occurs timeout_msg = "Sorry, didn't get any input from you. Goodbye." # check if this call was initialized by sending an alert if name == "alert": # the digit options to press digitOpts = ''' Press 1 to hear the message. Press 2 to acknowledge this alert. ''' receiver = User.get_user_by_phone(d.To) alert = Alert.Alert(d.alert_id) # check if this is the first interaction for this call session if d.init.lower() == "true": with r.gather( action="%s:%s/call/alert?alert_id=%s&init=false" % (conf['server_address'], conf['port'], alert.id), timeout=conf['call_timeout'], method="POST", numDigits="1") as g: g.say( '''Hello %s, a message from Oncall. An alert has been issued with subject "%s". %s.''' % (receiver.name, alert.subject, digitOpts)) r.say(timeout_msg) else: if int(d.Digits) == 1: with r.gather( action="%s:%s/call/alert?alert_id=%s&init=false" % (conf['server_address'], conf['port'], alert.id), timeout="30", method="POST", numDigits="1") as g: g.say('''%s. %s''' % (alert.message, digitOpts)) r.say(timeout_msg) elif int(d.Digits) == 2: if alert.ack_alert(receiver): r.say( "The alert has been acknowledged. Thank you and goodbye." ) r.redirect( url="%s:%s/call/alert?alert_id=%s&init=false" % (conf['server_address'], conf['port'], alert.id)) else: r.say( "Sorry, failed to acknowledge the alert. Please try it via SMS" ) r.redirect( url="%s:%s/call/alert?alert_id=%s&init=false" % (conf['server_address'], conf['port'], alert.id)) elif d.Digits == 0: with r.gather( action="%s:%s/call/alert?alert_id=%s&init=false" % (conf['server_address'], conf['port'], alert.id), timeout="30", method="POST", numDigits="1") as g: g.say('''%s''' % (digitOpts)) r.say(timeout_msg) else: r.say( "Sorry, didn't understand the digits you entered. Goodbye" ) else: requester = User.get_user_by_phone(d.From) # get the team that is associate with this phone number the user called team = twilio.twil_reverse_phone_num(d.To) # if caller is not a oncall user or they are, but calling a different team then they are in if requester == False or requester.team != team: if team == '': r.say( "Sorry, The phone number you called is not associated with any team. Please contact you system administrator for help." ) else: # get the first user on call and forward the call to them oncall_users = User.sort_by_state(User.on_call(team)) if len(oncall_users) > 0: foundOncallUser = False for userlist in oncall_users: for u in userlist: r.say("Calling %s." % u.name) r.dial(number=u.phone) foundOncallUser = True break if foundOncalluser == True: break else: r.say( "Sorry, currently there is no one on call for %s. Please try again later." % team) else: # the caller is calling the same team phone number as the team that they are on # check if d.Digits is the default value (meaning, either the caller hasn't pushed a button and this is the beginning of the call, or they hit 0 to start over if int(d.Digits) == 0: if d.init.lower() == "true": if requester.state > 0 and requester.state < 9: oncall_status = "You are currently on call in spot %s" % ( requester.state) else: oncall_users = User.sort_by_state( User.on_call(requester.team)) if len(oncall_users) > 0: for userlist in oncall_users: for u in userlist: oncall_status = "Currenty, %s is on call" % ( u.name) else: oncall_status = "Currenty, no one is on call" with r.gather(action="%s:%s/call/event?init=false" % (conf['server_address'], conf['port']), timeout=conf['call_timeout'], method="POST", numDigits="1") as g: g.say( '''Hello %s. %s. Press 1 if you want to hear the present status of alerts. Press 2 to acknowledge the last alert sent to you. Press 3 to conference call everyone on call into this call.''' % (requester.name, oncall_status)) else: with r.gather(action="%s:%s/call/event?init=false" % (conf['server_address'], conf['port']), timeout=conf['call_timeout'], method="POST", numDigits="1") as g: g.say( '''Press 1 if you want to hear the present status of alerts. Press 2 to acknowledge the last alert sent to you. Press 3 to conference call everyone on call into this call.''' ) r.say(timeout_msg) elif int(d.Digits) == 1: # getting the status of alerts r.say(oncall.run("alert status -f " + requester.phone)) r.redirect(url="%s:%s/call/event?init=false" % (conf['server_address'], conf['port'])) elif int(d.Digits) == 2: # acking the last alert sent to the user calling r.say(oncall.run("alert ack -f " + requester.phone)) r.redirect(url="%s:%s/call/event?init=false" % (conf['server_address'], conf['port'])) elif int(d.Digits) == 3: # calling the other users on call oncall_users_raw = User.on_call(requester.team) for user in oncall_users_raw: if user.phone == requester.phone: continue r.say("Calling %s." % user.name) r.dial(number=user.phone) else: r.say( "Sorry, number you pressed is not valid. Please try again." ) return r