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 testRedirectEmpty(self): r = Response() r.append(twiml.Redirect()) r = self.strip(r) self.assertEquals( r, '<?xml version="1.0" encoding="UTF-8"?><Response><Redirect /></Response>' )
def testRedirectMethod(self): r = Response() r.append(twiml.Redirect(url="example.com", method="POST")) r = self.strip(r) self.assertEquals( r, '<?xml version="1.0" encoding="UTF-8"?><Response><Redirect method="POST">example.com</Redirect></Response>' )
def testRedirectMethodGetParams(self): r = Response() r.append( twiml.Redirect(url="example.com?id=34&action=hey", method="POST")) r = self.strip(r) assert_equal( r, '<?xml version="1.0" encoding="UTF-8"?><Response><Redirect method="POST">example.com?id=34&action=hey</Redirect></Response>' )
def PracticeIVR_Options_Actions(request, internalCall=False): """ changes setting on doctor com number for practice """ #practice = PracticeLocation.objects.get(id=request.session['practice_id']) logger.debug('%s: PracticeIVR_Options_Actions POST data is %s' % ( request.session.session_key, str(request.POST))) if (not internalCall and request.method == 'POST' and 'Digits' in request.POST): digits = request.POST['Digits'] p = re.compile('[0-9#*]$') if (not p.match(digits)): r = twilio.Response() r.append(tts(_('I\'m sorry, I didn\'t understand that.'))) elif (digits == '1'): # Change name request.session['ivr2_sub_state'] = 'PracticeIVR_Options_1' request.session.modified = True return changeNameNew(request) elif (digits == '3'): # Change closed greeting - ivr2_setup_stage to indicate which greeting # request.session['ivr2_setup_stage'] = 3 # deprecated request.session['ivr2_sub_state'] = 'PracticeIVR_Options_2' request.session.modified = True return changeGreetingNew(request) elif (digits == '5'): # change temporarily closed office greeting # request.session['ivr2_setup_stage'] = 5 # deprecated request.session['ivr2_sub_state'] = 'PracticeIVR_Options_3' request.session.modified = True return changeGreetingNew(request) elif (digits == '7'): # change pin request.session['ivr2_sub_state'] = 'PracticeIVR_Options_4' request.session.modified = True return changePinNew(request) elif (digits == '9'): # Return to the main menu r = twilio.Response() request.session['ivr2_state'] = 'PracticeIVR_TreeRoot_New' r.append(twilio.Redirect(reverse('PracticeIVR_TreeRoot_New'))) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) elif (digits == '*'): # Repeat menu r = twilio.Response() pass else: r = twilio.Response() r.append(tts(_('I\'m sorry, that wasn\'t a valid selection.'))) return PracticeIVR_Options_New(request, r) else: # should never happen but if we get here, we log and goto main logger.debug('%s: PracticeIVR_Options_Actions is called with no post or digits' % ( request.session.session_key)) request.session['ivr2_state'] = 'PracticeIVR_Main_New' return PracticeIVR_Main_New(request)
def testImproperNesting(self): """ bad nesting """ verb = twiml.Gather() self.assertRaises(TwimlException, verb.append, twiml.Gather()) self.assertRaises(TwimlException, verb.append, twiml.Record()) self.assertRaises(TwimlException, verb.append, twiml.Hangup()) 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(""))
def ProviderIVR_Options(request, internalCall=False): r = twilio.Response() if (not internalCall and request.method == 'POST' 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.')) elif (digits == '1'): # Change name request.session['ivr_call_stack'].append('ProviderIVR_Options') request.session.modified = True event = callEvent(callSID=request.POST['CallSid'], event='F_NCH') return changeName(request) elif (digits == '3'): # Change greeting request.session['ivr_call_stack'].append('ProviderIVR_Options') request.session.modified = True event = callEvent(callSID=request.POST['CallSid'], event='F_GCH') return changeGreeting(request) elif (digits == '5'): # Change pin request.session['ivr_call_stack'].append('ProviderIVR_Options') request.session.modified = True event = callEvent(callSID=request.POST['CallSid'], event='F_PCH') return changePin(request, None, True) elif (digits == '*'): # Repeat menu pass elif (digits == '9'): # Return to the main menu r.append( twilio.Redirect( reverse(request.session['ivr_call_stack'].pop()))) request.session.modified = True return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) else: r.append(tts('I\'m sorry, that wasn\t a valid selection.')) gather = twilio.Gather(finishOnKey='', numDigits=1, action=reverse('ProviderIVR_Options')) gather.append(tts('Options menu')) gather.append(tts('To re-record your name, press 1')) gather.append(tts('To record a new greeting, press 3')) gather.append(tts('To change your pin, press 5')) gather.append(tts('To return to the main menu, press 9')) gather.append(tts('To repeat this menu, press star')) r.append(gather) 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 changeGreeting(request, prependPrompt=''): """Requests the user record their greeting and stores it in the config with id at request.session['config_id']. :param request: the usual Django view argument :param prependPrompt: The string to prepend to the start of the request. Note that sending None will result in an error. If you don't wish to prepend anything explicitly, please pass in an empty string. :returns: django.http.HttpResponse -- the result """ if ('ivr_makeRecording_recording' in request.session): if ('answering_service' in request.session and request.session['answering_service'] == 'yes'): practice = PracticeLocation.objects.get(id=request.session['practice_id']) if (request.session['ivr_setup_stage'] == 3): practice.greeting_closed = request.session['ivr_makeRecording_recording'] else: practice.greeting_lunch = request.session['ivr_makeRecording_recording'] del request.session['ivr_makeRecording_recording'] practice.save() else: config = VMBox_Config.objects.get(id=request.session['config_id']) config.greeting = request.session['ivr_makeRecording_recording'] del request.session['ivr_makeRecording_recording'] config.save() event = callEvent(callSID=request.POST['CallSid'], event='F_GCH') event.save() r = twilio.Response() r.append(twilio.Redirect(reverse(request.session['ivr_call_stack'].pop()))) request.session.modified = True return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) #make twilio say different things based on who called it, prepend seemed to #be never used, i will investigate later and see why not to use it if ('answering_service' in request.session and request.session['answering_service'] == 'yes'): if (request.session['ivr_setup_stage'] == 3): request.session['ivr_makeRecording_prompt'] = tts(_("Please say your " "new greeting for closed office after the tone. Press pound to finish.")) else: request.session['ivr_makeRecording_prompt'] = tts(_("Please say your greeting " "greeting for temporarily closed office after the tone. Press pound to finish.")) else: request.session['ivr_makeRecording_prompt'] = tts(_("Please say your new " "greeting after the tone. Press pound to finish.")) request.session['ivr_makeRecording_maxLength'] = 120 request.session['ivr_makeRecording_timeout'] = 3 request.session['ivr_call_stack'].append('changeGreeting') return getRecording(request)
def ProviderIVR_Options_Actions(request): """ Options to change VM settings - twilio calls back here We do the option processing here We track the ivr2_sub_state so we know where recording and pin go since we call the same method for setup """ assert (request.session['provider_id']) assert (request.session['ivr2_state'] == 'ProviderIVR_Options_New') provider = Provider.objects.get(id=request.session['provider_id']) logger.debug( '%s: ProviderIVR_Options_Actions provider %s POST data is %s' % (request.session.session_key, provider, str(request.POST))) r = twilio.Response() if (request.method == 'POST' 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.')) elif (digits == '1'): # Change name event = callEvent(callSID=request.POST['CallSid'], event='F_NCH') request.session['ivr2_sub_state'] = 'ProviderIVR_Options_1' return changeNameNew(request) elif (digits == '3'): # Change greeting event = callEvent(callSID=request.POST['CallSid'], event='F_GCH') request.session['ivr2_sub_state'] = 'ProviderIVR_Options_3' return changeGreetingNew(request) elif (digits == '5'): # change pin event = callEvent(callSID=request.POST['CallSid'], event='F_PCH') request.session['ivr2_sub_state'] = 'ProviderIVR_Options_5' return changePinNew(request) elif (digits == '9'): # Return to the main menu request.session['ivr2_state'] = 'ProviderIVR_TreeRoot_New' r.append(twilio.Redirect(reverse('ProviderIVR_TreeRoot_New'))) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) elif (digits == '*'): # Repeat menu pass else: r.append(tts('I\'m sorry, that wasn\'t a valid selection.')) return ProviderIVR_Options_New(request, r) else: # should never happen - but if we get here without Digits, we log and go back to Main logger.debug( '%s: ProviderIVR_TreeRoot_Actions is called with no post or digits' % (request.session.session_key)) request.session['ivr2_state'] = 'ProviderIVR_Main_New' return ProviderIVR_Main_New(request)
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 changeName(request, prependPrompt=''): """Requests the user record their name and stores it in the config with id at request.session['config_id']. :param request: the usual Django view argument :param prependPrompt: The string to prepend to the start of the request. Note that sending None will result in an error. If you don't wish to prepend anything explicitly, please pass in an empty string. :returns: django.http.HttpResponse -- the result """ if ('ivr_makeRecording_recording' in request.session): if ('answering_service' in request.session and request.session['answering_service'] == 'yes'): practice = PracticeLocation.objects.get(id=request.session['practice_id']) practice.name_greeting = request.session['ivr_makeRecording_recording'] del request.session['ivr_makeRecording_recording'] practice.save() else: config = VMBox_Config.objects.get(id=request.session['config_id']) config.name = request.session['ivr_makeRecording_recording'] del request.session['ivr_makeRecording_recording'] config.save() event = callEvent(callSID=request.POST['CallSid'], event='F_NCH') event.save() r = twilio.Response() r.append(twilio.Redirect(reverse(request.session['ivr_call_stack'].pop()))) request.session.modified = True return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) request.session['ivr_makeRecording_prompt'] = tts(_("Please say your name " "after the tone. Press pound to finish.")) request.session['ivr_makeRecording_maxLength'] = 10 request.session['ivr_makeRecording_timeout'] = 3 request.session['ivr_call_stack'].append('changeName') return getRecording(request)
def testAddAttribute(self): """ add attribute """ r = twiml.Redirect("", foo="bar") r = self.strip(r) assert_equal(r, '<?xml version="1.0" encoding="UTF-8"?><Redirect foo="bar" />')
def getQuickRecording(request): """Takes a recording from the user. This function uses the session dictionary at request.session for inputs and outputs. This is done to maintain code base flexibility with this and getRecording. This function differs from getRecording in that strictly gets a recording from the user, without allowing the user to confirm that they wish to keep the recording. :param request: The standard Django request argument :returns: django.http.HttpResponse -- the result Required Session Keys: request.session['ivr_makeRecording_prompt'] - A Twilio verb object (pretty much always Say or Play) that is used to lead into the recording. e.g., tts('Leave a message.') Optional Session Keys: request.session['ivr_makeRecording_maxLength'] - The Twilio gather max_length value. Default is 5: 5 seconds. request.session['ivr_makeRecording_timeout'] - The Twilio record timeout value. Default is 6. request.session['ivr_makeRecording_leadSilence'] - How many seconds of silence to give before starting any prompts. This is necessary because the first second or so of sound at the very beginning of any Twilio call is lost. Default is 1. request.session['ivr_makeRecording_playBeep'] - Set to True if you want the recording to be prompted with a tone. Default is True. request.session['ivr_makeRecording_finishOnKey'] - The Twilio gather finishOnKey value. Default is any key. Output Session Keys: request.session['ivr_makeRecording_recording'] - The Twilio URL of the recording Make sure you clear this key using the 'del' built-in function so that other fucntions can test against it to see if getRecording has succeeded. To "return" to your function, push it onto the end of request.session['ivr_call_stack'], as per the usual IVR philosophy. """ if 'CallStatus' in request.POST: logger.debug('%s: Into getQuickRecording with call status %s' % ( request.session.session_key, request.POST['CallStatus'])) r = twilio.Response() request.session.modified = True request.session['ivr_only_callbacknumber'] = True if 'CallStatus' in request.POST and request.POST['CallStatus'] == 'completed': view = request.session.get('ivr_makeRecording_returnOnHangup', None) if view: # The user hung up. Return out and tell twilio no message recorded. request.session['ivr_no_pound'] = True if 'RecordingUrl' in request.POST: request.session['ivr_makeRecording_recording'] = request.POST['RecordingUrl'] request.session['ivr_only_callbacknumber'] = False else: request.session['ivr_only_callbacknumber'] = True try: # TODO: no more exec() but validation on view is needed mod, func = view.rsplit('.', 1) mod = import_module(mod) getattr(mod, func)(request) # call the view function except Exception as e: mail_admins("Problem calling view in getQuickRecording", str(e)) cleanup_recording_state(request) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) if 'CallStatus' in request.POST and 'RecordingUrl' in request.POST: if request.POST['CallStatus'] == 'completed': # The user hung up. Return out and tell Twilio to do nothing. return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) recording_url = request.POST['RecordingUrl'] p1 = re.compile('http://api.twilio.com/\d{4}-\d{2}-\d{2}/Accounts/AC[0-9a-f]{32}'\ '/Recordings/RE[0-9a-f]{32}$') if (not p1.match(recording_url)): raise Exception(_('Recording url failed to match regex: %s') % (recording_url,)) request.session['ivr_makeRecording_recording'] = recording_url request.session['ivr_only_callbacknumber'] = False cleanup_recording_state(request) del request.session['getQuickRecording_subsequentExcecution'] r.append(twilio.Redirect(reverse(request.session['ivr_call_stack'].pop()))) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) # Check for required values if (not 'ivr_makeRecording_prompt' in request.session): raise Exception(_('Error. Required session key \'ivr_makeRecording_prompt\' ' 'undefined. Request.method is %s.') % (request.POST,)) # Set up default values if (not 'ivr_makeRecording_maxLength' in request.session): request.session['ivr_makeRecording_maxLength'] = 5 if (not 'ivr_makeRecording_timeout' in request.session): request.session['ivr_makeRecording_timeout'] = 6 if (not 'ivr_makeRecording_leadSilence' in request.session): request.session['ivr_makeRecording_leadSilence'] = 1 if (not 'ivr_makeRecording_playBeep' in request.session): request.session['ivr_makeRecording_playBeep'] = True if (not 'ivr_makeRecording_finishOnKey' in request.session): request.session['ivr_makeRecording_finishOnKey'] = '1234567890*#' # Use this to keep track of if we've been through here before. if ('getQuickRecording_subsequentExcecution' in request.session): r.append(tts('Sorry, I didn\'t get that.')) request.session['getQuickRecording_subsequentExcecution'] = True if (request.session['ivr_makeRecording_leadSilence']): r.append(twilio.Pause(length=request.session['ivr_makeRecording_leadSilence'])) r.append(request.session['ivr_makeRecording_prompt']) r.append(twilio.Record( action=reverse('getQuickRecording'), maxLength=request.session['ivr_makeRecording_maxLength'], finishOnKey=request.session['ivr_makeRecording_finishOnKey'], timeout=request.session['ivr_makeRecording_timeout'], playBeep=request.session['ivr_makeRecording_playBeep'], )) r.append(twilio.Redirect(reverse('getQuickRecording'))) #raise Exception(str(r)) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE)
def getRecording(request, twilioResponse=None): """ Takes a recording from the user. This function uses the session dictionary at request.session for inputs and outputs. This is necessary because Twilio will make multiple calls to this function. This function differs from getQuickRecording in that it allows a user to confirm their recording. :param request: The standard Django request argument :returns: django.http.HttpResponse -- the result Required Session Keys: request.session['ivr_makeRecording_prompt'] - A Twilio verb object (pretty much always Say or Play) that is used to lead into the recording. e.g., tts('Leave a message.') Optional Session Keys: request.session['ivr_makeRecording_promptOnce'] - A flag that specifies if the prompt should be spoken only once, if True. The stored value must be one that can be tested against for truth. (i.e., the value must be able to be used in an if statement such as, "if (request.session['ivr_makeRecording_promptOnce']):...." request.session['ivr_makeRecording_maxLength'] - The Twilio gather max_length value. Default is 180: 3 minutes. request.session['ivr_makeRecording_timeout'] - The Twilio record timeout value. Default is 5. request.session['ivr_makeRecording_transcribe'] - The Twilio gather transcribe value. Default is False. request.session['ivr_makeRecording_finishOnKey'] - The Twilio gather finishOnKey value. Default is any key. request.session['ivr_makeRecording_playBeep'] - The Twilio gather playBeep value. Default is True. request.session['ivr_makeRecording_leadSilence'] - How many seconds of silence to give before starting any prompts. This is necessary because the first second or so of sound at the very beginning of any Twilio call is lost. Default is 0. request.session['ivr_makeRecording_returnOnHangup'] - The name of the function to return control flow to, should the user hang up on the recording (e.g., to terminate a voicemail message). The function gets called with a single argument -- the standard Django request object, default is None. Output Session Keys: request.session['ivr_makeRecording_recording'] - The Twilio URL of the recording Make sure you clear this key using the 'del' built-in function so that other fucntions can test against it to see if getRecording has succeeded. To "return" to your function, push it onto the end of request.session['ivr_call_stack'], as per the usual IVR philosophy. """ # FIXME: # There's gotta be a less complicated way of doing this. The biggest # complicating factor when writing a generic function for Twilio is that # every time we want to get anything from the user, we need to return and # wait for Twilio to establish a new HTTP connection. # # There are two design patterns that I've come up with so far. The first is # what you see implemented here, where Twilio accesses this function # directly via a REST API we provide. The two biggest problems here are that # it requires us to rely heavily on the session database, and that we become # reliant on Twilio to functionally return to the calling function. This # second problem is generally annoying, but becomes a meaningful problem # when Twilio won't redirect for us -- e.g., when the user hangs up on the # recording. The current solution is to use an eval() statement to directly # call the "caller" function, but this is kind of kludgey. # # The other design pattern is to have Twilio keep calling the "caller" # function, and have that call this function. The problem is that it makes # caller functions more complicated since they have to check the return # data from this function to determine what happened, and potentially keep # track of where this function is, in terms of its execution path across # HTTP connections. # # I'm not sure what we want to do about this. I'm inclined to say that the # latter implementation is going to be somewhat cleaner since we can # probably just pass a tuple of values with state and whatnot, as well as # the return value for the function at large? if 'CallStatus' in request.POST: logger.debug('%s: Into getRecording with call status %s' % ( request.session.session_key, request.POST['CallStatus'])) r = twilioResponse or twilio.Response() request.session.modified = True # First, check to see if the caller has hung up. #if (request.POST['CallStatus'] == 'completed'): if ('CallStatus' in request.POST and request.POST['CallStatus'] == 'completed'): if('RecordingUrl' in request.POST): request.session['ivr_makeRecording_recording'] = request.POST['RecordingUrl'] if 'ivr_makeRecording_recording' in request.session: view = request.session.get('ivr_makeRecording_returnOnHangup', None) if view: try: # TODO: no more exec() but validation on view is needed mod, func = view.rsplit('.', 1) mod = import_module(mod) getattr(mod, func)(request) # call the view function except Exception as e: mail_admins("Problem calling view in getRecording", str(e)) cleanup_recording_state(request) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) if 'RecordingUrl' in request.POST: recording_url = request.POST['RecordingUrl'] p1 = re.compile('http://api.twilio.com/\d{4}-\d{2}-\d{2}/Accounts/AC[0-9a-f]'\ '{32}/Recordings/RE[0-9a-f]{32}$') if (not p1.match(recording_url)): raise Exception(_('Recording url failed to match regex: %s') % (recording_url,)) request.session['ivr_makeRecording_recording'] = recording_url getRecording_playRecordingAndConfirmation(request, r) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) elif ('ivr_makeRecording_recording' in request.session): if 'Digits' in request.POST: digits = request.POST['Digits'] p2 = re.compile('[0-9*#]$') if (not p2.match(digits)): raise Exception('') if (digits == '1'): # User accepted the recording. cleanup_recording_state(request) r.append(twilio.Redirect(reverse(request.session['ivr_call_stack'].pop()))) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) if (digits == '3'): del request.session['ivr_makeRecording_recording'] # And just fall through. User wishes to record again, so pretty much start over. else: getRecording_playRecordingAndConfirmation(request, r) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) else: getRecording_getConfirmation(request, r) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) # Check for required values if (not 'ivr_makeRecording_prompt' in request.session): raise Exception(_('Error. Required session key \'ivr_makeRecording_prompt\' undefined.')) # Set up default values if (not 'ivr_makeRecording_promptOnce' in request.session): request.session['ivr_makeRecording_promptOnce'] = False if (not 'ivr_makeRecording_maxLength' in request.session): request.session['ivr_makeRecording_maxLength'] = 180 if (not 'ivr_makeRecording_timeout' in request.session): request.session['ivr_makeRecording_timeout'] = 5 if (not 'ivr_makeRecording_transcribe' in request.session): request.session['ivr_makeRecording_transcribe'] = False if (not 'ivr_makeRecording_finishOnKey' in request.session): request.session['ivr_makeRecording_finishOnKey'] = '1234567890*#' if (not 'ivr_makeRecording_playBeep' in request.session): request.session['ivr_makeRecording_playBeep'] = True if (not 'ivr_makeRecording_leadSilence' in request.session): request.session['ivr_makeRecording_leadSilence'] = 0 if (not 'ivr_makeRecording_returnOnHangup' in request.session): request.session['ivr_makeRecording_returnOnHangup'] = None if (request.session['ivr_makeRecording_promptOnce']): if (not 'ivr_makeRecording_promptOnce_played' in request.session): request.session['ivr_makeRecording_promptOnce_played'] = True r.append(request.session['ivr_makeRecording_prompt']) else: r.append(request.session['ivr_makeRecording_prompt']) if (request.session['ivr_makeRecording_leadSilence']): r.append(twilio.Pause(length=request.session['ivr_makeRecording_leadSilence'])) r.append(twilio.Record( action=reverse('getRecording'), maxLength=request.session['ivr_makeRecording_maxLength'], timeout=request.session['ivr_makeRecording_timeout'], finishOnKey=request.session['ivr_makeRecording_finishOnKey'], transcribe=request.session['ivr_makeRecording_transcribe'], playBeep=request.session['ivr_makeRecording_playBeep'], )) r.append(twilio.Redirect(reverse('getRecording'))) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE)
def ProviderIVR_ForwardCall_New(request, provider=None, twilioResponse=None): """ new version of ProviderIVR_ForwardCall - forward call to dialed user as per user preference called by ProviderIVR_Main_New Steps: 1. get name 2. Dial - based on provider.forward_voicemail state to Mobile, office, other (VM already handled) 3. After dialed: handle failure by going to LeaveMsg or hangup? """ assert (request.session['provider_id']) provider = Provider.objects.get(id=request.session['provider_id']) logger.debug( '%s: ProviderIVR_ForwardCall_New is initiated provider %s state %s substate %s POST %s' % (request.session.session_key, provider, request.session.get('ivr2_state', None), request.session.get('ivr2_sub_state', None), str(request.POST))) callEnded = _checkCallbackDuration(request, False) # check user forwarding preference forward = provider.forward_voicemail if (forward == 'VM'): # go to voicemail request.session['ivr2_state'] = 'ProviderIVR_LeaveMsg_New' logger.debug( '%s: ProviderIVR_ForwardCall_New forwarding to voicemail of %s' % (request.session.session_key, provider)) return ProviderIVR_LeaveMsg_New(request) # State processing - 1. get caller name or ask for it r = twilioResponse or twilio.Response() if ('ivr2_sub_state' not in request.session): request.session['ivr2_sub_state'] = 'ProviderIVR_ForwardCall_Start' else: logger.debug( '%s: ProviderIVR_ForwardCall_New sub_state %s' % (request.session.session_key, request.session['ivr2_sub_state'])) if (request.session['ivr2_sub_state'] == 'ProviderIVR_ForwardCall_Start'): request.session['ivr2_sub_state'] = 'ProviderIVR_ForwardCall_GetName' # is this a doctorcom user with recorded name? callSID = request.POST['CallSid'] log = callLog.objects.get(callSID=callSID) if (log.mdcom_caller and isinstance(log.mdcom_caller, Provider)): if (log.mdcom_caller.vm_config.count()): prov_vmconfig = log.mdcom_caller.vm_config.get() if (prov_vmconfig.config_complete): logger.debug('%s/%s: Found the caller\'s name!' % ( request.session.session_key, request.session['ivr2_state'], )) log.caller_spoken_name = prov_vmconfig.name log.save() # got the recorded name; just go back to the next step - Dial return ProviderIVR_ForwardCall_New(request, provider, r) # next step else: logger.debug( '%s/%s: ProviderIVR_ForwardCall_New GetName: Caller\'s ' 'vm_config incomplete!' % (request.session.session_key, request.session['ivr2_state'])) else: logger.debug( '%s/%s: ProviderIVR_ForwardCall_New GetName: unsuitable ' 'number of vm_config objects found: %i' % (request.session.session_key, request.session['ivr2_state'], log.mdcom_caller.vm_config.count())) else: logger.debug( '%s/%s: ProviderIVR_ForwardCall_New GetName: mdcom_caller %s ' 'either isn\'t defined or doesn\'t seem to be a Provider' % (request.session.session_key, request.session['ivr2_state'], str(log.mdcom_caller))) # Not a user with a name recording. Get one. # ivr2_state already set to ProviderIVR_ForwardCall_GetName request.session[ 'ivr2_Record_prompt_str'] = 'Please say your name after the tone.' request.session['ivr2_Record_maxLength'] = 4 request.session['ivr2_Record_timeout'] = 2 request.session['ivr2_Record_leadSilence'] = 1 return getQuickRecordingNew(request) elif (request.session['ivr2_sub_state'] == 'ProviderIVR_ForwardCall_GetName'): request.session['ivr2_sub_state'] = 'ProviderIVR_ForwardCall_Dial' # save the caller name callSID = request.POST['CallSid'] log = callLog.objects.get(callSID=callSID) if (not log.caller_spoken_name): log.caller_spoken_name = request.session['ivr2_Record_recording'] del request.session['ivr2_Record_recording'] log.save() # Okay, let's find number to dial! user_number = None if (forward == 'MO'): user_number = provider.user.mobile_phone elif (forward == 'OF'): user_number = provider.office_phone elif (forward == 'OT'): user_number = provider.user.phone logger.debug( '%s/%s: ProviderIVR_ForwardCall_New Dial user number is \'%s\' forward %s' % (request.session.session_key, request.session['ivr2_state'], user_number, forward)) if (not user_number): # no flags were set. if (provider.user.mobile_phone): user_number = provider.user.mobile_phone else: return ProviderIVR_LeaveMsg_New(request, r) # when dial action is done, we go back to its actionurl - which is here with state Dial dial = twilio.Dial( action=reverse('ProviderIVR_ForwardCall_New'), timeout=22, timeLimit=14400, # 4 hours callerId=_makeUSNumber(request.session['Caller'])) # we also want to allow call vetting dial.append( twilio.Number(user_number, url=reverse('ProviderIVR_ForwardCall_Vet'))) r.append(dial) # If the call did not connect, we go to LeaveMsg r.append(twilio.Redirect(reverse('ProviderIVR_LeaveMsg_New'))) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) elif (request.session['ivr2_sub_state'] == 'ProviderIVR_ForwardCall_Dial'): # done with forward call del request.session['ivr2_sub_state'] # need to get parent call log for caller and connected; also update child log for duration (log, plog) = _getCallLogOrParent(request) if log: logger.debug( '%s/%s: ProviderIVR_ForwardCall_New state connected %s' % (request.session.session_key, request.session['ivr2_state'], str(log.call_connected))) else: logger.debug( '%s/%s: ProviderIVR_ForwardCall_New state no log SID %s' % (request.session.session_key, request.session['ivr2_state'], request.POST['CallSid'])) if ('DialCallStatus' in request.POST): if (request.POST['DialCallStatus'] == 'completed'): # update child log call duration diallog = callLog.objects.get( callSID=request.POST['DialCallSid']) if diallog: diallog.call_duration = request.POST['DialCallDuration'] diallog.save() logger.debug( '%s: ProviderIVR_ForwardCall_New update child diallog ' 'dialSid %s duration %s' % (request.session.session_key, request.POST['DialCallSid'], request.POST['DialCallDuration'])) else: logger.debug( '%s: ProviderIVR_ForwardCall_New diallog not found: dialSid %s duration %s' % (request.session.session_key, request.POST['DialCallSid'], request.POST['DialCallDuration'])) # Do nothing so that the second leg call continues un-interrupted return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) else: # (request.POST['DialCallStatus'] != 'completed'): logger.debug( '%s/%s: ProviderIVR_ForwardCall_New DialStatus not answered' % (request.session.session_key, request.session['ivr2_state'])) if (request.POST['DialCallStatus'] == 'failed'): # TODO: Figure out how to deal with connection problems. Most # likely, send an email to the user and administrators. logger.debug( '%s/%s: ProviderIVR_ForwardCall_New DialStatus failed' % (request.session.session_key, request.session['ivr2_state'])) subject = 'ProviderIVR_ForwardCall Call Forward DialStatus Fail' message = 'ProviderIVR_ForwardCall got DialStatus failed. Post data: %s' \ % (str(request.POST),) mail_admins(subject=subject, message=message, fail_silently=False) # else request.POST['DialStatus'] == 'busy' or request.POST['DialStatus'] == 'no-answer' return ProviderIVR_LeaveMsg_New(request, r) # if we connected (in Vet), we hang up here if (log.call_connected): r.append(twilio.Hangup()) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) # if not connected, we go to LeaveMsg return ProviderIVR_LeaveMsg_New(request, r)
def ProviderIVR_Setup_New(request, provider=None): """ New version of ProviderIVR_Setup processing. This is done in 4 consecutive steps: 0. initial sub state: ProviderIVR_Setup_Start 1. setup pin 2. setup Name 3. setup Greeting We use generic calls to setup Pin, Name and Greeting, but use ivr2_state to direct the return calls here so it could be redirected to the next step """ # we always need provider assert (request.session['provider_id']) assert (request.session['ivr2_state'] == 'ProviderIVR_Setup_New') if (provider == None): provider = Provider.objects.get(id=request.session['provider_id']) # we also need VMBox_config's config_id if (not 'config_id' in request.session): config = _getProviderVMConfig(provider) request.session['config_id'] = config.id logger.debug('%s: ProviderIVR_Setup_New state %s provider %s config %s' % (request.session.session_key, request.session['ivr2_state'], provider, request.session['config_id'])) if ('ivr2_sub_state' not in request.session): # new setup processing request.session['ivr2_sub_state'] = 'ProviderIVR_Setup_Start' else: logger.debug( '%s: ProviderIVR_Setup_New sub_state %s' % (request.session.session_key, request.session['ivr2_sub_state'])) if (request.session['ivr2_sub_state'] == 'ProviderIVR_Setup_Start'): # set up pin r = twilio.Response() r.append(twilio.Pause( )) # one second pause keeps the first words from getting cut off. request.session['ivr2_prompt_str'] = "Welcome to your voicemail account. It "\ "looks like some setup is needed. Let's get started. First, we need to "\ "set up your pin number." event = callEvent(callSID=request.POST['CallSid'], event='I_STR') event.save() request.session['ivr2_sub_state'] = 'ProviderIVR_Setup_Pin' return changePinNew(request, r) elif (request.session['ivr2_sub_state'] == 'ProviderIVR_Setup_Pin'): request.session['ivr2_sub_state'] = 'ProviderIVR_Setup_Name' return changeNameNew(request, 'Now, we need to record your name.') elif (request.session['ivr2_sub_state'] == 'ProviderIVR_Setup_Name'): request.session['ivr2_sub_state'] = 'ProviderIVR_Setup_Greeting' return changeGreetingNew(request, 'Finally, we need to set up a greeting.') elif (request.session['ivr2_sub_state'] == 'ProviderIVR_Setup_Greeting'): # setup is complete - automatically "log" user in request.session['authenticated'] = True del request.session['ivr2_sub_state'] request.session['ivr2_state'] = 'ProviderIVR_TreeRoot_New' config = VMBox_Config.objects.get(id=request.session['config_id']) config.config_complete = True config.save() event = callEvent(callSID=request.POST['CallSid'], event='I_FIN') event.save() logger.debug('%s: ProviderIVR_Setup is complete config %s' % (request.session.session_key, config)) # we don't need the welcome msg anymore if ('ivr2_prompt_str' in request.session): del request.session['ivr2_prompt_str'] r = twilio.Response() r.append( tts('Your voice mail account is now set up. You may hang up ' 'now, or stay on the line to be taken to your voice mail box home.' )) # after VM Setup, we go to main r.append(twilio.Redirect(reverse('ProviderIVR_TreeRoot_New'))) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) else: # should not get here with unknown state - log state and return to main logger.debug( '%s: ProviderIVR_Setup has unhandled state set to %s' % (request.session.session_key, request.session['ivr2_state'])) request.session['ivr2_state'] = 'ProviderIVR_Main_New' return ProviderIVR_Main_New(request)
def PracticeIVR_Setup_New(request): """ This function is heavily dependent upon request.session; Twilio is kind enough to keep session cookies for us. sets up doctor com answering service practice open/closed greetings and pin """ assert(request.session['practice_id']) assert(request.session['ivr2_state'] == 'PracticeIVR_Setup_New') _checkCallbackDuration(request) logger.debug('%s: PracticeIVR_Setup_New POST data is %s' % ( request.session.session_key, str(request.POST))) logger.debug('%s: PracticeIVR_Setup_New state %s practice %s' % ( request.session.session_key, request.session['ivr2_state'], request.session['practice_id'])) # TODO - check if we need to create event for this if ('ivr2_sub_state' not in request.session): request.session['ivr2_sub_state'] = 'PracticeIVR_Setup_Start' else: logger.debug('%s: PracticeIVR_Setup_New sub_state %s' % ( request.session.session_key, request.session['ivr2_sub_state'])) if (request.session['ivr2_sub_state'] == 'PracticeIVR_Setup_Start'): # Okay, this is the first time this function is being executed for this call. request.session['ivr2_sub_state'] = 'PracticeIVR_Setup_1' #will need to Practice Location and see if this needs set up and values that are there already r = twilio.Response() r.append(twilio.Pause()) # one second pause keeps the first words from getting cut off. request.session['ivr2_prompt_str'] = "Welcome to your voicemail account. It looks like some setup is needed. \ Let's get started. First, we need to set up your pin number." return changePinNew(request, r) elif (request.session['ivr2_sub_state'] == 'PracticeIVR_Setup_1'): # Record name request.session['ivr2_sub_state'] = 'PracticeIVR_Setup_2' return changeNameNew(request, _('Now, we need to record your office name.')) elif (request.session['ivr2_sub_state'] == 'PracticeIVR_Setup_2'): # Record a greeting for closed office request.session['ivr2_sub_state'] = 'PracticeIVR_Setup_3' # request.session['ivr2_setup_stage'] = 3 # deprecated return changeGreetingNew(request, _('Next, we need to set up your answering service ' 'greeting. This will be played when the office is closed.')) elif (request.session['ivr2_sub_state'] == 'PracticeIVR_Setup_3'): # Record a greeting for open request.session['ivr2_sub_state'] = 'PracticeIVR_Setup_4' # request.session['ivr2_setup_stage'] = 4 # deprecated return changeGreetingNew(request, _('Finally, we need to set up a greeting that ' 'will be played when the office is open.')) elif (request.session['ivr2_sub_state'] == 'PracticeIVR_Setup_4'): # Configuration complete! #store new information in Practice Locations del request.session['ivr2_sub_state'] request.session['ivr2_state'] = 'PracticeIVR_TreeRoot_New' practice = PracticeLocation.objects.get(id=request.session['practice_id']) practice.config_complete = True practice.save() # we don't need the welcome msg anymore if ('ivr2_prompt_str' in request.session): del request.session['ivr2_prompt_str'] r = twilio.Response() r.append(tts(_('Your voice mail account is now set up. You may hang up now.'))) r.append(twilio.Redirect(reverse('PracticeIVR_TreeRoot_New'))) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) else: # should not get here with unknown state - log state and return to main; or throw exception? logger.debug('%s: PracticeIVR_Setup_New has unhandled state set to %s' % ( request.session.session_key, request.session['ivr2_state'])) request.session['ivr2_state'] = 'PracticeIVR_Main_New' return PracticeIVR_Main_New(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)
def ProviderIVR_Setup(request, config=None): """ This function is heavily dependent upon request.session; Twilio is kind enough to keep session cookies for us. """ # DEBUG: #if (not 'ProviderIVR_Setup' in request.session['callCounts']): # request.session['callCounts']['ProviderIVR_Setup'] = 1 #else: # request.session['callCounts']['ProviderIVR_Setup'] += 1 # DEBUG: #if (not 'debug_semaphore' in request.session): # request.session['ivr_setup_stage'] = 1 # request.session['debug_semaphore'] = True #else: # raise Exception(request.session['ivr_call_stack']) if ('CallStatus' in request.POST and request.POST['CallStatus'] == 'completed'): # call ended #raise Exception('Ending inappropriately. Call stack is %s'%(str( # request.session['ivr_call_stack']),)) # DEBUG r = twilio.Response() return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) elif (not 'CallStatus' in request.POST): # call ended #raise Exception('Ending inappropriately. Call stack is %s'%(str( # request.session['ivr_call_stack']),)) # DEBUG r = twilio.Response() return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) if 'ivr_setup_stage' not in request.session: # Okay, this is the first time this function is being executed for this # call. #raise Exception(request.session['ivr_call_stack']) # DEBUG r = twilio.Response() # Set up our session variables. request.session['ivr_setup_stage'] = 1 request.session['ivr_call_stack'].append('ProviderIVR_Setup') request.session.modified = True provider = Provider.objects.get(id=request.session['provider_id']) if (not provider.vm_config.count()): # This user needs a voicemailbox configuration object config = VMBox_Config() config.owner = provider config.save() request.session['config_id'] = config.id r.append(twilio.Pause( )) # one second pause keeps the first words from getting cut off. r.append( tts("Welcome to your voicemail account. It looks like some " "setup is needed. Let's get started.")) r.append(tts("First, we need to set up your pin number.")) event = callEvent(callSID=request.POST['CallSid'], event='I_STR') event.save() #raise Exception(request.session['ivr_call_stack']) # DEBUG return changePin(request, r, True) elif (request.session['ivr_setup_stage'] == 1): # Record name request.session['ivr_call_stack'].append('ProviderIVR_Setup') request.session.modified = True request.session['ivr_setup_stage'] = 2 return changeName(request, 'Now, we need to record your name.') elif (request.session['ivr_setup_stage'] == 2): # Record a greeting request.session['ivr_call_stack'].append('ProviderIVR_Setup') request.session.modified = True request.session['ivr_setup_stage'] = 3 return changeGreeting(request, 'Finally, we need to set up a greeting.') elif (request.session['ivr_setup_stage'] == 3): # Configuration complete! #raise Exception(request.session['ivr_call_stack']) # DEBUG #raise Exception(request.session['callCounts']) # DEBUG # Automatically "log" this user in. request.session['authenticated'] = True config = VMBox_Config.objects.get(id=request.session['config_id']) config.config_complete = True config.save() r = twilio.Response() r.append( tts('Your voice mail account is now set up. You may hang up ' 'now, or stay on the line to be taken to your voice mail box home.' )) event = callEvent(callSID=request.POST['CallSid'], event='I_FIN') event.save() r.append( twilio.Redirect(reverse(request.session['ivr_call_stack'].pop()))) request.session.modified = True return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) raise Exception( 'Reached the end of ProviderIVR_Setup. This should never happen.')
def ProviderIVR_ForwardCall(request): """Forward the call to the dialed user, as per the user's preferences. Uses the following session variables: ProviderIVR_ForwardCall_state: The most recent "state" of execution. May have the following values: - None/Undefined/Empty String: First execution of this function. - Getting_Name: Getting the caller's name, if one hasn't been defined. - Dialing: Phone(s) have been dialed, and waiting for a response Caller """ r = twilio.Response() request.session.modified = True provider = Provider.objects.get(id=request.session['provider_id']) if ('CallStatus' in request.POST and request.POST['CallStatus'] == 'completed'): if ('Duration' in request.POST): callSID = request.POST['CallSid'] log = callLog.objects.get(callSID=callSID) log.call_duration = request.POST['Duration'] log.save() if (not 'ProviderIVR_ForwardCall_forward' in request.session): request.session[ 'ProviderIVR_ForwardCall_forward'] = provider.forward_voicemail forward = provider.forward_voicemail if (forward == 'VM'): return ProviderIVR_LeaveMsg(request) if (not 'ProviderIVR_ForwardCall_state' in request.session or not request.session['ProviderIVR_ForwardCall_state']): # New call. First, check to see if we should go straight to voicemail # Okay, the call isn't going to voicemail directly. Now, set state. request.session['ProviderIVR_ForwardCall_state'] = 'Getting_Name' # Now, get the caller's name # Is the user a DoctorCom user with a recorded name? callSID = request.POST['CallSid'] log = callLog.objects.get(callSID=callSID) if (log.mdcom_caller and isinstance(log.mdcom_caller, Provider)): if (log.mdcom_caller.vm_config.count()): prov_vmconfig = log.mdcom_caller.vm_config.get() if (prov_vmconfig.config_complete): logger.debug('%s/%s: Found the caller\'s name!' % ( request.session.session_key, request.session['ProviderIVR_ForwardCall_state'], )) log.caller_spoken_name = prov_vmconfig.name log.save() return ProviderIVR_ForwardCall( request) # restart execution of this function else: logger.debug('%s/%s: Caller\'s vm_config incomplete!' % ( request.session.session_key, request.session['ProviderIVR_ForwardCall_state'], )) else: logger.debug( '%s/%s: An unsuitable number of vm_config objects found: %i' % ( request.session.session_key, request.session['ProviderIVR_ForwardCall_state'], log.mdcom_caller.vm_config.count(), )) else: logger.debug( '%s/%s: mdcom_caller %s either isn\'t defined or doesn\'t ' 'seem to be a Provider' % ( request.session.session_key, request.session['ProviderIVR_ForwardCall_state'], str(log.mdcom_caller), )) # Okay, it's not a user with a name recording. Get one. request.session['ivr_call_stack'].append('ProviderIVR_ForwardCall') request.session['ivr_makeRecording_prompt'] = \ tts('Please say your name after the tone.') request.session['ivr_makeRecording_maxLength'] = 4 request.session['ivr_makeRecording_timeout'] = 2 request.session['ivr_makeRecording_leadSilence'] = 1 return getQuickRecording(request) if (request.session['ProviderIVR_ForwardCall_state'] == 'Getting_Name'): request.session['ProviderIVR_ForwardCall_state'] = 'Dialed' logger.debug('%s/%s: Set session to %s' % ( request.session.session_key, request.session['ProviderIVR_ForwardCall_state'], request.session['ProviderIVR_ForwardCall_state'], )) callSID = request.POST['CallSid'] log = callLog.objects.get(callSID=callSID) if (not log.caller_spoken_name): log.caller_spoken_name = request.session.pop( 'ivr_makeRecording_recording') log.save() logger.debug('%s/%s: got provider \'%s\' \'%s\' with id %s' % ( request.session.session_key, request.session['ProviderIVR_ForwardCall_state'], provider.first_name, provider.last_name, provider.pk, )) logger.debug( '%s/%s: Provider phone is \'%s\' and forward_other is \'%s\'' % ( request.session.session_key, request.session['ProviderIVR_ForwardCall_state'], provider.user.phone, str(provider.forward_other), )) # Okay, let's dial! user_number = None if (forward == 'MO'): logger.debug('%s/%s: provider.forward_mobile True' % ( request.session.session_key, request.session['ProviderIVR_ForwardCall_state'], )) user_number = provider.user.mobile_phone logger.debug('%s/%s: Setting user_number to \'%s\'' % ( request.session.session_key, request.session['ProviderIVR_ForwardCall_state'], provider.user.mobile_phone, )) elif (forward == 'OF'): logger.debug('%s/%s: provider.forward_office True' % ( request.session.session_key, request.session['ProviderIVR_ForwardCall_state'], )) user_number = provider.office_phone logger.debug('%s/%s: Setting user_number to \'%s\'' % ( request.session.session_key, request.session['ProviderIVR_ForwardCall_state'], provider.office_phone, )) elif (forward == 'OT'): logger.debug('%s/%s: provider.forward_other True' % ( request.session.session_key, request.session['ProviderIVR_ForwardCall_state'], )) user_number = provider.user.phone logger.debug('%s/%s: Setting user_number to \'%s\'' % ( request.session.session_key, request.session['ProviderIVR_ForwardCall_state'], provider.user.phone, )) logger.debug('%s/%s: Tried to get called\'s number. Got \'%s\'' % ( request.session.session_key, request.session['ProviderIVR_ForwardCall_state'], user_number, )) logger.debug( '%s/%s: Provider phone is \'%s\' and forward_other is \'%s\'' % ( request.session.session_key, request.session['ProviderIVR_ForwardCall_state'], provider.user.phone, str(provider.forward_other), )) if (not user_number): # no flags were set. if (provider.user.mobile_phone): user_number = provider.user.mobile_phone else: return ProviderIVR_LeaveMsg(request) dial = twilio.Dial( action=reverse('ProviderIVR_ForwardCall'), timeout=22, timeLimit=14400, # 4 hours callerId=request.session['Caller']) dial.append( twilio.Number(user_number, url=reverse('ProviderIVR_ForwardCall_VetAnswer'))) r.append(dial) r.append(twilio.Redirect(reverse('ProviderIVR_LeaveMsg'))) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) if (request.session['ProviderIVR_ForwardCall_state'] == 'Dialed'): callSID = request.POST['CallSid'] log = callLog.objects.get(callSID=callSID) if (log.call_connected): r.append(twilio.Hangup()) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) return ProviderIVR_LeaveMsg(request) r = twilio.Response() if (request.POST['DialStatus'] != 'answered'): if (request.POST['DialStatus'] == 'failed'): # TODO: Figure out how to deal with connection problems. Most # likely, send an email to the user and administrators. subject = 'ProviderIVR_ForwardCall Call Forward DialStatus Fail' message = 'ProviderIVR_ForwardCall got DialStatus failed. Post data: %s' % \ (str(request.POST),) mail_admins(subject=subject, message=message, fail_silently=False) # else request.POST['DialStatus'] == 'busy' or request.POST['DialStatus'] == 'no-answer' return ProviderIVR_LeaveMsg(request) # else: Do nothing so that the call continues un-interrupted return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE)
def authenticateSession(request, twilioResponse=None): """ :param request: The standard Django request argument :param request.session Keys: config_id - The ID of the VMBox_Config object pertaining to the current voicemail session. :param twilioResponse: A twilio response object. Use this to pass in any verbs that should be run before the prompt. Note that any verbs passed in will be lost on subsequent runs through this function (e.g., when the user enters an incorrect pin) :returns: django.http.HttpResponse -- the result """ r = twilioResponse or twilio.Response() if (not 'pin_errCount' in request.session): request.session['pin_errCount'] = 0 if 'Digits' in request.POST: call_sid = request.POST['CallSid'] digits = request.POST['Digits'] p = re.compile('\d{4,8}#?$') if (p.match(digits)): if ('answering_service' in request.session and request.session['answering_service'] == 'yes'): practice = PracticeLocation.objects.get(id=request.session['practice_id']) if (practice.verify_pin(digits)): request.session['authenticated'] = True r.append(twilio.Redirect(reverse(request.session['ivr_call_stack'].pop()))) request.session.modified = True return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) else: user = authenticate(config_id=request.session['config_id'], pin=digits) if (user): login(request, user) # TESTING_KMS_INTEGRATION uprivs = UserPrivateKey.objects.filter(user=user, credtype=CRED_IVRPIN, gfather=True) if uprivs.exists(): config = VMBox_Config.objects.get(id=request.session['config_id']) config.change_pin(request, new_pin=digits) request.session['authenticated'] = True event = callEvent(callSID=call_sid, event='V_ASU') event.save() r.append(twilio.Redirect(reverse(request.session['ivr_call_stack'].pop()))) request.session.modified = True response = HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) store_user_key(request, response, digits) return response event = callEvent(callSID=call_sid, event='V_AFL') event.save() r.append(tts('An in valid pin was entered.')) request.session['pin_errCount'] += 1 if (request.session['pin_errCount'] >= 3): # give the user three erroneous pin entries. r.append(tts('Good bye.')) r.append(twilio.Hangup()) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) # This is the code that gets executed on the first run of this function. gather = twilio.Gather(numDigits=8, action=reverse('authenticateSession')) gather.append(tts(_("Please enter your pin number. Press pound to finish."))) r.append(gather) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE)
def PracticeIVR_ForwardCall_New(request, twilioResponse=None): """ Forward the call to the dialed user, there are no preferences for office managers, just call their cell phone Done in 3 steps: 1. get caller name 2. forward call 3. if connected, done; if fail to connect, go to LeaveUrgentMsg_New """ provider = None forward = None try: provider = Provider.objects.get(id=request.session['provider_id']) if(not 'ProviderIVR_ForwardCall_forward' in request.session): request.session['ProviderIVR_ForwardCall_forward'] = provider.forward_anssvc forward = provider.forward_anssvc except Provider.DoesNotExist: pass logger.debug('%s: PracticeIVR_ForwardCall_New provider %s practice %s state %s substate %s' % ( request.session.session_key, provider, request.session.get('practice_id', None), request.session.get('ivr2_state', None), request.session.get('ivr2_sub_state', None))) callSID = request.POST['CallSid'] # TODO - what if we don't get the callLog? log = callLog.objects.get(callSID=callSID) log.call_source = 'AS' log.save() if('click2call' in request.session): forward = 'MO' # hack to keep click2call working if(forward == 'VM'): request.session['ivr2_state'] = 'PracticeIVR_LeaveUrgentMsg_New' logger.debug('%s: PracticeIVR_ForwardCall_New forward to VM - LeaveUrgentMsg_New to %s' % ( request.session.session_key, provider)) return PracticeIVR_LeaveUrgentMsg_New(request) r = twilioResponse or twilio.Response() if ('ivr2_sub_state' not in request.session): request.session['ivr2_sub_state'] = 'PracticeIVR_ForwardCall_Start' else: logger.debug('%s: PracticeIVR_ForwardCall_New sub_state %s' % ( request.session.session_key, request.session['ivr2_sub_state'])) # now we get caller name, dial and handle failure to connect by going to leave urgent message if (request.session['ivr2_sub_state'] == 'PracticeIVR_ForwardCall_Start'): request.session['ivr2_sub_state'] = 'PracticeIVR_ForwardCall_GetName' # Is the user a DoctorCom user with a recorded name? if (log.mdcom_caller and isinstance(log.mdcom_caller, Provider)): if (log.mdcom_caller.vm_config.count()): prov_vmconfig = log.mdcom_caller.vm_config.get() if (prov_vmconfig.config_complete): logger.debug('%s/%s sub %s: Found the caller\'s name! Forwarding call' % ( request.session.session_key, request.session['ivr2_state'], request.session['ivr2_sub_state'], )) log.caller_spoken_name = prov_vmconfig.name log.save() return PracticeIVR_ForwardCall_New(request, r) # restart execution of this function else: logger.debug('%s/%s sub %s: Caller\'s vm_config incomplete!' % ( request.session.session_key, request.session['ivr2_state'], request.session['ivr2_sub_state'], )) else: logger.debug('%s/%s sub %s: An unsuitable number of vm_config objects found: %i' % ( request.session.session_key, request.session['ivr2_state'], request.session['ivr2_sub_state'], log.mdcom_caller.vm_config.count(), )) else: logger.debug('%s/%s sub %s: mdcom_caller %s either isn\'t defined or doesn\'t seem to be a Provider' % ( request.session.session_key, request.session['ivr2_state'], request.session['ivr2_sub_state'], str(log.mdcom_caller), )) # Okay, it's not a user with a name recording. Get one. request.session['ivr2_Record_prompt_str'] = 'Please say your name after the tone.' request.session['ivr2_Record_maxLength'] = 4 request.session['ivr2_Record_timeout'] = 2 request.session['ivr2_Record_leadSilence'] = 1 return getQuickRecordingNew(request) elif (request.session['ivr2_sub_state'] == 'PracticeIVR_ForwardCall_GetName'): request.session['ivr2_sub_state'] = 'PracticeIVR_ForwardCall_Dial' # save caller name logger.debug('%s/%s: Set session to %s' % ( request.session.session_key, request.session['ivr2_state'], request.session['ivr2_sub_state'] )) if (not log.caller_spoken_name): log.caller_spoken_name = request.session['ivr2_Record_recording'] del request.session['ivr2_Record_recording'] log.save() # now find the number to dial user_number = '' try: office_staff = OfficeStaff.objects.get(user=request.session['provider_id']) # manager being called logger.debug('%s/%s: got office staff \'%s\' \'%s\' with id %s office phone \'%s\'.' % ( request.session.session_key, request.session['ivr2_state'], office_staff.user.first_name, office_staff.user.last_name, office_staff.pk, office_staff.user.mobile_phone, )) user_number = office_staff.user.mobile_phone except OfficeStaff.DoesNotExist: #it's a provider if(forward == 'MO'): user_number = provider.mobile_phone elif(forward == 'OF'): user_number = provider.office_phone elif(forward == 'OT'): user_number = provider.phone logger.debug('%s/%s: Setting user_number to \'%s\'' % ( request.session.session_key, request.session['ivr2_state'], user_number, )) logger.debug('%s/%s: Tried to get called\'s number. Got \'%s\'' % ( request.session.session_key, request.session['ivr2_state'], user_number, )) dial = twilio.Dial( action=reverse('PracticeIVR_ForwardCall_New'), timeout=22, timeLimit=14400, # 4 hours callerId=request.session['Caller'], ) dial.append(twilio.Number(user_number, url=reverse('PracticeIVR_ForwardCall_Vet') )) r.append(dial) r.append(twilio.Redirect(reverse('PracticeIVR_LeaveUrgentMsg_New'))) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) elif (request.session['ivr2_sub_state'] == 'PracticeIVR_ForwardCall_Dial'): del request.session['ivr2_sub_state'] (clog, plog) = _getCallLogOrParent(request) if clog: logger.debug('%s/%s: PracticeIVR_ForwardCall_New state connected %s' % ( request.session.session_key, request.session['ivr2_state'], str(clog.call_connected))) else: logger.debug('%s/%s: ProviderIVR_ForwardCall_New state no log SID %s' % ( request.session.session_key, request.session['ivr2_state'], request.POST['CallSid'])) if ('DialCallStatus' in request.POST): if (request.POST['DialCallStatus'] == 'completed'): # update child log call duration diallog = callLog.objects.get(callSID=request.POST['DialCallSid']) if diallog: diallog.call_duration = request.POST['DialCallDuration'] diallog.save() logger.debug('%s: PracticeIVR_ForwardCall_New update child diallog dialSid %s duration %s' % ( request.session.session_key, request.POST['DialCallSid'], request.POST['DialCallDuration'])) else: logger.debug('%s: PracticeIVR_ForwardCall_New diallog not found: dialSid %s duration %s' % ( request.session.session_key, request.POST['DialCallSid'], request.POST['DialCallDuration'])) # Do nothing so that the second leg call continues un-interrupted return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) if (clog.call_connected): r.append(twilio.Hangup()) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) r.append(tts("The provider is not available right now.")) r.append(twilio.Redirect(reverse('PracticeIVR_LeaveUrgentMsg_New'))) # redirecting to LeaveUrgentMsg_New request.session['ivr2_state'] = 'PracticeIVR_LeaveUrgentMsg_New' return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) else: # else: Do nothing so that the call continues un-interrupted return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE)
def testBadAppend(self): """ should raise exceptions for wrong appending """ self.improperAppend(twiml.Redirect())
def getCallBackNumber(request, twilioResponse=None): """ Gets call back number from users input, verifies number, sends it back to be used in msg or sms """ if 'CallStatus' in request.POST: logger.debug('%s: Into getCallBackNumber with call status %s' % ( request.session.session_key, request.POST['CallStatus'])) r = twilioResponse or twilio.Response() request.session.modified = True if ('CallStatus' in request.POST and request.POST['CallStatus'] == 'completed'): # First, check to see if the caller has hung up. if ('ivr_has_number' in request.session and 'ivr_callback_returnOnHangup' in request.session and 'ivr_makeRecording_callbacknumber' in request.session): #call caller function, just to send empty msg or sms request.session['ivr_only_callbacknumber'] = True view = request.session.get('ivr_callback_returnOnHangup', None) if view: try: # TODO: no more exec() but validation on view is needed mod, func = view.rsplit('.', 1) mod = import_module(mod) getattr(mod, func)(request) # call the view function except Exception as e: mail_admins("Problem calling view in getCallBackNumber", str(e)) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) # after hung up we need to clear first time < 10 digit numbers for urgent calls if ('ivr_urgent_second_time' in request.session): request.session.pop('ivr_makeRecording_callbacknumber', None) request.session.pop('ivr_caller_id_area_code', None) if 'Digits' in request.POST: digits = request.POST['Digits'] if ('ivr_makeRecording_callbacknumber' in request.session): p = re.compile('[0-9]$') if (not p.match(digits)): del request.session['ivr_makeRecording_callbacknumber'] del request.session['ivr_has_number'] request.session.pop('ivr_caller_id_area_code', None) r.append(tts('I\'m sorry, I didn\'t understand that.')) r.append(twilio.Redirect(reverse('getCallBackNumber'))) elif (digits == '1'): # correct number - leave function, and get voice recordng r.append(twilio.Redirect(reverse(request.session['ivr_call_stack'].pop()))) request.session.modified = True #r.append(twilio.Redirect(reverse('getCallBackNumber'))) elif (digits == '3'): #user said, bad number, reinit and enter number again del request.session['ivr_makeRecording_callbacknumber'] del request.session['ivr_has_number'] request.session.pop('ivr_caller_id_area_code', None) r.append(twilio.Redirect(reverse('getCallBackNumber'))) else: r.append(tts('I\'m sorry, I didn\'t understand that.')) gather = twilio.Gather(finishOnKey='', numDigits=1, action=reverse('getCallBackNumber')) spoken_number = [] [spoken_number.extend([i, ' ']) for i in request.session['ivr_makeRecording_callbacknumber']] spoken_number.pop() # drop the last element gather.append(tts(_('Eye got %s. If this is correct, press one. Or' 'press three to enter eh different number') % (''.join(spoken_number),))) r.append(gather) #r.append(twilio.Redirect(reverse('getCallBackNumber'))) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) if ('ivr_has_number' in request.session): #first time thru phone was entered ivr_makeRecording_callbacknumber does # not have phone number in it yet. if (not 'ivr_makeRecording_callbacknumber' in request.session or 'ivr_urgent_second_time' in request.session): if(re.match(r'[0-9]+', digits)): spoken_number = [] [spoken_number.extend([i, ' ']) for i in digits] spoken_number.pop() # drop the last element #spoken_number.insert(5, ',') #spoken_number.insert(12, ',') request.session['ivr_makeRecording_callbacknumber'] = digits #take first three digits from caller, in case less than 10 digits are # entered, we do this for ALL calls where call back number is < 10 digits if (len(digits) < 10 and 'Caller' in request.session and len(request.session['Caller']) > 2): request.session['ivr_caller_id_area_code'] = request.session['Caller'][0:3] # for bug 829, ONLY on FIRST pass, we need to make sure its at least # 10 digits, if not say please make sure you entered area code # only if this is URGENT call, rest of callers are free to leave any # number of digits also, if after first try, users still enters < 10 # digits, let it go thru (ivr_urgent_second_time var is used for that) view = request.session.get('ivr_callback_returnOnHangup', None) if (not 'ivr_urgent_second_time' in request.session and len(digits) < 10 and view and view.split('.')[-1] == 'PracticeIVR_LeaveUrgentMsg'): gather = twilio.Gather(finishOnKey='#', numDigits=12, timeout=30, action=reverse('getCallBackNumber')) gather.append(tts('I\'m sorry, It appears your call back number ' 'is less than ten digits. Please enter your call back ' 'number including area code now. Then press pound.')) r.append(gather) r.append(twilio.Redirect(reverse('getCallBackNumber'))) request.session['ivr_urgent_second_time'] = True return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) #========= end of bug 829 ======================= else: gather = twilio.Gather(finishOnKey='', numDigits=1, action=reverse('getCallBackNumber')) gather.append(tts('Eye got %s . If this is correct, press one. ' 'Or press three to enter eh different number' % \ (''.join(spoken_number),))) r.append(gather) r.append(twilio.Redirect(reverse('getCallBackNumber'))) request.session.pop('ivr_urgent_second_time', None) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) else: r.append(tts(_('I\'m sorry, I didn\'t understand that.'))) r.append(twilio.Redirect(reverse('getCallBackNumber'))) request.session.pop('ivr_has_number', None) request.session.pop('ivr_makeRecording_callbacknumber', None) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) if (not 'ivr_has_number' in request.session): # This is the code that gets executed on the first run of this function. #'digits' get posted for next itteration # It also gets run if the call back number verification fails gather = twilio.Gather(finishOnKey='#', numDigits=12, timeout=30, action=reverse('getCallBackNumber')) gather.append(tts(_('On the keypad, please enter your call back number ' 'including area code now, then press pound.'))) r.append(gather) r.append(twilio.Redirect(reverse('getCallBackNumber'))) request.session['ivr_has_number'] = True return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) #this is the case of user pressing just pound at call back number, there are no digits. if ('ivr_has_number' in request.session and 'Digits' not in request.POST): del request.session['ivr_has_number'] request.session.pop('ivr_makeRecording_callbacknumber', None) r.append(tts(_('I\'m sorry, I didn\'t understand that.'))) r.append(twilio.Redirect(reverse('getCallBackNumber'))) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) raise Exception(_('should never get here'))
def changePin(request, twilioResponse=None, internalCall=False): """This function gets called three times per successful PIN change. The first time, it requests the user's pin. The second time, it requests confirmation of the pin. The last time, it finally saves the pin, then :returns: to the function specified at request.session['ivr_call_stack'][-1] """ r = twilioResponse or twilio.Response() if (not internalCall and 'Digits' in request.POST): digits = request.POST['Digits'] if (not 'ivr_changePin_hash' in request.session): # This is the first time the PIN has been entered. p = re.compile('\d{4,8}#?$') if (not p.match(digits)): r.append(tts(_("An in valid pin was entered."))) else: request.session['ivr_changePin_hash'] = get_new_pin_hash(digits) gather = twilio.Gather(numDigits=8, action=reverse('changePin')) gather.append(tts(_('To verify that we have the correct pin, ' 'please enter it again. Press pound to finish.'))) r.append(gather) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) else: # The PIN has been entered once. Time to verify it. p = re.compile('\d{4,8}#?$') if (p.match(digits)): if (check_pin(digits, request.session['ivr_changePin_hash'])): r.append(twilio.Redirect(reverse(request.session['ivr_call_stack'].pop()))) response = HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) if ('answering_service' in request.session and request.session['answering_service'] == 'yes'): practice = PracticeLocation.objects.get(id=request.session['practice_id']) practice.pin = request.session['ivr_changePin_hash'] practice.save() else: config = VMBox_Config.objects.get(id=request.session['config_id']) # Note: request.user is anon for twilio sessions, issue 1362 # get_user_key assumes cookie has 'ss' and ss def arg None by def old_key = get_user_key(request) if 'ss' in request.COOKIES else None config.change_pin(request, old_key=old_key, new_pin=digits) config.pin = request.session['ivr_changePin_hash'] config.save() del request.session['ivr_changePin_hash'] event = callEvent(callSID=request.POST['CallSid'], event='F_PCH') event.save() request.session.modified = True return response r.append(tts(_('The entered pins do not match.'))) del request.session['ivr_changePin_hash'] if (not 'ivr_changePin_hash' in request.session): # This is the code that gets executed on the first run of this function. # It also gets run if the PIN verification fails. gather = twilio.Gather(numDigits=8, action=reverse('changePin')) gather.append(tts(_("Please enter four to eight digits. Press pound to finish."))) r.append(gather) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE)