예제 #1
0
def process_incoming_smses(username, incomings, id_string=None):
    ''' Process Incoming (identity, text[, id_string]) SMS '''

    xforms = []
    medias = []
    xforms_notes = []
    responses = []
    json_submissions = []
    resp_str = {
        'success':
        _(u"[SUCCESS] Your submission has been accepted. "
          u"It's ID is {{ id }}.")
    }

    def process_incoming(incoming, id_string):
        # assign variables
        if len(incoming) >= 2:
            identity = incoming[0].strip().lower()
            text = incoming[1].strip().lower()
            # if the tuple contain an id_string, use it, otherwise default
            if len(incoming) and id_string is None >= 3:
                id_string = incoming[2]
        else:
            responses.append({
                'code':
                SMS_API_ERROR,
                'text':
                _(u"Missing 'identity' "
                  u"or 'text' field.")
            })
            return

        if not len(identity.strip()) or not len(text.strip()):
            responses.append({
                'code':
                SMS_API_ERROR,
                'text':
                _(u"'identity' and 'text' fields can "
                  u"not be empty.")
            })
            return

        # if no id_string has been supplied
        # we expect the SMS to be prefixed with the form's sms_id_string
        if id_string is None:
            keyword, text = [s.strip() for s in text.split(None, 1)]
            xform = XForm.objects.get(user__username=username,
                                      sms_id_string=keyword)
        else:
            xform = XForm.objects.get(user__username=username,
                                      id_string=id_string)

        if not xform.allows_sms:
            responses.append({
                'code': SMS_SUBMISSION_REFUSED,
                'text': _(u"The form '%(id_string)s' does not "
                          u"accept SMS submissions.") % {
                              'id_string': xform.id_string
                          }
            })
            return

        # parse text into a dict object of groups with values
        json_submission, medias_submission, notes = parse_sms_text(
            xform, identity, text)

        # retrieve sms_response if exist in the form.
        json_survey = json.loads(xform.json)
        if json_survey.get('sms_response'):
            resp_str.update({'success': json_survey.get('sms_response')})

        # check that the form contains at least one filled group
        meta_groups = sum(
            [1 for k in json_submission.keys() if k.startswith('meta')])
        if len(json_submission.keys()) <= meta_groups:
            responses.append({
                'code':
                SMS_PARSING_ERROR,
                'text':
                _(u"There must be at least one group of "
                  u"questions filled.")
            })
            return

        # check that required fields have been filled
        required_fields = [
            f.get('name') for g in json_survey.get('children', {})
            for f in g.get('children', {})
            if f.get('bind', {}).get('required', 'no') == 'yes'
        ]
        submitted_fields = {}
        for group in json_submission.values():
            submitted_fields.update(group)

        for field in required_fields:
            if not submitted_fields.get(field):
                responses.append({
                    'code': SMS_SUBMISSION_REFUSED,
                    'text': _(u"Required field `%(field)s` is  "
                              u"missing.") % {
                                  'field': field
                              }
                })
                return

        # convert dict object into an XForm string
        xml_submission = dict2xform(jsform=json_submission,
                                    form_id=xform.id_string)

        # compute notes
        data = {}
        for g in json_submission.values():
            data.update(g)
        for idx, note in enumerate(notes):
            try:
                notes[idx] = note.replace('${', '{').format(**data)
            except:
                pass

        # process_incoming expectes submission to be a file-like object
        xforms.append(StringIO.StringIO(xml_submission))
        medias.append(medias_submission)
        json_submissions.append(json_submission)
        xforms_notes.append(notes)

    for incoming in incomings:
        try:
            process_incoming(incoming, id_string)
        except Exception as e:
            responses.append({'code': SMS_PARSING_ERROR, 'text': str(e)})

    for idx, xform in enumerate(xforms):
        # generate_instance expects media as a request.FILES.values() list
        xform_medias = [sms_media_to_file(f, n) for n, f in medias[idx]]
        # create the instance in the data base
        response = generate_instance(username=username,
                                     xml_file=xform,
                                     media_files=xform_medias)
        if response.get('code') == SMS_SUBMISSION_ACCEPTED:
            success_response = re.sub(r'{{\s*[i,d,I,D]{2}\s*}}',
                                      response.get('id'),
                                      resp_str.get('success'), re.I)

            # extend success_response with data from the answers
            data = {}
            for g in json_submissions[idx].values():
                data.update(g)
            success_response = success_response.replace('${',
                                                        '{').format(**data)
            response.update({'text': success_response})
            # add sendouts (notes)
            response.update({'sendouts': xforms_notes[idx]})
        responses.append(response)

    return responses
