def test_get_all_open_sessions_contact_mismatch(self): domain = uuid.uuid4().hex contact = uuid.uuid4().hex _make_session( domain=domain, connection_id='wrong', end_time=None, session_type=XFORMS_SESSION_SMS, ) self.assertEqual(0, len(XFormsSession.get_all_open_sms_sessions(domain, contact)))
def test_get_all_open_sessions_already_ended(self): domain = uuid.uuid4().hex contact = uuid.uuid4().hex _make_session( domain=domain, connection_id=contact, end_time=datetime.utcnow(), session_type=XFORMS_SESSION_SMS, ) self.assertEqual(0, len(XFormsSession.get_all_open_sms_sessions(domain, contact)))
def test_get_and_close_all_open_sessions(self): domain = uuid.uuid4().hex contact = uuid.uuid4().hex for i in range(3): _make_session( domain=domain, connection_id=contact, end_time=None, session_type=XFORMS_SESSION_SMS, ) couch_sessions = XFormsSession.get_all_open_sms_sessions(domain, contact) sql_sessions = SQLXFormsSession.get_all_open_sms_sessions(domain, contact) self.assertEqual(3, len(couch_sessions)) self.assertEqual(3, len(sql_sessions)) self.assertEqual(set([x._id for x in couch_sessions]), set([x.couch_id for x in sql_sessions])) SQLXFormsSession.close_all_open_sms_sessions(domain, contact) self.assertEqual(0, len(XFormsSession.get_all_open_sms_sessions(domain, contact))) self.assertEqual(0, len(SQLXFormsSession.get_all_open_sms_sessions(domain, contact)))
def form_session_handler(v, text, msg=None): """ The form session handler will use the inbound text to answer the next question in the open XformsSession for the associated contact. If no session is open, the handler passes. If multiple sessions are open, they are all closed and an error message is displayed to the user. """ sessions = XFormsSession.get_all_open_sms_sessions(v.domain, v.owner_id) if len(sessions) > 1: # If there are multiple sessions, there's no way for us to know which one this message # belongs to. So we should inform the user that there was an error and to try to restart # the survey. for session in sessions: session.end(False) session.save() send_sms_to_verified_number(v, "An error has occurred. Please try restarting the survey.") return True session = sessions[0] if len(sessions) == 1 else None if session is not None: if msg is not None: msg.workflow = session.workflow msg.reminder_id = session.reminder_id msg.xforms_session_couch_id = session._id msg.save() # If there's an open session, treat the inbound text as the answer to the next question try: resp = current_question(session.session_id) event = resp.event valid, text, error_msg = validate_answer(event, text) if valid: responses = _get_responses(v.domain, v.owner_id, text, yield_responses=True) if has_invalid_response(responses): if msg: mark_as_invalid_response(msg) text_responses = _responses_to_text(responses) if len(text_responses) > 0: response_text = format_message_list(text_responses) send_sms_to_verified_number(v, response_text, workflow=session.workflow, reminder_id=session.reminder_id, xforms_session_couch_id=session._id) else: if msg: mark_as_invalid_response(msg) send_sms_to_verified_number(v, error_msg + event.text_prompt, workflow=session.workflow, reminder_id=session.reminder_id, xforms_session_couch_id=session._id) except Exception: # Catch any touchforms errors msg_id = msg._id if msg is not None else "" logging.exception("Exception in form_session_handler for message id %s." % msg_id) send_sms_to_verified_number(v, "An error has occurred. Please try again later. If the problem persists, try restarting the survey.") return True else: return False
def sms_keyword_handler(v, text, msg): text = text.strip() if text == "": return False sessions = XFormsSession.get_all_open_sms_sessions(v.domain, v.owner_id) text_words = text.upper().split() if text.startswith("#"): return handle_global_keywords(v, text, msg, text_words, sessions) else: return handle_domain_keywords(v, text, msg, text_words, sessions)
def sms_keyword_handler(v, text, msg): text = text.strip() if text == "": return False sessions = XFormsSession.get_all_open_sms_sessions(v.domain, v.owner_id) text_words = text.upper().split() if text.startswith("#"): return handle_global_keywords(v, text, msg, text_words, sessions) else: return handle_domain_keywords(v, text, msg, text_words, sessions)
def test_get_single_open_session_close_multiple(self): domain = uuid.uuid4().hex contact = uuid.uuid4().hex for i in range(3): _make_session( domain=domain, connection_id=contact, end_time=None, session_type=XFORMS_SESSION_SMS, ) (mult, session) = get_single_open_session_or_close_multiple(domain, contact) self.assertEqual(True, mult) self.assertEqual(None, session) self.assertEqual(0, len(XFormsSession.get_all_open_sms_sessions(domain, contact))) self.assertEqual(0, len(SQLXFormsSession.get_all_open_sms_sessions(domain, contact)))
def get_single_open_session(domain, contact_id): """ Retrieves the current open XFormsSession for the given contact. If multiple sessions are open, it closes all of them and returns None for the session. The return value is a tuple of (multiple, session), where multiple is True if there were multiple sessions, and session is the session if there was a single open session available. """ sessions = XFormsSession.get_all_open_sms_sessions(domain, contact_id) if len(sessions) > 1: for session in sessions: session.end(False) session.save() return (True, None) session = sessions[0] if len(sessions) == 1 else None return (False, session)
def get_single_open_session(domain, contact_id): """ Retrieves the current open XFormsSession for the given contact. If multiple sessions are open, it closes all of them and returns None for the session. The return value is a tuple of (multiple, session), where multiple is True if there were multiple sessions, and session is the session if there was a single open session available. """ sessions = XFormsSession.get_all_open_sms_sessions(domain, contact_id) if len(sessions) > 1: for session in sessions: session.end(False) session.save() return (True, None) session = sessions[0] if len(sessions) == 1 else None return (False, session)
def test_get_single_open_session(self): properties = _arbitrary_session_properties( end_time=None, session_type=XFORMS_SESSION_SMS, ) couch_session = XFormsSession(**properties) couch_session.save() (mult, session) = get_single_open_session_or_close_multiple( couch_session.domain, couch_session.connection_id ) self.assertEqual(False, mult) self.assertEqual(couch_session._id, session._id) [couch_session_back] = XFormsSession.get_all_open_sms_sessions( couch_session.domain, couch_session.connection_id ) [sql_session] = SQLXFormsSession.get_all_open_sms_sessions( couch_session.domain, couch_session.connection_id ) self.assertEqual(couch_session._id, couch_session_back._id) self.assertEqual(couch_session._id, sql_session.couch_id)
def sms_keyword_handler(v, text, msg=None): from corehq.apps.reminders.models import SurveyKeyword text = text.strip() if text == "": return False sessions = XFormsSession.get_all_open_sms_sessions(v.domain, v.owner_id) any_session_open = len(sessions) > 0 text_words = text.upper().split() if text.startswith("#"): if len(text_words) > 0 and text_words[0] == "#START": # Respond to "#START <keyword>" command if len(text_words) > 1: sk = SurveyKeyword.get_keyword(v.domain, text_words[1]) if sk is not None: if len(sk.initiator_doc_type_filter) > 0 and v.owner_doc_type not in sk.initiator_doc_type_filter: # The contact type is not allowed to invoke this keyword return False process_survey_keyword_actions(v, sk, text[6:].strip(), msg=msg) else: send_sms_to_verified_number( v, "Keyword not found: '%s'." % text_words[1], workflow=WORKFLOW_KEYWORD ) else: send_sms_to_verified_number(v, "Usage: #START <keyword>", workflow=WORKFLOW_KEYWORD) elif len(text_words) > 0 and text_words[0] == "#STOP": # Respond to "#STOP" keyword XFormsSession.close_all_open_sms_sessions(v.domain, v.owner_id) elif len(text_words) > 0 and text_words[0] == "#CURRENT": # Respond to "#CURRENT" keyword if len(sessions) == 1: resp = current_question(sessions[0].session_id) send_sms_to_verified_number( v, resp.event.text_prompt, workflow=sessions[0].workflow, reminder_id=sessions[0].reminder_id, xforms_session_couch_id=sessions[0]._id, ) else: # Response to unknown command send_sms_to_verified_number(v, "Unknown command: '%s'" % text_words[0]) if msg is not None: msg.workflow = WORKFLOW_KEYWORD msg.save() return True else: for survey_keyword in SurveyKeyword.get_all(v.domain): if survey_keyword.delimiter is not None: args = text.split(survey_keyword.delimiter) else: args = text.split() keyword = args[0].strip().upper() if keyword == survey_keyword.keyword.upper(): if any_session_open and not survey_keyword.override_open_sessions: # We don't want to override any open sessions, so just pass and let the form session handler handle the message return False elif ( len(survey_keyword.initiator_doc_type_filter) > 0 and v.owner_doc_type not in survey_keyword.initiator_doc_type_filter ): # The contact type is not allowed to invoke this keyword return False else: process_survey_keyword_actions(v, survey_keyword, text, msg=msg) if msg is not None: msg.workflow = WORKFLOW_KEYWORD msg.save() return True # No keywords matched, so pass the message onto the next handler return False