コード例 #1
0
ファイル: views.py プロジェクト: philipkaare/commcare-hq
def device_data(request):
    if "data" not in request.POST:
        return HttpResponseBadRequest("Missing 'data' POST parameter.")

    data = request.POST.get("data")
    data = data.strip()
    data_points = data.split(",")
    device_id = None
    for data_point in data_points:
        key_value = data_point.partition("=")
        key = key_value[0].strip().upper()
        value = key_value[2].strip()
        if key == "SN":
            device_id = value
            break

    if device_id is None:
        return HttpResponseBadRequest("Missing 'SN' in data string.")

    # This view lookup is an implicit assert that either one device exists
    # with the given device_id, or no devices exist with this device_id.
    case = CommConnectCase.view("wisepill/device", key=[device_id], include_docs=True).one()

    event = WisePillDeviceEvent(
        domain=case.domain if case is not None else None,
        data=data,
        received_on=datetime.utcnow(),
        case_id=case._id if case is not None else None,
        processed=False,
    )
    event.save()

    if case is not None:
        survey_keywords = SurveyKeyword.get_all(case.domain)
        for survey_keyword in survey_keywords:
            if survey_keyword.keyword.upper() == "DEVICE_EVENT":
                for survey_keyword_action in survey_keyword.actions:
                    if survey_keyword_action.action == METHOD_STRUCTURED_SMS:
                        handle_structured_sms(
                            survey_keyword,
                            survey_keyword_action,
                            case,
                            None,
                            "DEVICE_EVENT,%s" % data,
                            send_response=False,
                        )
                        event.processed = True
                        event.save()
                        break

    return HttpResponse("")
コード例 #2
0
def handle_domain_keywords(v, text, msg, text_words, sessions):
    any_session_open = len(sessions) > 0
    for survey_keyword in SurveyKeyword.get_all(v.domain):
        args = split_args(text, survey_keyword)
        keyword = args[0].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 not contact_can_use_keyword(v, survey_keyword):
                # The contact type is not allowed to invoke this keyword
                return False
            else:
                inbound_metadata = MessageMetadata(workflow=WORKFLOW_KEYWORD, )
                add_msg_tags(msg, inbound_metadata)
                process_survey_keyword_actions(v, survey_keyword, text, msg)
                return True
    # No keywords matched, so pass the message onto the next handler
    return False
コード例 #3
0
ファイル: keyword.py プロジェクト: johan--/commcare-hq
def handle_domain_keywords(v, text, msg, text_words, sessions):
    any_session_open = len(sessions) > 0
    for survey_keyword in SurveyKeyword.get_all(v.domain):
        args = split_args(text, survey_keyword)
        keyword = args[0].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 not contact_can_use_keyword(v, survey_keyword):
                # The contact type is not allowed to invoke this keyword
                return False
            else:
                inbound_metadata = MessageMetadata(
                    workflow=WORKFLOW_KEYWORD,
                )
                add_msg_tags(msg, inbound_metadata)
                process_survey_keyword_actions(v, survey_keyword, text, msg)
                return True
    # No keywords matched, so pass the message onto the next handler
    return False
