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)))
Exemple #4
0
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
Exemple #5
0
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)
Exemple #6
0
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)
Exemple #9
0
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)
Exemple #11
0
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