def get_first_ivr_response_data(recipient, call_log_entry, logged_subevent): """ As long as the form has at least one question in it (i.e., it doesn't consist of all labels), then we can start the touchforms session now and cache the first IVR response, so that all we need to do later is serve it up. This makes for less time ringing when the user is on the phone, waiting for the line to pick up. If the form consists of all labels, we don't do anything here, because then we would end up submitting the form right away regardless of whether the user actually got the call. Returns (ivr_data, error) where ivr_data is an instance of IVRResponseData """ app, module, form, error = get_app_module_form(call_log_entry, logged_subevent) if error: return (None, True) if form_requires_input(form): session, responses, error = start_call_session(recipient, call_log_entry, logged_subevent, app, module, form) if error: return (None, True) ivr_responses = [] for response in responses: ivr_responses.append(format_ivr_response(response.event.caption, app)) ivr_data = IVRResponseData(ivr_responses, get_input_length(responses[-1]), session) return (ivr_data, False) return (None, False)
def get_memoized_app_module_form(self, domain): try: app = get_app(domain, self.app_id) form = app.get_form(self.form_unique_id) module = form.get_module() except (Http404, FormNotFoundException): return None, None, None, None return app, module, form, form_requires_input(form)
def get_memoized_app_module_form(self, domain): try: form = Form.get_form(self.form_unique_id) app = form.get_app() module = form.get_module() except (ResourceNotFound, XFormIdNotUnique): return None, None, None, None if app.domain != domain: return None, None, None, None return app, module, form, form_requires_input(form)
def get_memoized_app_module_form(self, domain): try: form = Form.get_form(self.form_unique_id) app = form.get_app() module = form.get_module() except (ResourceNotFound, XFormIdNotUnique): return None, None, None, None if app.domain != domain: return None, None, None, None return app, module, form, form_requires_input(form)
def get_first_ivr_response_data(recipient, call_log_entry, logged_subevent): """ As long as the form has at least one question in it (i.e., it doesn't consist of all labels), then we can start the touchforms session now and cache the first IVR response, so that all we need to do later is serve it up. This makes for less time ringing when the user is on the phone, waiting for the line to pick up. If the form consists of all labels, we don't do anything here, because then we would end up submitting the form right away regardless of whether the user actually got the call. Returns (ivr_data, error) where ivr_data is an instance of IVRResponseData """ app, module, form, error = get_app_module_form(call_log_entry, logged_subevent) if error: return (None, True) if form_requires_input(form): session, responses, error = start_call_session(recipient, call_log_entry, logged_subevent, app, module, form) if error: return (None, True) ivr_responses = [] for response in responses: ivr_responses.append( format_ivr_response(response.event.caption, app)) ivr_data = IVRResponseData(ivr_responses, get_input_length(responses[-1]), session) return (ivr_data, False) return (None, False)
def fire_sms_survey_event(reminder, handler, recipients, verified_numbers, logged_event): if reminder.callback_try_count > 0: # Handle timeouts if handler.submit_partial_forms and ( reminder.callback_try_count == len(reminder.current_event.callback_timeout_intervals) ): # Submit partial form completions for session_id in reminder.xforms_session_ids: submit_unfinished_form(session_id, handler.include_case_side_effects) else: # Resend current question for session_id in reminder.xforms_session_ids: session = get_session_by_session_id(session_id) if session.end_time is None: vn = VerifiedNumber.view( "sms/verified_number_by_owner_id", key=session.connection_id, include_docs=True ).first() if vn is not None: metadata = MessageMetadata( workflow=get_workflow(handler), reminder_id=reminder._id, xforms_session_couch_id=session._id, ) resp = current_question(session_id) send_sms_to_verified_number(vn, resp.event.text_prompt, metadata) else: reminder.xforms_session_ids = [] domain_obj = Domain.get_by_name(reminder.domain, strict=True) # Get the app, module, and form try: form_unique_id = reminder.current_event.form_unique_id form = Form.get_form(form_unique_id) app = form.get_app() module = form.get_module() except Exception: logged_event.error(MessagingEvent.ERROR_CANNOT_FIND_FORM) return # Start a touchforms session for each recipient for recipient in recipients: logged_subevent = logged_event.create_subevent(handler, reminder, recipient) verified_number, unverified_number = get_recipient_phone_number(reminder, recipient, verified_numbers) no_verified_number = verified_number is None cant_use_unverified_number = ( unverified_number is None or not domain_obj.send_to_duplicated_case_numbers or form_requires_input(form) ) if no_verified_number and cant_use_unverified_number: logged_subevent.error(MessagingEvent.ERROR_NO_TWO_WAY_PHONE_NUMBER) continue key = "start-sms-survey-for-contact-%s" % recipient.get_id with CriticalSection([key], timeout=60): # Get the case to submit the form against, if any if isinstance(recipient, CommCareCase) and not handler.force_surveys_to_use_triggered_case: case_id = recipient.get_id else: case_id = reminder.case_id if form.requires_case() and not case_id: logged_subevent.error(MessagingEvent.ERROR_NO_CASE_GIVEN) continue # Close all currently open sessions SQLXFormsSession.close_all_open_sms_sessions(reminder.domain, recipient.get_id) # Start the new session try: session, responses = start_session( reminder.domain, recipient, app, module, form, case_id, case_for_case_submission=handler.force_surveys_to_use_triggered_case, ) except TouchformsError as e: human_readable_message = e.response_data.get("human_readable_message", None) logged_subevent.error( MessagingEvent.ERROR_TOUCHFORMS_ERROR, additional_error_text=human_readable_message ) if touchforms_error_is_config_error(e): # Don't reraise the exception because this means there are configuration # issues with the form that need to be fixed continue else: # Reraise the exception so that the framework retries it again later raise except Exception as e: logged_subevent.error(MessagingEvent.ERROR_TOUCHFORMS_ERROR) # Reraise the exception so that the framework retries it again later raise session.survey_incentive = handler.survey_incentive session.workflow = get_workflow(handler) session.reminder_id = reminder._id session.save() reminder.xforms_session_ids.append(session.session_id) logged_subevent.xforms_session = session logged_subevent.save() # Send out first message if len(responses) > 0: message = format_message_list(responses) metadata = MessageMetadata( workflow=get_workflow(handler), reminder_id=reminder._id, xforms_session_couch_id=session._id ) if verified_number: send_sms_to_verified_number(verified_number, message, metadata) else: send_sms(reminder.domain, recipient, unverified_number, message, metadata) logged_subevent.completed()
def fire_sms_survey_event(reminder, handler, recipients, verified_numbers, logged_event): if reminder.callback_try_count > 0: # Handle timeouts if handler.submit_partial_forms and ( reminder.callback_try_count == len( reminder.current_event.callback_timeout_intervals)): # Submit partial form completions for session_id in reminder.xforms_session_ids: submit_unfinished_form(session_id, handler.include_case_side_effects) else: # Resend current question for session_id in reminder.xforms_session_ids: session = get_session_by_session_id(session_id) if session.end_time is None: vn = VerifiedNumber.view("sms/verified_number_by_owner_id", key=session.connection_id, include_docs=True).first() if vn is not None: metadata = MessageMetadata( workflow=get_workflow(handler), reminder_id=reminder._id, xforms_session_couch_id=session._id, ) resp = current_question(session_id) send_sms_to_verified_number(vn, resp.event.text_prompt, metadata) else: reminder.xforms_session_ids = [] domain_obj = Domain.get_by_name(reminder.domain, strict=True) # Get the app, module, and form try: form_unique_id = reminder.current_event.form_unique_id form = Form.get_form(form_unique_id) app = form.get_app() module = form.get_module() except Exception: logged_event.error(MessagingEvent.ERROR_CANNOT_FIND_FORM) return # Start a touchforms session for each recipient for recipient in recipients: logged_subevent = logged_event.create_subevent( handler, reminder, recipient) verified_number, unverified_number = get_recipient_phone_number( reminder, recipient, verified_numbers) no_verified_number = verified_number is None cant_use_unverified_number = ( unverified_number is None or not domain_obj.send_to_duplicated_case_numbers or form_requires_input(form)) if no_verified_number and cant_use_unverified_number: logged_subevent.error( MessagingEvent.ERROR_NO_TWO_WAY_PHONE_NUMBER) continue key = "start-sms-survey-for-contact-%s" % recipient.get_id with CriticalSection([key], timeout=60): # Get the case to submit the form against, if any if (isinstance(recipient, CommCareCase) and not handler.force_surveys_to_use_triggered_case): case_id = recipient.get_id else: case_id = reminder.case_id if form.requires_case() and not case_id: logged_subevent.error(MessagingEvent.ERROR_NO_CASE_GIVEN) continue # Close all currently open sessions SQLXFormsSession.close_all_open_sms_sessions( reminder.domain, recipient.get_id) # Start the new session try: session, responses = start_session( reminder.domain, recipient, app, module, form, case_id, case_for_case_submission=handler. force_surveys_to_use_triggered_case) except TouchformsError as e: human_readable_message = e.response_data.get( 'human_readable_message', None) logged_subevent.error( MessagingEvent.ERROR_TOUCHFORMS_ERROR, additional_error_text=human_readable_message) if touchforms_error_is_config_error(e): # Don't reraise the exception because this means there are configuration # issues with the form that need to be fixed continue else: # Reraise the exception so that the framework retries it again later raise except Exception as e: logged_subevent.error( MessagingEvent.ERROR_TOUCHFORMS_ERROR) # Reraise the exception so that the framework retries it again later raise session.survey_incentive = handler.survey_incentive session.workflow = get_workflow(handler) session.reminder_id = reminder._id session.save() reminder.xforms_session_ids.append(session.session_id) logged_subevent.xforms_session = session logged_subevent.save() # Send out first message if len(responses) > 0: message = format_message_list(responses) metadata = MessageMetadata( workflow=get_workflow(handler), reminder_id=reminder._id, xforms_session_couch_id=session._id, ) if verified_number: send_sms_to_verified_number(verified_number, message, metadata) else: send_sms(reminder.domain, recipient, unverified_number, message, metadata) logged_subevent.completed()
def fire_sms_survey_event(reminder, handler, recipients, verified_numbers): if reminder.callback_try_count > 0: # Handle timeouts if handler.submit_partial_forms and (reminder.callback_try_count == len(reminder.current_event.callback_timeout_intervals)): # Submit partial form completions for session_id in reminder.xforms_session_ids: submit_unfinished_form(session_id, handler.include_case_side_effects) else: # Resend current question for session_id in reminder.xforms_session_ids: session = XFormsSession.view("smsforms/sessions_by_touchforms_id", startkey=[session_id], endkey=[session_id, {}], include_docs=True).one() if session.end_time is None: vn = VerifiedNumber.view("sms/verified_number_by_owner_id", key=session.connection_id, include_docs=True).first() if vn is not None: metadata = MessageMetadata( workflow=get_workflow(handler), reminder_id=reminder._id, xforms_session_couch_id=session._id, ) resp = current_question(session_id) send_sms_to_verified_number(vn, resp.event.text_prompt, metadata) return True else: reminder.xforms_session_ids = [] # Get the app, module, and form try: form_unique_id = reminder.current_event.form_unique_id form = Form.get_form(form_unique_id) app = form.get_app() module = form.get_module() except Exception as e: raise_error(reminder, ERROR_FORM) return False # Start a touchforms session for each recipient for recipient in recipients: verified_number, unverified_number = get_recipient_phone_number( reminder, recipient, verified_numbers) domain_obj = Domain.get_by_name(reminder.domain, strict=True) no_verified_number = verified_number is None cant_use_unverified_number = (unverified_number is None or not domain_obj.send_to_duplicated_case_numbers or form_requires_input(form)) if no_verified_number and cant_use_unverified_number: if len(recipients) == 1: raise_error(reminder, ERROR_NO_VERIFIED_NUMBER) return False else: continue # Close all currently open sessions XFormsSession.close_all_open_sms_sessions(reminder.domain, recipient.get_id) # Start the new session if isinstance(recipient, CommCareCase) and not handler.force_surveys_to_use_triggered_case: case_id = recipient.get_id else: case_id = reminder.case_id session, responses = start_session(reminder.domain, recipient, app, module, form, case_id, case_for_case_submission=handler.force_surveys_to_use_triggered_case) session.survey_incentive = handler.survey_incentive session.workflow = get_workflow(handler) session.reminder_id = reminder._id session.save() reminder.xforms_session_ids.append(session.session_id) # Send out first message if len(responses) > 0: message = format_message_list(responses) metadata = MessageMetadata( workflow=get_workflow(handler), reminder_id=reminder._id, xforms_session_couch_id=session._id, ) if verified_number: result = send_sms_to_verified_number(verified_number, message, metadata) else: result = send_sms(reminder.domain, recipient, unverified_number, message, metadata) if len(recipients) == 1: return result return True
def initiate_outbound_call(call_log_entry, *args, **kwargs): phone_number = call_log_entry.phone_number if phone_number.startswith("+"): phone_number = phone_number[1:] if phone_number.startswith("91"): phone_number = "0" + phone_number[2:] else: call_log_entry.error = True call_log_entry.error_message = "Kookoo can only send to Indian phone numbers." call_log_entry.save() return False form = Form.get_form(call_log_entry.form_unique_id) app = form.get_app() module = form.get_module() # Only precache the first response if it's not an only-label form, otherwise we could end up # submitting the form regardless of whether the person actually answers the call. if form_requires_input(form): recipient = call_log_entry.recipient case_id = call_log_entry.case_id case_for_case_submission = call_log_entry.case_for_case_submission session, responses = start_session(recipient.domain, recipient, app, module, form, case_id, yield_responses=True, session_type=XFORMS_SESSION_IVR, case_for_case_submission=case_for_case_submission) ivr_responses = [] if len(responses) == 0: call_log_entry.error = True call_log_entry.error_message = "No prompts seen in form. Please check that the form does not have errors." call_log_entry.save() return False for response in responses: ivr_responses.append(format_ivr_response(response.event.caption, app)) input_length = get_input_length(responses[-1]) call_log_entry.use_precached_first_response = True call_log_entry.xforms_session_id = session.session_id url_base = get_url_base() params = urlencode({ "phone_no" : phone_number, "api_key" : kwargs["api_key"], "outbound_version" : "2", "url" : url_base + reverse("corehq.apps.kookoo.views.ivr"), "callback_url" : url_base + reverse("corehq.apps.kookoo.views.ivr_finished"), }) url = "http://www.kookoo.in/outbound/outbound.php?%s" % params if kwargs.get("is_test", False): session_id = hashlib.sha224(datetime.utcnow().isoformat()).hexdigest() response = "<request><status>queued</status><message>%s</message></request>" % session_id else: response = urlopen(url, timeout=settings.IVR_GATEWAY_TIMEOUT).read() root = XML(response) for child in root: if child.tag.endswith("status"): status = child.text elif child.tag.endswith("message"): message = child.text do_not_retry = False if status == "queued": call_log_entry.error = False call_log_entry.gateway_session_id = "KOOKOO-" + message elif status == "error": call_log_entry.error = True call_log_entry.error_message = message if (message.strip().upper() in [ 'CALLS WILL NOT BE MADE BETWEEN 9PM TO 9AM.', 'PHONE NUMBER IN DND LIST', ]): do_not_retry = True else: call_log_entry.error = True call_log_entry.error_message = "Unknown status received from Kookoo." if call_log_entry.error: call_log_entry.use_precached_first_response = False if call_log_entry.use_precached_first_response: call_log_entry.first_response = get_http_response_string(call_log_entry.gateway_session_id, ivr_responses, collect_input=True, hang_up=False, input_length=input_length) call_log_entry.save() return not call_log_entry.error or do_not_retry
def fire_sms_survey_event(reminder, handler, recipients, verified_numbers, logged_event): current_event = reminder.current_event if reminder.callback_try_count > 0: # Leaving this as an explicit reminder that all survey related actions now happen # in a different process. Eventually all of this code will be removed when we move # to the new reminders framework. pass else: reminder.xforms_session_ids = [] domain_obj = Domain.get_by_name(reminder.domain, strict=True) # Get the app, module, and form try: form_unique_id = current_event.form_unique_id form = Form.get_form(form_unique_id) app = form.get_app() module = form.get_module() except Exception: logged_event.error(MessagingEvent.ERROR_CANNOT_FIND_FORM) return # Start a touchforms session for each recipient for recipient in recipients: logged_subevent = logged_event.create_subevent( handler, reminder, recipient) verified_number, unverified_number = get_recipient_phone_number( reminder, recipient, verified_numbers) no_verified_number = verified_number is None cant_use_unverified_number = (unverified_number is None or form_requires_input(form)) if no_verified_number and cant_use_unverified_number: logged_subevent.error( MessagingEvent.ERROR_NO_TWO_WAY_PHONE_NUMBER) continue if verified_number: pb = PhoneBlacklist.get_by_phone_number_or_none( verified_number.phone_number) else: pb = PhoneBlacklist.get_by_phone_number_or_none( unverified_number) if pb and not pb.send_sms: logged_subevent.error(MessagingEvent.ERROR_PHONE_OPTED_OUT) continue with critical_section_for_smsforms_sessions(recipient.get_id): # Get the case to submit the form against, if any if (is_commcarecase(recipient) and not handler.force_surveys_to_use_triggered_case): case_id = recipient.case_id else: case_id = reminder.case_id if form.requires_case() and not case_id: logged_subevent.error(MessagingEvent.ERROR_NO_CASE_GIVEN) continue # Close all currently open sessions SQLXFormsSession.close_all_open_sms_sessions( reminder.domain, recipient.get_id) # Start the new session try: if current_event.callback_timeout_intervals: if handler.submit_partial_forms: expire_after = sum( current_event.callback_timeout_intervals) reminder_intervals = current_event.callback_timeout_intervals[: -1] else: expire_after = SQLXFormsSession.MAX_SESSION_LENGTH reminder_intervals = current_event.callback_timeout_intervals submit_partially_completed_forms = handler.submit_partial_forms include_case_updates_in_partial_submissions = handler.include_case_side_effects else: expire_after = SQLXFormsSession.MAX_SESSION_LENGTH reminder_intervals = [] submit_partially_completed_forms = False include_case_updates_in_partial_submissions = False session, responses = start_session( SQLXFormsSession.create_session_object( reminder.domain, recipient, verified_number.phone_number if verified_number else unverified_number, app, form, expire_after=expire_after, reminder_intervals=reminder_intervals, submit_partially_completed_forms= submit_partially_completed_forms, include_case_updates_in_partial_submissions= include_case_updates_in_partial_submissions), reminder.domain, recipient, app, module, form, case_id, case_for_case_submission=handler. force_surveys_to_use_triggered_case) except TouchformsError as e: human_readable_message = get_formplayer_exception( reminder.domain, e) logged_subevent.error( MessagingEvent.ERROR_TOUCHFORMS_ERROR, additional_error_text=human_readable_message) if touchforms_error_is_config_error(reminder.domain, e): # Don't reraise the exception because this means there are configuration # issues with the form that need to be fixed continue else: # Reraise the exception so that the framework retries it again later raise except Exception as e: logged_subevent.error( MessagingEvent.ERROR_TOUCHFORMS_ERROR) # Reraise the exception so that the framework retries it again later raise session.survey_incentive = handler.survey_incentive session.workflow = get_workflow(handler) session.reminder_id = reminder._id session.save() reminder.xforms_session_ids.append(session.session_id) logged_subevent.xforms_session = session logged_subevent.save() # Send out first message if len(responses) > 0: message = format_message_list(responses) metadata = MessageMetadata( workflow=get_workflow(handler), reminder_id=reminder._id, xforms_session_couch_id=session._id, ) if verified_number: send_sms_to_verified_number( verified_number, message, metadata, logged_subevent=logged_subevent) else: send_sms(reminder.domain, recipient, unverified_number, message, metadata) logged_subevent.completed()
def fire_sms_survey_event(reminder, handler, recipients, verified_numbers): if reminder.callback_try_count > 0: # Handle timeouts if handler.submit_partial_forms and ( reminder.callback_try_count == len( reminder.current_event.callback_timeout_intervals)): # Submit partial form completions for session_id in reminder.xforms_session_ids: submit_unfinished_form(session_id, handler.include_case_side_effects) else: # Resend current question for session_id in reminder.xforms_session_ids: session = XFormsSession.view( "smsforms/sessions_by_touchforms_id", startkey=[session_id], endkey=[session_id, {}], include_docs=True).one() if session.end_time is None: vn = VerifiedNumber.view("sms/verified_number_by_owner_id", key=session.connection_id, include_docs=True).first() if vn is not None: metadata = MessageMetadata( workflow=get_workflow(handler), reminder_id=reminder._id, xforms_session_couch_id=session._id, ) resp = current_question(session_id) send_sms_to_verified_number(vn, resp.event.text_prompt, metadata) return True else: reminder.xforms_session_ids = [] # Get the app, module, and form try: form_unique_id = reminder.current_event.form_unique_id form = Form.get_form(form_unique_id) app = form.get_app() module = form.get_module() except Exception as e: raise_error(reminder, ERROR_FORM) return False # Start a touchforms session for each recipient for recipient in recipients: verified_number, unverified_number = get_recipient_phone_number( reminder, recipient, verified_numbers) domain_obj = Domain.get_by_name(reminder.domain, strict=True) no_verified_number = verified_number is None cant_use_unverified_number = ( unverified_number is None or not domain_obj.send_to_duplicated_case_numbers or form_requires_input(form)) if no_verified_number and cant_use_unverified_number: if len(recipients) == 1: raise_error(reminder, ERROR_NO_VERIFIED_NUMBER) return False else: continue # Close all currently open sessions XFormsSession.close_all_open_sms_sessions(reminder.domain, recipient.get_id) # Start the new session if isinstance( recipient, CommCareCase ) and not handler.force_surveys_to_use_triggered_case: case_id = recipient.get_id else: case_id = reminder.case_id session, responses = start_session( reminder.domain, recipient, app, module, form, case_id, case_for_case_submission=handler. force_surveys_to_use_triggered_case) session.survey_incentive = handler.survey_incentive session.workflow = get_workflow(handler) session.reminder_id = reminder._id session.save() reminder.xforms_session_ids.append(session.session_id) # Send out first message if len(responses) > 0: message = format_message_list(responses) metadata = MessageMetadata( workflow=get_workflow(handler), reminder_id=reminder._id, xforms_session_couch_id=session._id, ) if verified_number: result = send_sms_to_verified_number( verified_number, message, metadata) else: result = send_sms(reminder.domain, recipient, unverified_number, message, metadata) if len(recipients) == 1: return result return True
def initiate_outbound_call(call_log_entry, *args, **kwargs): phone_number = call_log_entry.phone_number if phone_number.startswith("+"): phone_number = phone_number[1:] if phone_number.startswith("91"): phone_number = "0" + phone_number[2:] else: call_log_entry.error = True call_log_entry.error_message = "Kookoo can only send to Indian phone numbers." call_log_entry.save() return False form = Form.get_form(call_log_entry.form_unique_id) app = form.get_app() module = form.get_module() # Only precache the first response if it's not an only-label form, otherwise we could end up # submitting the form regardless of whether the person actually answers the call. if form_requires_input(form): recipient = call_log_entry.recipient case_id = get_case_id(call_log_entry) session, responses = start_session(recipient.domain, recipient, app, module, form, case_id, yield_responses=True, session_type=XFORMS_SESSION_IVR) ivr_responses = [] if len(responses) == 0: call_log_entry.error = True call_log_entry.error_message = "No prompts seen in form. Please check that the form does not have errors." call_log_entry.save() return False for response in responses: ivr_responses.append( format_ivr_response(response.event.caption, app)) input_length = get_input_length(responses[-1]) call_log_entry.use_precached_first_response = True call_log_entry.xforms_session_id = session.session_id url_base = get_url_base() params = urlencode({ "phone_no": phone_number, "api_key": kwargs["api_key"], "outbound_version": "2", "url": url_base + reverse("corehq.apps.kookoo.views.ivr"), "callback_url": url_base + reverse("corehq.apps.kookoo.views.ivr_finished"), }) url = "http://www.kookoo.in/outbound/outbound.php?%s" % params response = urlopen(url, timeout=settings.IVR_GATEWAY_TIMEOUT).read() root = XML(response) for child in root: if child.tag.endswith("status"): status = child.text elif child.tag.endswith("message"): message = child.text if status == "queued": call_log_entry.error = False call_log_entry.gateway_session_id = "KOOKOO-" + message elif status == "error": call_log_entry.error = True call_log_entry.error_message = message else: call_log_entry.error = True call_log_entry.error_message = "Unknown status received from Kookoo." if call_log_entry.error: call_log_entry.use_precached_first_response = False if call_log_entry.use_precached_first_response: call_log_entry.first_response = get_http_response_string( call_log_entry.gateway_session_id, ivr_responses, collect_input=True, hang_up=False, input_length=input_length) call_log_entry.save() return not call_log_entry.error
def initiate_outbound_call(call_log_entry, *args, **kwargs): phone_number = call_log_entry.phone_number if phone_number.startswith("+"): phone_number = phone_number[1:] if phone_number.startswith("91"): phone_number = "0" + phone_number[2:] else: raise InvalidPhoneNumberException("Kookoo can only send to Indian phone numbers.") form = Form.get_form(call_log_entry.form_unique_id) app = form.get_app() module = form.get_module() # Only precache the first response if it's not an only-label form, otherwise we could end up # submitting the form regardless of whether the person actually answers the call. if form_requires_input(form): recipient = call_log_entry.recipient case_id = get_case_id(call_log_entry) session, responses = start_session(recipient.domain, recipient, app, module, form, case_id, yield_responses=True, session_type=XFORMS_SESSION_IVR) ivr_responses = [] if len(responses) == 0: call_log_entry.error = True call_log_entry.error_message = "No prompts seen in form. Please check that the form does not have errors." call_log_entry.save() return False for response in responses: ivr_responses.append(format_ivr_response(response.event.caption, app)) input_length = get_input_length(responses[-1]) call_log_entry.use_precached_first_response = True call_log_entry.xforms_session_id = session.session_id url_base = get_url_base() params = urlencode({ "phone_no" : phone_number, "api_key" : kwargs["api_key"], "outbound_version" : "2", "url" : url_base + reverse("corehq.apps.kookoo.views.ivr"), "callback_url" : url_base + reverse("corehq.apps.kookoo.views.ivr_finished"), }) url = "http://www.kookoo.in/outbound/outbound.php?%s" % params response = urlopen(url).read() root = XML(response) for child in root: if child.tag.endswith("status"): status = child.text elif child.tag.endswith("message"): message = child.text if status == "queued": call_log_entry.error = False call_log_entry.gateway_session_id = "KOOKOO-" + message elif status == "error": call_log_entry.error = True call_log_entry.error_message = message else: call_log_entry.error = True call_log_entry.error_message = "Unknown status received from Kookoo." if call_log_entry.error: call_log_entry.use_precached_first_response = False if call_log_entry.use_precached_first_response: call_log_entry.first_response = get_http_response_string(call_log_entry.gateway_session_id, ivr_responses, collect_input=True, hang_up=False, input_length=input_length) call_log_entry.save() return not call_log_entry.error