コード例 #4
0
def structured_sms_handler(verified_number, text):

    # Circular Import
    from corehq.apps.reminders.models import SurveyKeyword, FORM_TYPE_ALL_AT_ONCE

    text = text.strip()
    if text == "":
        return False
    for survey_keyword in SurveyKeyword.get_all(verified_number.domain):
        if survey_keyword.form_type == FORM_TYPE_ALL_AT_ONCE:
            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():
                continue

            try:
                error_occurred = False
                error_msg = ""
                form_complete = False

                # Close any open sessions
                close_open_sessions(verified_number.domain, verified_number.owner_id)

                # Start the session
                form = Form.get_form(survey_keyword.form_unique_id)
                app = form.get_app()
                module = form.get_module()

                if verified_number.owner_doc_type == "CommCareCase":
                    case_id = verified_number.owner_id
                else:
                    # TODO: Need a way to choose the case when it's a user that's playing the form
                    case_id = None

                session, responses = start_session(
                    verified_number.domain,
                    verified_number.owner,
                    app,
                    module,
                    form,
                    case_id=case_id,
                    yield_responses=True,
                )
                assert len(responses) > 0, "There should be at least one response."

                current_question = responses[-1]
                form_complete = is_form_complete(current_question)

                if not form_complete:
                    if survey_keyword.use_named_args:
                        # Arguments in the sms are named
                        xpath_answer = {}  # Dictionary of {xpath : answer}
                        for answer in args[1:]:
                            answer = answer.strip()
                            answer_upper = answer.upper()
                            if survey_keyword.named_args_separator is not None:
                                # A separator is used for naming arguments; for example, the "=" in "register name=joe age=25"
                                answer_parts = answer.partition(survey_keyword.named_args_separator)
                                if answer_parts[1] != survey_keyword.named_args_separator:
                                    error_occurred = True
                                    error_msg = "ERROR: Expected name and value to be joined by" + (
                                        " '%s'" % survey_keyword.named_args_separator
                                    )
                                    break
                                else:
                                    arg_name = answer_parts[0].upper().strip()
                                    xpath = survey_keyword.named_args.get(arg_name, None)
                                    if xpath is not None:
                                        if xpath in xpath_answer:
                                            error_occurred = True
                                            error_msg = "ERROR: More than one answer found for" + (" '%s'" % arg_name)
                                            break

                                        xpath_answer[xpath] = answer_parts[2].strip()
                                    else:
                                        # Ignore unexpected named arguments
                                        pass
                            else:
                                # No separator is used for naming arguments; for example, "update a100 b34 c5"
                                matches = 0
                                for k, v in survey_keyword.named_args.items():
                                    if answer_upper.startswith(k):
                                        matches += 1
                                        if matches > 1:
                                            error_occurred = True
                                            error_msg = "ERROR: More than one question matches" + (" '%s'" % answer)
                                            break

                                        if v in xpath_answer:
                                            error_occurred = True
                                            error_msg = "ERROR: More than one answer found for" + (" '%s'" % k)
                                            break

                                        xpath_answer[v] = answer[len(k) :].strip()

                                if matches == 0:
                                    # Ignore unexpected named arguments
                                    pass

                            if error_occurred:
                                break

                        # Go through each question in the form, answering only the questions that the sms has answers for
                        while not form_complete and not error_occurred:
                            if current_question.is_error:
                                error_occurred = True
                                error_msg = current_question.text_prompt or "ERROR: Internal server error"
                                break

                            xpath = current_question.event._dict["binding"]
                            if xpath in xpath_answer:
                                valid, answer, _error_msg = validate_answer(current_question.event, xpath_answer[xpath])
                                if not valid:
                                    error_occurred = True
                                    error_msg = "ERROR: " + _error_msg
                                    break
                                responses = _get_responses(
                                    verified_number.domain, verified_number.owner_id, answer, yield_responses=True
                                )
                            else:
                                responses = _get_responses(
                                    verified_number.domain, verified_number.owner_id, "", yield_responses=True
                                )

                            current_question = responses[-1]
                            if is_form_complete(current_question):
                                form_complete = True
                    else:
                        # Arguments in the sms are not named; pass each argument to each question in order
                        for answer in args[1:]:
                            if form_complete:
                                # Form is complete, ignore remaining answers
                                break

                            if current_question.is_error:
                                error_occurred = True
                                error_msg = current_question.text_prompt or "ERROR: Internal server error"
                                break

                            valid, answer, _error_msg = validate_answer(current_question.event, answer.strip())
                            if not valid:
                                error_occurred = True
                                error_msg = "ERROR: " + _error_msg
                                break

                            responses = _get_responses(
                                verified_number.domain, verified_number.owner_id, answer, yield_responses=True
                            )
                            current_question = responses[-1]
                            form_complete = is_form_complete(current_question)

                        # If the form isn't finished yet but we're out of arguments, try to leave each remaining question blank and continue
                        while not form_complete and not error_occurred:
                            responses = _get_responses(
                                verified_number.domain, verified_number.owner_id, "", yield_responses=True
                            )
                            current_question = responses[-1]

                            if current_question.is_error:
                                error_occurred = True
                                error_msg = current_question.text_prompt or "ERROR: Internal server error"

                            if is_form_complete(current_question):
                                form_complete = True
            except Exception:
                logging.exception(
                    "Could not process structured sms for verified number %s, domain %s, keyword %s"
                    % (verified_number._id, verified_number.domain, keyword)
                )
                error_occurred = True
                error_msg = "ERROR: Internal server error"

            if error_occurred:
                send_sms_to_verified_number(verified_number, error_msg)

            if error_occurred or not form_complete:
                session = XFormsSession.get(session._id)
                session.end(False)
                session.save()

            return True

    return False