예제 #2
0
파일: parser.py 프로젝트: cagulas/onadata
def process_incoming_smses(username, incomings,
                           id_string=None):
    ''' Process Incoming (identity, text[, id_string]) SMS '''

    xforms = []
    medias = []
    responses = []
    json_submissions = []
    resp_str = {'success': _(u"[SUCCESS] Your submission has been accepted. "
                             u"It's ID is {{ id }}.")}

    def process_incoming(incoming, id_string):
        # assign variables
        if len(incoming) >= 2:
            identity = incoming[0].strip().lower()
            text = incoming[1].strip().lower()
            # if the tuple contain an id_string, use it, otherwise default
            if len(incoming) and id_string is None >= 3:
                id_string = incoming[2]
        else:
            responses.append({'code': SMS_API_ERROR,
                              'text': _(u"Missing 'identity' "
                                        u"or 'text' field.")})
            return

        if not len(identity.strip()) or not len(text.strip()):
            responses.append({'code': SMS_API_ERROR,
                              'text': _(u"'identity' and 'text' fields can "
                                        u"not be empty.")})
            return

        # if no id_string has been supplied
        # we expect the SMS to be prefixed with the form's sms_id_string
        if id_string is None:
            keyword, text = [s.strip() for s in text.split(None, 1)]
            xform = XForm.objects.get(user__username=username,
                                      sms_id_string=keyword)
        else:
            xform = XForm.objects.get(user__username=username,
                                      id_string=id_string)

        if not xform.allows_sms:
            responses.append({'code': SMS_SUBMISSION_REFUSED,
                              'text': _(u"The form '%(id_string)s' does not "
                                        u"accept SMS submissions.")
                             % {'id_string': xform.id_string}})
            return

        # parse text into a dict object of groups with values
        json_submission, medias_submission = parse_sms_text(xform,
                                                            identity, text)

        # retrieve sms_response if exist in the form.
        json_survey = json.loads(xform.json)
        if json_survey.get('sms_response'):
            resp_str.update({'success': json_survey.get('sms_response')})

        # check that the form contains at least one filled group
        meta_groups = sum([1 for k in json_submission.keys()
                           if k.startswith('meta')])
        if len(json_submission.keys()) <= meta_groups:
            responses.append({'code': SMS_PARSING_ERROR,
                              'text': _(u"There must be at least one group of "
                                        u"questions filled.")})
            return

        # check that required fields have been filled
        required_fields = [f.get('name')
                           for g in json_survey.get('children', {})
                           for f in g.get('children', {})
                           if f.get('bind', {}).get('required', 'no') == 'yes']
        submitted_fields = {}
        for group in json_submission.values():
            submitted_fields.update(group)

        for field in required_fields:
            if not submitted_fields.get(field):
                responses.append({'code': SMS_SUBMISSION_REFUSED,
                                  'text': _(u"Required field `%(field)s` is  "
                                            u"missing.") % {'field': field}})
                return

        # convert dict object into an XForm string
        xml_submission = json2xform(jsform=json_submission,
                                    form_id=xform.id_string)

        # process_incoming expectes submission to be a file-like object
        xforms.append(StringIO.StringIO(xml_submission))
        medias.append(medias_submission)
        json_submissions.append(json_submission)

    for incoming in incomings:
        try:
            process_incoming(incoming, id_string)
        except Exception as e:
            responses.append({'code': SMS_PARSING_ERROR, 'text': str(e)})

    for idx, xform in enumerate(xforms):
        # generate_instance expects media as a request.FILES.values() list
        xform_medias = [sms_media_to_file(f, n) for n, f in medias[idx]]
        # create the instance in the data base
        response = generate_instance(username=username,
                                     xml_file=xform,
                                     media_files=xform_medias)
        if response.get('code') == SMS_SUBMISSION_ACCEPTED:
            success_response = re.sub(r'{{\s*[i,d,I,D]{2}\s*}}',
                                      response.get('id'),
                                      resp_str.get('success'), re.I)

            # extend success_response with data from the answers
            data = {}
            for g in json_submissions[idx].values():
                data.update(g)
            success_response = success_response.replace('${',
                                                        '{').format(**data)
            response.update({'text': success_response})
        responses.append(response)

    return responses