示例#1
0
 def testRecordActionMethod(self):
     """should record with an action and a get method"""
     r = Response()
     r.append(twiml.Record(action="example.com", method="GET"))
     r = self.strip(r)
     self.assertEquals(
         r,
         '<?xml version="1.0" encoding="UTF-8"?><Response><Record action="example.com" method="GET" /></Response>'
     )
示例#2
0
 def testRecordEmpty(self):
     """should record"""
     r = Response()
     r.append(twiml.Record())
     r = self.strip(r)
     self.assertEquals(
         r,
         '<?xml version="1.0" encoding="UTF-8"?><Response><Record /></Response>'
     )
示例#3
0
 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(""))
示例#4
0
 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())
示例#5
0
文件: views.py 项目: cnzhuran/mdcom
def Twilio_record(request):
	import cPickle

	# Save debugging data
	sid = request.POST['CallSid']
	status = request.POST['CallStatus']

	log = TwilioRecordTest.objects.get(callid=sid)

	if (not log.debug_data):
		debugData = []
	else:
		debugData = cPickle.loads(log.debug_data.encode('ascii'))
	newEntry = ['Twilio_record', cPickle.dumps(request.POST)]
	debugData.append(newEntry)
	log.debug_data = cPickle.dumps(debugData)

	log.save()

	# We don't care about which session this is associated with as all
	# verification is the same across all sessions.
	r = twilio.Response()
	say = twilio.Say("After the tone, please press 1, 2, and 3, then pound to finish.", 
			voice=twilio.Say.MAN, language=twilio.Say.ENGLISH)
	r.append(say)

	abs_uri = '://'.join([settings.SERVER_PROTOCOL, settings.SERVER_ADDRESS])
	url = reverse('MHLogin.tests.views.Twilio_record_complete')

	record = twilio.Record(
				action=urljoin(abs_uri, url),
				transcribe=False,
				finishOnKey='#',
				playBeep='true',
				timeout=30,
				)
	r.append(record)

	debugData.append(str(r))
	log.debug_data = cPickle.dumps(debugData)
	log.save()

	return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE)
示例#6
0
 def testRecordBadAppend(self):
     """ should raise exceptions for wrong appending """
     self.improperAppend(twiml.Record())
示例#7
0
 def testRecordAddAttribute(self):
     """ add attribute """
     r = twiml.Record(foo="bar")
     r = self.strip(r)
     assert_equal(r, '<?xml version="1.0" encoding="UTF-8"?><Record foo="bar" />')
示例#8
0
 def testRecordTranscribeCallback(self):
     """ should record with a transcribe and transcribeCallback """
     r = Response()
     r.append(twiml.Record(transcribeCallback="example.com"))
     r = self.strip(r)
     assert_equal(r, '<?xml version="1.0" encoding="UTF-8"?><Response><Record transcribeCallback="example.com" /></Response>')
示例#9
0
 def testRecordMaxlengthFinishTimeout(self):
     """ should record with an maxlength, finishonkey, and timeout """
     r = Response()
     r.append(twiml.Record(timeout=4, finishOnKey="#", maxLength=30))
     r = self.strip(r)
     assert_equal(r, '<?xml version="1.0" encoding="UTF-8"?><Response><Record finishOnKey="#" maxLength="30" timeout="4" /></Response>')
示例#10
0
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)
示例#11
0
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)