コード例 #5
0
ファイル: views.py プロジェクト: mchampanis/core-hq
def manage_surveys(request, domain):
    context = {
        "domain" : domain,
        "keywords" : SurveyKeyword.get_all(domain)
    }
    return render_to_response(request, "reminders/partial/manage_surveys.html", context)
コード例 #6
0
ファイル: api.py プロジェクト: pawelreise/commcare-hq
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
コード例 #7
0
ファイル: views.py プロジェクト: tsinkala/commcare-hq
def manage_keywords(request, domain):
    context = {"domain": domain, "keywords": SurveyKeyword.get_all(domain)}
    return render(request, "reminders/partial/manage_keywords.html", context)
コード例 #8
0
ファイル: api.py プロジェクト: tsinkala/commcare-hq
def structured_sms_handler(verified_number, text):

    # Circular Import
    from corehq.apps.reminders.models import SurveyKeyword, FORM_TYPE_ALL_AT_ONCE

    text = text.strip()
    if text == "":
        return False
    for survey_keyword in SurveyKeyword.get_all(verified_number.domain):
        if survey_keyword.form_type == FORM_TYPE_ALL_AT_ONCE:
            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():
                continue

            try:
                error_occurred = False
                error_msg = ""
                form_complete = False

                # Close any open sessions
                close_open_sessions(verified_number.domain,
                                    verified_number.owner_id)

                # Start the session
                form = Form.get_form(survey_keyword.form_unique_id)
                app = form.get_app()
                module = form.get_module()

                if verified_number.owner_doc_type == "CommCareCase":
                    case_id = verified_number.owner_id
                else:
                    #TODO: Need a way to choose the case when it's a user that's playing the form
                    case_id = None

                session, responses = start_session(verified_number.domain,
                                                   verified_number.owner,
                                                   app,
                                                   module,
                                                   form,
                                                   case_id=case_id,
                                                   yield_responses=True)
                assert len(
                    responses) > 0, "There should be at least one response."

                current_question = responses[-1]
                form_complete = is_form_complete(current_question)

                if not form_complete:
                    if survey_keyword.use_named_args:
                        # Arguments in the sms are named
                        xpath_answer = {}  # Dictionary of {xpath : answer}
                        for answer in args[1:]:
                            answer = answer.strip()
                            answer_upper = answer.upper()
                            if survey_keyword.named_args_separator is not None:
                                # A separator is used for naming arguments; for example, the "=" in "register name=joe age=25"
                                answer_parts = answer.partition(
                                    survey_keyword.named_args_separator)
                                if answer_parts[
                                        1] != survey_keyword.named_args_separator:
                                    error_occurred = True
                                    error_msg = "ERROR: Expected name and value to be joined by" + (
                                        " '%s'" %
                                        survey_keyword.named_args_separator)
                                    break
                                else:
                                    arg_name = answer_parts[0].upper().strip()
                                    xpath = survey_keyword.named_args.get(
                                        arg_name, None)
                                    if xpath is not None:
                                        if xpath in xpath_answer:
                                            error_occurred = True
                                            error_msg = "ERROR: More than one answer found for" + (
                                                " '%s'" % arg_name)
                                            break

                                        xpath_answer[xpath] = answer_parts[
                                            2].strip()
                                    else:
                                        # Ignore unexpected named arguments
                                        pass
                            else:
                                # No separator is used for naming arguments; for example, "update a100 b34 c5"
                                matches = 0
                                for k, v in survey_keyword.named_args.items():
                                    if answer_upper.startswith(k):
                                        matches += 1
                                        if matches > 1:
                                            error_occurred = True
                                            error_msg = "ERROR: More than one question matches" + (
                                                " '%s'" % answer)
                                            break

                                        if v in xpath_answer:
                                            error_occurred = True
                                            error_msg = "ERROR: More than one answer found for" + (
                                                " '%s'" % k)
                                            break

                                        xpath_answer[v] = answer[
                                            len(k):].strip()

                                if matches == 0:
                                    # Ignore unexpected named arguments
                                    pass

                            if error_occurred:
                                break

                        # Go through each question in the form, answering only the questions that the sms has answers for
                        while not form_complete and not error_occurred:
                            if current_question.is_error:
                                error_occurred = True
                                error_msg = current_question.text_prompt or "ERROR: Internal server error"
                                break

                            xpath = current_question.event._dict["binding"]
                            if xpath in xpath_answer:
                                valid, answer, _error_msg = validate_answer(
                                    current_question.event,
                                    xpath_answer[xpath])
                                if not valid:
                                    error_occurred = True
                                    error_msg = "ERROR: " + _error_msg
                                    break
                                responses = _get_responses(
                                    verified_number.domain,
                                    verified_number.owner_id,
                                    answer,
                                    yield_responses=True)
                            else:
                                responses = _get_responses(
                                    verified_number.domain,
                                    verified_number.owner_id,
                                    "",
                                    yield_responses=True)

                            current_question = responses[-1]
                            if is_form_complete(current_question):
                                form_complete = True
                    else:
                        # Arguments in the sms are not named; pass each argument to each question in order
                        for answer in args[1:]:
                            if form_complete:
                                # Form is complete, ignore remaining answers
                                break

                            if current_question.is_error:
                                error_occurred = True
                                error_msg = current_question.text_prompt or "ERROR: Internal server error"
                                break

                            valid, answer, _error_msg = validate_answer(
                                current_question.event, answer.strip())
                            if not valid:
                                error_occurred = True
                                error_msg = "ERROR: " + _error_msg
                                break

                            responses = _get_responses(
                                verified_number.domain,
                                verified_number.owner_id,
                                answer,
                                yield_responses=True)
                            current_question = responses[-1]
                            form_complete = is_form_complete(current_question)

                        # If the form isn't finished yet but we're out of arguments, try to leave each remaining question blank and continue
                        while not form_complete and not error_occurred:
                            responses = _get_responses(
                                verified_number.domain,
                                verified_number.owner_id,
                                "",
                                yield_responses=True)
                            current_question = responses[-1]

                            if current_question.is_error:
                                error_occurred = True
                                error_msg = current_question.text_prompt or "ERROR: Internal server error"

                            if is_form_complete(current_question):
                                form_complete = True
            except Exception:
                logging.exception(
                    "Could not process structured sms for verified number %s, domain %s, keyword %s"
                    % (verified_number._id, verified_number.domain, keyword))
                error_occurred = True
                error_msg = "ERROR: Internal server error"

            if error_occurred:
                send_sms_to_verified_number(verified_number, error_msg)

            if error_occurred or not form_complete:
                session = XFormsSession.get(session._id)
                session.end(False)
                session.save()

            return True

    return False
コード例 #9
0
    def deleteAllObjects(self):
        for obj in SurveyKeyword.get_all(self.domain):
            obj.delete()

        Keyword.objects.filter(domain=self.domain).delete()