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
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