def PracticeIVR_ForwardCall_Vet(request): """ This function is executed on Number nouns within Dial verbs. The idea is to try to determine if it's a human who picked up, or a machine. Alternatively, this gives the called party a chance to send the call to voicemail without the caller knowing they're rejecting the call. """ logger.debug('%s: PracticeIVR_ForwardCall_Vet ' % (request.session.session_key)) r = twilio.Response() # First, find the recording to play callSID = request.POST['CallSid'] # second leg calls have their own callSIDs - may need parentCallSID (log, plog) = _getCallLogOrParent(request) if (request.method == 'POST' and 'Digits' in request.POST): # Connect the calls log.call_connected = True log.save() if plog: plog.call_connected = True plog.save() logger.debug('%s: PracticeIVR_ForwardCall_Vet update parent of logsid %s plogSID %s' % (request.session.session_key, log.callSID, plog.callSID)) event = callEvent(callSID=callSID, event='C_ACC') event.save() return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) caller_spoken_name = log.caller_spoken_name gather = twilio.Gather(numDigits=1, finishOnKey='', action=reverse('PracticeIVR_ForwardCall_Vet')) if('click2call' in request.session): gather.append(tts(_("You have a call from"))) gather.append(twilio.Play(caller_spoken_name)) gather.append(tts(_("Press any key to accept."))) else: gather.append(tts(_("You have an urgent answering service call from"))) gather.append(twilio.Play(caller_spoken_name)) gather.append(tts(_("Press any key to accept."))) r.append(gather) r.append(twilio.Hangup()) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE)
def getRecording_playRecordingAndConfirmation(request, twilioResponse): gather = twilio.Gather(numDigits=1, finishOnKey='', action=reverse('getRecording')) gather.append(tts(_("You said"))) gather.append(twilio.Play(request.session['ivr_makeRecording_recording'])) gather.append(tts(_('If you wish to record again, please press three.' 'Press one to continue. Press any other key to replay the recording.'))) twilioResponse.append(gather) twilioResponse.append(twilio.Redirect())
def testPlayHelloLoop(self): """should play hello monkey loop""" r = Response() r.append(twiml.Play("http://hellomonkey.mp3", loop=3)) r = self.strip(r) self.assertEqual( r, '<?xml version="1.0" encoding="UTF-8"?><Response><Play loop="3">http://hellomonkey.mp3</Play></Response>' )
def testEmptyPlay(self): """should play hello monkey""" r = Response() r.append(twiml.Play("")) r = self.strip(r) self.assertEqual( r, '<?xml version="1.0" encoding="UTF-8"?><Response><Play /></Response>' )
def testPlayDigits(self): """ should play digits """ r = Response() r.append(twiml.Play(digits='w123')) r = self.strip(r) self.assertEqual( r, '<?xml version="1.0" encoding="UTF-8"?><Response><Play digits="w123" /></Response>' )
def testNestedSayPlayPause(self): """ a gather with a say, play, and pause """ r = Response() g = twiml.Gather() g.append(twiml.Say("Hey")) g.append(twiml.Play("hey.mp3")) g.append(twiml.Pause()) r.append(g) r = self.strip(r) assert_equal(r, '<?xml version="1.0" encoding="UTF-8"?><Response><Gather><Say>Hey</Say><Play>hey.mp3</Play><Pause /></Gather></Response>')
def PracticeIVR_CallerResponse_New(request, twilioResponse=None): """ This function process callers response - set up practice greeting based on practice hours and callgroups and specialties (via create_dynamic_greeting) """ request.session['ivr2_state'] = 'PracticeIVR_CallerResponse_New' practice = PracticeLocation.objects.get(id=request.session['practice_id']) logger.debug('%s: PracticeIVR_CallerResponse_New state %s practice %s' % ( request.session.session_key, request.session['ivr2_state'], practice)) r = twilioResponse or twilio.Response() gather = twilio.Gather(action=reverse('PracticeIVR_CallerResponse_Action'), finishOnKey='', numDigits=1, timeout=60) if (not 'practice_greeting' in request.session): if (practice.is_open()): request.session['practice_greeting'] = practice.greeting_lunch else: request.session['practice_greeting'] = practice.greeting_closed if(practice.skip_to_rmsg and practice.is_open()): request.session['ivr2_state'] = 'PracticeIVR_LeaveRegularMsg_New' r.append(twilio.Play(request.session['practice_greeting'])) r.append(twilio.Redirect(reverse('PracticeIVR_LeaveRegularMsg_New'))) logger.debug('%s: PracticeIVR_CallerResponse_New skip to leave msg for %s open greeting' % ( request.session.session_key, practice)) else: if practice.uses_original_answering_serice(): gather.append(twilio.Play(request.session['practice_greeting'])) r.append(gather) logger.debug('%s: PracticeIVR_CallerResponse_New practice %s orig greeting' % ( request.session.session_key, practice)) else: #layer 1 greeting, it recites call group lists, #populates request.session['call_groups_map'] and request.session['specialty_map'] dynamic_greeting = create_dynamic_greeting(request, practice) request.session['last_played'] = dynamic_greeting gather.append(twilio.Play(request.session['practice_greeting'])) gather.append(tts(_('%s.') % (''.join(request.session['last_played'])))) r.append(gather) logger.debug('%s: PracticeIVR_CallerResponse_New practice %s greeting %s' % ( request.session.session_key, practice, request.session['last_played'])) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE)
def improperAppend(self, verb): self.assertRaises(TwimlException, verb.append, twiml.Say("")) self.assertRaises(TwimlException, verb.append, twiml.Gather()) self.assertRaises(TwimlException, verb.append, twiml.Play("")) self.assertRaises(TwimlException, verb.append, twiml.Record()) self.assertRaises(TwimlException, verb.append, twiml.Hangup()) self.assertRaises(TwimlException, verb.append, twiml.Reject()) self.assertRaises(TwimlException, verb.append, twiml.Redirect()) self.assertRaises(TwimlException, verb.append, twiml.Dial()) self.assertRaises(TwimlException, verb.append, twiml.Conference("")) self.assertRaises(TwimlException, verb.append, twiml.Sms("")) self.assertRaises(TwimlException, verb.append, twiml.Pause())
def ProviderIVR_ForwardCall_VetAnswer(request): """ This function is executed on Number nouns within Dial verbs. The idea is to try to determine if it's a human who picked up, or a machine. Alternatively, this gives the called party a chance to send the call to voicemail without the caller knowing they're rejecting the call. """ r = twilio.Response() request.session.modified = True callSID = request.POST['CallSid'] log = callLog.objects.get(callSID=callSID) if (request.method == 'POST' and 'Digits' in request.POST): # Connect the calls log.call_connected = True log.save() event = callEvent(callSID=callSID, event='C_ACC') event.save() return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) caller_spoken_name = log.caller_spoken_name if (log.mdcom_caller): # Great. Is it a Provider? if (isinstance(log.mdcom_caller, Provider) and log.mdcom_caller.vm_config.count()): vm_config = log.mdcom_caller.vm_config.get() if (vm_config.config_complete): caller_spoken_name = vm_config.name gather = twilio.Gather(numDigits=1, finishOnKey='', action=reverse('ProviderIVR_ForwardCall_VetAnswer')) gather.append(tts("You have a call from")) gather.append(twilio.Play(caller_spoken_name)) gather.append(tts("Press any key to accept.")) r.append(gather) r.append(twilio.Hangup()) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE)
def testPlayBadAppend(self): """ should raise exceptions for wrong appending """ self.improperAppend(twiml.Play(""))
def testPlayAddAttribute(self): """ add attribute """ r = twiml.Play("", foo="bar") r = self.strip(r) assert_equal(r, '<?xml version="1.0" encoding="UTF-8"?><Play foo="bar" />')
def ProviderIVR_ForwardCall_Vet(request): """ This function is executed on Number nouns within Dial verbs. The idea is to try to determine if it's a human who picked up, or a machine. Alternatively, this gives the called party a chance to send the call to voicemail without the caller knowing they're rejecting the call. """ logger.debug('%s: ProviderIVR_ForwardCall_Vet POST %s' % (request.session.session_key, str(request.POST))) r = twilio.Response() callSID = request.POST['CallSid'] # second leg calls have their own callSIDs - may need parentCallSID (log, plog) = _getCallLogOrParent(request) if (request.method == 'POST' and 'Digits' in request.POST): # Connect the calls, get parent log if any if log: logger.debug( '%s: ProviderIVR_ForwardCall_Vet connected callsid %s logSID %s' % (request.session.session_key, callSID, log.callSID)) log.call_connected = True log.save() if plog: plog.call_connected = True plog.save() logger.debug( '%s: ProviderIVR_ForwardCall_Vet update parent of logsid %s plogSID %s' % (request.session.session_key, log.callSID, plog.callSID)) else: logger.debug( '%s: ProviderIVR_ForwardCall_Vet connected log not found %s' % (request.session.session_key, callSID)) event = callEvent(callSID=request.POST['CallSid'], event='C_ACC') event.save() return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) if log: caller_spoken_name = log.caller_spoken_name if (log.mdcom_caller): # Great. Is it a Provider? if (isinstance(log.mdcom_caller, Provider) and log.mdcom_caller.vm_config.count()): vm_config = log.mdcom_caller.vm_config.get() if (vm_config.config_complete): caller_spoken_name = vm_config.name else: logger.debug( '%s: ProviderIVR_ForwardCall_Vet call log sid %s not found' % (request.session.session_key, callSID)) gather = twilio.Gather(numDigits=1, finishOnKey='', action=reverse('ProviderIVR_ForwardCall_Vet')) gather.append(tts("You have a call from")) gather.append(twilio.Play(caller_spoken_name)) gather.append(tts("Press any key to accept.")) r.append(gather) r.append(twilio.Hangup()) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE)
def ProviderIVR_LeaveMsg(request): """ Records a voicemail message. Arguments: request - The standard Django request argument request.session Keys: provider_id - The ID of the Provider user who owns this voicemail box. """ # TODO: Update this code so that users can hit the pound key to # pop back and log into their own voicemail box. provider = Provider.objects.get(id=request.session['provider_id']) config = None config_complete = provider.vm_config.count( ) == 1 and provider.vm_config.get().config_complete if (config_complete): config = provider.vm_config.get() if ('CallStatus' in request.POST and request.POST['CallStatus'] == 'completed'): try: callSID = request.POST['CallSid'] auth, uri, = client.auth, client.account_uri resp = make_twilio_request('GET', uri + '/Calls/%s' % callSID, auth=auth) content = json.loads(resp.content) log = callLog.objects.get(callSID=callSID) log.call_duration = content['TwilioResponse']['Call']['Duration'] log.save() except: pass # this is really ugly, but letting this exception fall through # destroys a message analytics will pick up the duration later on if it's missing if ('ivr_makeRecording_recording' in request.session): provider_qs = Provider.objects.filter( mobile_phone=request.session['Caller']) if (provider_qs): request.session['ivr_makeRecording_callbacknumber'] = provider_qs[ 0].mdcom_phone subject = "Voice Mail from %s %s" % (provider_qs[0].first_name, provider_qs[0].last_name) else: request.session[ 'ivr_makeRecording_callbacknumber'] = request.session['Caller'] subject = "Voice Mail from %s" % request.session[ 'ivr_makeRecording_callbacknumber'] save_message(request, subject, [provider.user], None, "VM", False) request.session.pop('ivr_makeRecording_recording') r = twilio.Response() r.append(tts('Good bye')) r.append(twilio.Hangup()) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) # Get the configuration file for this Provider if (not config_complete): # FIXME: # Probably not the best way to create the spoken number. We need to # break the number down so that there are spaces between each digit, and # so that there are commas after the third and sixth digits. if (not 'Called' in request.session or (not request.session['Called'])): # This will occur if click2call calls this function request.session['ivr_makeRecording_prompt'] = tts( 'The user is not available. ' 'Please leave a message after the beep. Press pound when finished for options.' ) else: number = request.session['Called'] spoken_number = [] [spoken_number.extend([i, ' ']) for i in number] spoken_number.pop() # drop the last element spoken_number.insert(5, ',') spoken_number.insert(12, ',') request.session['ivr_makeRecording_prompt'] = tts( 'The person at %s ' 'is not available. Please leave a message after the beep. Press pound ' 'when finished for options.' % (''.join(spoken_number), )) else: p = re.compile('http') if (p.match(config.greeting)): # This is a Twilio recording. request.session['ivr_makeRecording_prompt'] = twilio.Play( config.greeting) else: # TODO: raise Exception('Unimplemented playback of local files') request.session['ivr_makeRecording_maxLength'] = 120 # 2 minutes request.session['ivr_makeRecording_leadSilence'] = 2 request.session['ivr_makeRecording_promptOnce'] = True request.session['ivr_makeRecording_returnOnHangup'] = \ 'MHLogin.DoctorCom.IVR.views_provider.ProviderIVR_LeaveMsg' request.session['ivr_call_stack'].append('ProviderIVR_LeaveMsg') request.session.modified = True # Pass off the recording action to the getRecording function. return getRecording(request)
def playMessages(request, msgs_querySet=None, twilioResponse=None): """Plays and gives the menu tree to act on messages. :param request: the usual Django view argument :param msgs_querySet: django query set of voice messages :param twilioResponse: None if direct from Twilio, set if called within IVR :returns: django.http.HttpResponse -- the result """ # msgs_querySet is None when called from Twilio and session is setup if msgs_querySet != None: # msgs_querySet is not None when called within IVR tree but may be empty set request.session['ivr_playMessages_newMessages'] = list(msgs_querySet.filter( read_flag=False, delete_flag=False).order_by('msg_body__message__message_type', '-msg_body__message__send_timestamp').all()) if len(request.session['ivr_playMessages_newMessages']): request.session['ivr_playMessages_newMsgsFlag'] = True request.session['ivr_playMessages_oldMessages'] = list(msgs_querySet.filter( read_flag=True, delete_flag=False).order_by('msg_body__message__message_type', '-msg_body__message__send_timestamp').all()) # We're pretty much always going to be manipulating the session. request.session.modified = True r = twilioResponse or twilio.Response() replayFlag = False playFlag = True call_sid = request.POST['CallSid'] if (not msgs_querySet and 'Digits' in request.POST): digits = request.POST['Digits'] p = re.compile('[0-9#*]$') if (not p.match(digits)): r.append(tts('I\'m sorry, I didn\'t understand that.')) playFlag = False if (digits == '1'): # do nothing pass elif (digits == '3'): replayFlag = True elif (digits == '5'): return callBackUser(request, request.session['ivr_playMessages_currentMsg'].msg_body.message) elif (digits == '7'): # Merely sets the 'deleted' flag to hide the message. r.append(tts('Message resolved')) event = callEvent(callSID=call_sid, event='V_MDL') event.save() target = callEventTarget(event=event, target=request.session['ivr_playMessages_currentMsg']) target.save() request.session['ivr_playMessages_currentMsg'].\ msg_body.message.resolved_by = request.user elif (digits == '9'): r.append(twilio.Redirect(reverse(request.session['ivr_call_stack'].pop()))) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) if (replayFlag): r.append(tts('Re-playing message')) elif (not playFlag): pass # do nothing -- we don't want to move to the next message. elif (len(request.session['ivr_playMessages_newMessages'])): if (msgs_querySet): r.append(tts('Playing the first new message')) else: r.append(tts('Playing the next new message')) request.session['ivr_playMessages_currentMsg'] = \ request.session['ivr_playMessages_newMessages'].pop(0) event = None if(request.session['ivr_playMessages_currentMsg'].msg_body.message.message_type == 'ANS'): event = callEvent(callSID=call_sid, event='V_NAP') event.save() else: event = callEvent(callSID=call_sid, event='V_NMP') event.save() target = callEventTarget(event=event, target=request.session['ivr_playMessages_currentMsg']) target.save() request.session['ivr_playMessages_currentMsg'].read_flag = True request.session['ivr_playMessages_currentMsg'].save() elif (len(request.session['ivr_playMessages_oldMessages'])): #if (request.session['ivr_playMessages_newMsgsFlag']): # Done playing new messages. # pass if (msgs_querySet): r.append(tts('Playing the first old message')) else: r.append(tts('Playing the next old message')) request.session['ivr_playMessages_currentMsg'] = \ request.session['ivr_playMessages_oldMessages'].pop(0) event = None if(request.session['ivr_playMessages_currentMsg'].msg_body.message.message_type == 'ANS'): event = callEvent(callSID=call_sid, event='V_OAP') event.save() else: event = callEvent(callSID=call_sid, event='V_OMP') event.save() target = callEventTarget(event=event, target=request.session['ivr_playMessages_currentMsg']) target.save() else: r.append(tts('End of messages')) r.append(twilio.Redirect(reverse(request.session['ivr_call_stack'].pop()))) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) gather = twilio.Gather(finishOnKey='', numDigits=1, action=reverse('playMessages')) if (playFlag): url = '' if (request.session['ivr_playMessages_currentMsg'].\ msg_body.message.message_type == 'ANS'): spoken_number = [] digits = request.session['ivr_playMessages_currentMsg'].\ msg_body.message.callback_number [spoken_number.extend([i, ' ']) for i in digits] spoken_number.pop() # drop the last element #spoken_number.insert(5, ',') #spoken_number.insert(12, ',') gather.append(tts('Call from %s .' % (''.join(spoken_number),))) msg = request.session['ivr_playMessages_currentMsg'].msg_body.message try: uuid = MessageAttachment.objects.get(message=msg).uuid url = reverse("fetchRecording", kwargs={"uuid": uuid}) gather.append(twilio.Play(url)) except MessageAttachment.DoesNotExist: errors = { 'U': _("User hung up before confirming number."), 'C': _("User hung up before leaving message."), 'R': _("An error occurred downloading the recording. We will retry until " "successful and you will receive a new message at that time."), } gather.append(tts(errors[msg.vmstatus])) gather.append(twilio.Pause()) gather.append(tts(_('Press 1 to move to the next message. '))) gather.append(tts(_('Press 3 to re-play the message. '))) callback_number = request.session['ivr_playMessages_currentMsg'].\ msg_body.message.callback_number if(re.match("1?\d{10}", callback_number)): gather.append(tts(_('Press 5 to call this person back. '))) gather.append(tts(_('Press 7 to mark the message resolved and hide it. '))) gather.append(tts(_('Press 9 to return to the main menu. '))) r.append(gather) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE)