Beispiel #1
0
def process_survey_keyword_actions(verified_number, survey_keyword, text, msg):
    sender = verified_number.owner
    case = None
    args = split_args(text, survey_keyword)

    # Close any open sessions even if it's just an sms that we're
    # responding with.
    XFormsSession.close_all_open_sms_sessions(verified_number.domain,
        verified_number.owner_id)

    if sender.doc_type == "CommCareCase":
        case = sender
        args = args[1:]
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
Beispiel #3
0
def global_keyword_stop(v, text, msg, text_words, open_sessions):
    XFormsSession.close_all_open_sms_sessions(v.domain, v.owner_id)
    return True
Beispiel #4
0
def process_survey_keyword_actions(verified_number, survey_keyword, text, msg):
    sender = verified_number.owner
    case = None
    args = split_args(text, survey_keyword)

    # Close any open sessions even if it's just an sms that we're
    # responding with.
    XFormsSession.close_all_open_sms_sessions(verified_number.domain,
        verified_number.owner_id)

    if sender.doc_type == "CommCareCase":
        case = sender
        args = args[1:]
    elif sender.doc_type == "CommCareUser":
        if keyword_uses_form_that_requires_case(survey_keyword):
            if len(args) > 1:
                external_id = args[1]
                case = get_case_by_external_id(verified_number.domain,
                    external_id)
                if case is None or not user_can_access_case(sender, case):
                    send_keyword_response(verified_number, MSG_CASE_NOT_FOUND)
                    return
            else:
                send_keyword_response(verified_number, MSG_MISSING_EXTERNAL_ID)
                return
            args = args[2:]
        else:
            args = args[1:]
    def cmp_fcn(a1, a2):
        a1_ss = (a1.action == METHOD_STRUCTURED_SMS)
        a2_ss = (a2.action == METHOD_STRUCTURED_SMS)
        if a1_ss and a2_ss:
            return 0
        elif a1_ss:
            return -1
        elif a2_ss:
            return 1
        else:
            return 0
    # Process structured sms actions first
    actions = sorted(survey_keyword.actions, cmp=cmp_fcn)
    for survey_keyword_action in actions:
        if survey_keyword_action.recipient == RECIPIENT_SENDER:
            contact = sender
        elif survey_keyword_action.recipient == RECIPIENT_OWNER:
            if sender.doc_type == "CommCareCase":
                contact = get_wrapped_owner(get_owner_id(sender))
            else:
                contact = None
        elif survey_keyword_action.recipient == RECIPIENT_USER_GROUP:
            try:
                contact = Group.get(survey_keyword_action.recipient_id)
                assert contact.doc_type == "Group"
                assert contact.domain == verified_number.domain
            except Exception:
                contact = None
        else:
            contact = None

        if contact is None:
            continue

        if survey_keyword_action.action == METHOD_SMS:
            create_immediate_reminder(contact, METHOD_SMS, 
                reminder_type=REMINDER_TYPE_KEYWORD_INITIATED,
                message=survey_keyword_action.message_content,
                case=case)
        elif survey_keyword_action.action == METHOD_SMS_SURVEY:
            create_immediate_reminder(contact, METHOD_SMS_SURVEY,
                reminder_type=REMINDER_TYPE_KEYWORD_INITIATED,
                form_unique_id=survey_keyword_action.form_unique_id,
                case=case)
        elif survey_keyword_action.action == METHOD_STRUCTURED_SMS:
            res = handle_structured_sms(survey_keyword, survey_keyword_action,
                sender, verified_number, text, send_response=True, msg=msg,
                case=case, text_args=args)
            if not res:
                # If the structured sms processing wasn't successful, don't
                # process any of the other actions
                return
Beispiel #5
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
Beispiel #6
0
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
Beispiel #7
0
def global_keyword_stop(v, text, msg, text_words, open_sessions):
    XFormsSession.close_all_open_sms_sessions(v.domain, v.owner_id)
    return True