コード例 #1
0
ファイル: migration.py プロジェクト: ekush/commcare-hq
    def testSMSLogSync(self):
        prev_couch_count = self.getSMSLogCount()
        prev_sql_count = self.getSMSCount()

        # Test Create
        smslog = SMSLog()
        self.setRandomSMSLogValues(smslog)
        smslog.save()

        sleep(1)
        self.assertEqual(self.getSMSLogCount(), prev_couch_count + 1)
        self.assertEqual(self.getSMSCount(), prev_sql_count + 1)

        sms = SMS.objects.get(couch_id=smslog._id)
        self.checkFieldValues(smslog, sms, SMSLog._migration_get_fields())
        self.assertTrue(SMSLog.get_db().get_rev(smslog._id).startswith('1-'))

        # Test Update
        self.setRandomSMSLogValues(smslog)
        smslog.save()

        sleep(1)
        self.assertEqual(self.getSMSLogCount(), prev_couch_count + 1)
        self.assertEqual(self.getSMSCount(), prev_sql_count + 1)
        sms = SMS.objects.get(couch_id=smslog._id)
        self.checkFieldValues(smslog, sms, SMSLog._migration_get_fields())
        self.assertTrue(SMSLog.get_db().get_rev(smslog._id).startswith('2-'))
コード例 #2
0
ファイル: views.py プロジェクト: tsinkala/commcare-hq
def post(request, domain):
    # TODO: Figure out if this is being used anywhere and remove it if not
    """
    We assume sms sent to HQ will come in the form
    http://hqurl.com?username=%(username)s&password=%(password)s&id=%(phone_number)s&text=%(message)s
    """
    text = request.REQUEST.get('text', '')
    to = request.REQUEST.get('id', '')
    username = request.REQUEST.get('username', '')
    # ah, plaintext passwords....
    # this seems to be the most common API that a lot of SMS gateways expose
    password = request.REQUEST.get('password', '')
    if not text or not to or not username or not password:
        error_msg = 'ERROR missing parameters. Received: %(1)s, %(2)s, %(3)s, %(4)s' % \
                     ( text, to, username, password )
        logging.error(error_msg)
        return HttpResponseBadRequest(error_msg)
    user = authenticate(username=username, password=password)
    if user is None or not user.is_active:
        return HttpResponseBadRequest("Authentication fail")
    msg = SMSLog(
        domain=domain,
        # TODO: how to map phone numbers to recipients, when phone numbers are shared?
        #couch_recipient=id,
        phone_number=to,
        direction=INCOMING,
        date=datetime.now(),
        text=text)
    msg.save()
    return HttpResponse('OK')
コード例 #3
0
ファイル: migration.py プロジェクト: ansarbek/commcare-hq
    def testSMSLogSync(self):
        self.deleteAllLogs()
        self.assertEqual(self.getSMSLogCount(), 0)
        self.assertEqual(self.getSMSCount(), 0)

        # Test Create
        smslog = SMSLog()
        self.setRandomSMSLogValues(smslog)
        smslog.save()

        sleep(1)
        self.assertEqual(self.getSMSLogCount(), 1)
        self.assertEqual(self.getSMSCount(), 1)

        sms = SMS.objects.get(couch_id=smslog._id)
        self.checkFieldValues(smslog, sms, SMSLog._migration_get_fields())
        self.assertTrue(SMSLog.get_db().get_rev(smslog._id).startswith('1-'))

        # Test Update
        self.setRandomSMSLogValues(smslog)
        smslog.save()

        sleep(1)
        self.assertEqual(self.getSMSLogCount(), 1)
        self.assertEqual(self.getSMSCount(), 1)
        sms = SMS.objects.get(couch_id=smslog._id)
        self.checkFieldValues(smslog, sms, SMSLog._migration_get_fields())
        self.assertTrue(SMSLog.get_db().get_rev(smslog._id).startswith('2-'))
コード例 #4
0
ファイル: api.py プロジェクト: modonnell729/commcare-hq
def incoming(phone_number, text, backend_api, timestamp=None, domain_scope=None, backend_message_id=None, delay=True):
    """
    entry point for incoming sms

    phone_number - originating phone number
    text - message content
    backend_api - backend API ID of receiving sms backend
    timestamp - message received timestamp; defaults to now (UTC)
    domain_scope - if present, only messages from phone numbers that can be
      definitively linked to this domain will be processed; others will be
      dropped (useful to provide security when simulating incoming sms)
    """
    # Log message in message log
    phone_number = clean_phone_number(phone_number)
    msg = SMSLog(
        phone_number = phone_number,
        direction = INCOMING,
        date = timestamp or datetime.utcnow(),
        text = text,
        domain_scope = domain_scope,
        backend_api = backend_api,
        backend_message_id = backend_message_id,
    )
    if settings.SMS_QUEUE_ENABLED:
        msg.processed = False
        msg.datetime_to_process = datetime.utcnow()
        msg.queued_timestamp = msg.datetime_to_process
        msg.save()
        enqueue_directly(msg)
    else:
        msg.processed = True
        msg.save()
        process_incoming(msg, delay=delay)
    return msg
コード例 #5
0
ファイル: api.py プロジェクト: mchampanis/core-hq
def send_sms_to_verified_number(verified_number, text):
    """
    Sends an sms using the given verified phone number entry.
    
    verified_number The VerifiedNumber entry to use when sending.
    text            The text of the message to send.
    
    return  True on success, False on failure
    """
    try:
        backend = verified_number.backend
        module = __import__(backend.outbound_module, fromlist=["send"])
        kwargs = backend.outbound_params
        msg = SMSLog(
            couch_recipient_doc_type    = verified_number.owner_doc_type,
            couch_recipient             = verified_number.owner_id,
            phone_number                = "+" + str(verified_number.phone_number),
            direction                   = OUTGOING,
            date                        = datetime.utcnow(),
            domain                      = verified_number.domain,
            text                        = text
        )
        try:
            msg.backend_api = module.API_ID
        except Exception:
            pass
        module.send(msg, **kwargs)
        msg.save()
        return True
    except Exception as e:
        logging.exception("Exception while sending SMS to VerifiedNumber id " + verified_number._id)
        return False
コード例 #6
0
ファイル: api.py プロジェクト: mchampanis/core-hq
def send_sms(domain, id, phone_number, text):
    """
    Sends an outbound SMS. Returns false if it fails.
    """
    if phone_number is None:
        return False
    if isinstance(phone_number, int) or isinstance(phone_number, long):
        phone_number = str(phone_number)
    logging.debug('Sending message: %s' % text)
    phone_number = clean_phone_number(phone_number)
    msg = SMSLog(domain=domain,
                     couch_recipient=id, 
                     couch_recipient_doc_type="CouchUser",
                     phone_number=phone_number,
                     direction=OUTGOING,
                     date = datetime.utcnow(),
                     text = text)
    try:
        api = get_backend_api(msg)
        try:
            msg.backend_api = api.API_ID
        except Exception:
            pass
        api.send(msg)
        msg.save()
        return True
    except Exception:
        logging.exception("Problem sending SMS to %s" % phone_number)
        return False
コード例 #7
0
ファイル: views.py プロジェクト: kennknowles/commcare-hq
def post(request, domain):
    # TODO: Figure out if this is being used anywhere and remove it if not
    """
    We assume sms sent to HQ will come in the form
    http://hqurl.com?username=%(username)s&password=%(password)s&id=%(phone_number)s&text=%(message)s
    """
    text = request.REQUEST.get('text', '')
    to = request.REQUEST.get('id', '')
    username = request.REQUEST.get('username', '')
    # ah, plaintext passwords....  
    # this seems to be the most common API that a lot of SMS gateways expose
    password = request.REQUEST.get('password', '')
    if not text or not to or not username or not password:
        error_msg = 'ERROR missing parameters. Received: %(1)s, %(2)s, %(3)s, %(4)s' % \
                     ( text, to, username, password )
        logging.error(error_msg)
        return HttpResponseBadRequest(error_msg)
    user = authenticate(username=username, password=password)
    if user is None or not user.is_active:
        return HttpResponseBadRequest("Authentication fail")
    msg = SMSLog(domain=domain,
                 # TODO: how to map phone numbers to recipients, when phone numbers are shared?
                 #couch_recipient=id, 
                 phone_number=to,
                 direction=INCOMING,
                 date = datetime.now(),
                 text = text)
    msg.save()
    return HttpResponse('OK')     
コード例 #8
0
def incoming(phone_number, text, backend_api, timestamp=None, domain_scope=None, delay=True):
    """
    entry point for incoming sms

    phone_number - originating phone number
    text - message content
    backend_api - backend ID of receiving sms backend
    timestamp - message received timestamp; defaults to now (UTC)
    domain_scope - if present, only messages from phone numbers that can be
      definitively linked to this domain will be processed; others will be
      dropped (useful to provide security when simulating incoming sms)
    """
    phone_number = clean_phone_number(phone_number)
    v = VerifiedNumber.by_phone(phone_number, include_pending=True)
    if domain_scope:
        # only process messages for phones known to be associated with this domain
        if v is None or v.domain != domain_scope:
            raise RuntimeError("attempted to simulate incoming sms from phone number not verified with this domain")

    # Log message in message log
    msg = SMSLog(
        phone_number=phone_number,
        direction=INCOMING,
        date=timestamp or datetime.utcnow(),
        text=text,
        backend_api=backend_api,
    )
    if v is not None and v.verified:
        msg.couch_recipient_doc_type = v.owner_doc_type
        msg.couch_recipient = v.owner_id
        msg.domain = v.domain
    msg.save()

    create_billable_for_sms(msg, backend_api, delay=delay)

    if v is not None and v.verified:
        for h in settings.SMS_HANDLERS:
            try:
                handler = to_function(h)
            except:
                logging.exception("error loading sms handler: %s" % h)
                continue

            try:
                was_handled = handler(v, text)
            except:
                logging.exception("unhandled error in sms handler %s for message [%s]" % (h, text))
                was_handled = False

            if was_handled:
                break
    else:
        if not process_sms_registration(msg):
            import verify

            verify.process_verification(phone_number, text)

    return msg
コード例 #9
0
 def _get_fake_sms(self, text):
     msg = SMSLog(domain=self.domain,
                  phone_number='+16175555454',
                  direction=OUTGOING,
                  date=datetime.utcnow(),
                  backend_id=self.mobile_backend.get_id,
                  text=text)
     msg.save()
     return msg
コード例 #10
0
ファイル: test_backends.py プロジェクト: ansarbek/commcare-hq
 def create_outgoing_sms(self, backend):
     sms = SMSLog(
         domain=self.domain,
         date=datetime.utcnow(),
         direction='O',
         phone_number='9991234567',
         text='message',
         backend_id=backend.couch_id
     )
     sms.save()
     return sms
コード例 #11
0
 def _get_fake_sms(self, text):
     msg = SMSLog(
         domain=self.domain,
         phone_number='+16175555454',
         direction=OUTGOING,
         date=datetime.utcnow(),
         backend_id=self.mobile_backend.get_id,
         text=text
     )
     msg.save()
     return msg
コード例 #12
0
ファイル: utils.py プロジェクト: ekush/commcare-hq
def send_test_message(verified_number, text, metadata=None):
    msg = SMSLog(couch_recipient_doc_type=verified_number.owner_doc_type,
                 couch_recipient=verified_number.owner_id,
                 phone_number="+" + str(verified_number.phone_number),
                 direction=OUTGOING,
                 date=datetime.utcnow(),
                 domain=verified_number.domain,
                 text=text,
                 processed=True,
                 datetime_to_process=datetime.utcnow(),
                 queued_timestamp=datetime.utcnow())
    msg.save()
    add_msg_tags(msg, metadata)
    return True
コード例 #13
0
ファイル: api.py プロジェクト: ekush/commcare-hq
def incoming(phone_number,
             text,
             backend_api,
             timestamp=None,
             domain_scope=None,
             backend_message_id=None,
             delay=True,
             backend_attributes=None,
             raw_text=None):
    """
    entry point for incoming sms

    phone_number - originating phone number
    text - message content
    backend_api - backend API ID of receiving sms backend
    timestamp - message received timestamp; defaults to now (UTC)
    domain_scope - if present, only messages from phone numbers that can be
      definitively linked to this domain will be processed; others will be
      dropped (useful to provide security when simulating incoming sms)
    """
    # Log message in message log
    if text is None:
        text = ""
    phone_number = clean_phone_number(phone_number)
    msg = SMSLog(
        phone_number=phone_number,
        direction=INCOMING,
        date=timestamp or datetime.utcnow(),
        text=text,
        domain_scope=domain_scope,
        backend_api=backend_api,
        backend_message_id=backend_message_id,
        raw_text=raw_text,
    )
    if backend_attributes:
        for k, v in backend_attributes.items():
            setattr(msg, k, v)
    if settings.SMS_QUEUE_ENABLED:
        msg.processed = False
        msg.datetime_to_process = datetime.utcnow()
        msg.queued_timestamp = msg.datetime_to_process
        msg.save()
        enqueue_directly(msg)
    else:
        msg.processed = True
        msg.save()
        process_incoming(msg, delay=delay)
    return msg
コード例 #14
0
ファイル: utils.py プロジェクト: johan--/commcare-hq
def send_test_message(verified_number, text, metadata=None):
    msg = SMSLog(
        couch_recipient_doc_type=verified_number.owner_doc_type,
        couch_recipient=verified_number.owner_id,
        phone_number="+" + str(verified_number.phone_number),
        direction=OUTGOING,
        date=datetime.utcnow(),
        domain=verified_number.domain,
        text=text,
        processed=True,
        datetime_to_process=datetime.utcnow(),
        queued_timestamp=datetime.utcnow(),
    )
    msg.save()
    add_msg_tags(msg, metadata)
    return True
コード例 #15
0
ファイル: api.py プロジェクト: mchampanis/core-hq
def create_from_request(request, delay=True):
    """
    From an inbound request (representing an incoming message), 
    create a message (log) object with the right fields populated.
    """
    sender = request.REQUEST.get(InboundParams.SENDER, "")
    message = request.REQUEST.get(InboundParams.MESSAGE, "")
    timestamp = request.REQUEST.get(InboundParams.TIMESTAMP, "")
    # parse date or default to current utc time
    actual_timestamp = datetime.strptime(timestamp, DATE_FORMAT) \
                            if timestamp else datetime.utcnow()
    
    # not sure yet if this check is valid
    is_unicode = request.REQUEST.get(InboundParams.UDHI, "") == "1"
    if is_unicode:
        message = message.decode("hex").decode("utf_16_be")
    # if you don't have an exact match for either of these fields, save nothing
    domains = domains_for_phone(sender)
    domain = domains[0] if len(domains) == 1 else "" 
    recipients = users_for_phone(sender)
    recipient = recipients[0].get_id if len(recipients) == 1 else "" 
    
    log = SMSLog(couch_recipient=recipient,
                        couch_recipient_doc_type="CouchUser",
                        phone_number=sender,
                        direction=INCOMING,
                        date=actual_timestamp,
                        text=message,
                        domain=domain,
                        backend_api=API_ID)
    log.save()

    try:
        # attempt to bill client
        from hqbilling.tasks import bill_client_for_sms
        from hqbilling.models import UnicelSMSBillable
        if delay:
            bill_client_for_sms.delay(UnicelSMSBillable, log._id)
        else:
            bill_client_for_sms(UnicelSMSBillable, log._id)
    except Exception as e:
        logging.debug("UNICEL API contacted, errors in billing. Error: %s" % e)

    return log
コード例 #16
0
ファイル: generator.py プロジェクト: ekush/commcare-hq
def arbitrary_messages_by_backend_and_direction(backend_ids,
                                                phone_number=None,
                                                domain=None,
                                                directions=DIRECTIONS):
    phone_number = phone_number or TEST_NUMBER
    domain = domain or TEST_DOMAIN
    messages = []
    for api_id, instance_id in backend_ids.items():
        for direction in directions:
            sms_log = SMSLog(direction=direction,
                             phone_number=phone_number,
                             domain=domain,
                             backend_api=api_id,
                             backend_id=instance_id,
                             text=arbitrary_message(),
                             date=datetime.datetime.utcnow())
            sms_log.save()
            messages.append(sms_log)
    return messages
コード例 #17
0
ファイル: generator.py プロジェクト: NoahCarnahan/commcare-hq
def arbitrary_messages_by_backend_and_direction(backend_ids,
                                                phone_number=None,
                                                domain=None,
                                                directions=DIRECTIONS):
    phone_number = phone_number or TEST_NUMBER
    domain = domain or TEST_DOMAIN
    messages = []
    for api_id, instance_id in backend_ids.items():
        for direction in directions:
            sms_log = SMSLog(
                direction=direction,
                phone_number=phone_number,
                domain=domain,
                backend_api=api_id,
                backend_id=instance_id,
                text=arbitrary_message(),
                date=datetime.datetime.now()
            )
            sms_log.save()
            messages.append(sms_log)
    return messages
コード例 #18
0
ファイル: migration.py プロジェクト: bazuzi/commcare-hq
    def testFRISMSLogSync(self):
        prev_couch_count = self.getSMSLogCount()
        prev_sql_count = self.getSMSCount()

        # Test Create
        smslog = SMSLog()
        self.setRandomSMSLogValues(smslog)
        smslog.save()

        sleep(1)
        smslog = FRISMSLog.get(smslog._id)
        self.setRandomFRISMSLogValues(smslog)
        smslog.save()

        sleep(1)
        self.assertEqual(self.getSMSLogCount(), prev_couch_count + 1)
        self.assertEqual(self.getSMSCount(), prev_sql_count + 1)

        sms = SMS.objects.get(couch_id=smslog._id)
        self.checkFieldValues(smslog, sms, FRISMSLog._migration_get_fields())
        self.assertTrue(FRISMSLog.get_db().get_rev(smslog._id).startswith('2-'))

        # Test Update
        self.setRandomSMSLogValues(smslog)
        self.setRandomFRISMSLogValues(smslog)
        smslog.save()

        sleep(1)
        self.assertEqual(self.getSMSLogCount(), prev_couch_count + 1)
        self.assertEqual(self.getSMSCount(), prev_sql_count + 1)
        sms = SMS.objects.get(couch_id=smslog._id)
        self.checkFieldValues(smslog, sms, FRISMSLog._migration_get_fields())
        self.assertTrue(SMSLog.get_db().get_rev(smslog._id).startswith('3-'))
コード例 #19
0
ファイル: api.py プロジェクト: mchampanis/core-hq
def send_sms_with_backend(domain, phone_number, text, backend_id):
    msg = SMSLog(domain = domain,
                 phone_number = phone_number,
                 direction = OUTGOING,
                 date = datetime.utcnow(),
                 text = text)
    if backend_id == "MOBILE_BACKEND_MACH":
        try:
            try:
                msg.backend_api = mach_api.API_ID
            except Exception:
                pass
            mach_api.send(msg)
            msg.save()
            return True
        except Exception:
            logging.exception("Exception while sending SMS to %s with backend %s" % (phone_number, backend_id))
            return False
    elif backend_id == "MOBILE_BACKEND_UNICEL":
        try:
            try:
                msg.backend_api = unicel_api.API_ID
            except Exception:
                pass
            unicel_api.send(msg)
            msg.save()
            return True
        except Exception:
            logging.exception("Exception while sending SMS to %s with backend %s" % (phone_number, backend_id))
            return False
    else:
        try:
            backend = MobileBackend.get(backend_id)
        except Exception:
            backend = None
        if backend is None:
            return False
        
        try:
            module = __import__(backend.outbound_module, fromlist=["send"])
            try:
                msg.backend_api = module.API_ID
            except Exception:
                pass
            kwargs = backend.outbound_params
            module.send(msg, **kwargs)
            msg.save()
            return True
        except Exception as e:
            logging.exception("Exception while sending SMS to %s with backend %s" % (phone_number, backend_id))
            return False
コード例 #20
0
    def testOutgoingInternationalTropoApi(self):
        self.assertEqual(self.tropo_rate_any.conversion_rate, self.usd_rate.conversion)
        msg = SMSLog(domain = self.domain,
            direction = OUTGOING,
            date = datetime.datetime.utcnow(),
            text = self.test_message)
        msg.save()

        if self.sms_config and self.sms_config.get("tropo_int") and self.tropo_backend:
            logging.info("\n\n[Billing - LIVE] Tropo:  Outgoing International SMS Test")
            msg.phone_number = self.sms_config.get("tropo_int")
            msg.save()
            data = self.tropo_backend.send(msg, delay=False)
        else:
            logging.info("\n\n[Billing] Tropo: Outgoing International SMS Test")
            data = "<session><success>true</success><token>faketoken</token><id>aadfg3Aa321gdc8e628df2\n</id></session>"
            msg.phone_number = "+4915253271951"
            msg.save()
            bill_client_for_sms(TropoSMSBillable, msg.get_id, **dict(response=data))

        logging.info("[Billing] Response from TROPO: %s" % data)
        tropo_id = TropoSMSBillable.get_tropo_id(data)
        logging.info("[Billing] TROPO ID: %s" % tropo_id)

        billable_items = TropoSMSBillable.by_domain(self.domain)
        if billable_items:
            billable_item = billable_items[0]
            self.assertEqual(self.tropo_rate_any.base_fee,
                billable_item.billable_amount)
            self.assertEqual(self.tropo_rate_any._id, billable_item.rate_id)
            self.assertEqual(msg._id, billable_item.log_id)
            self.assertEqual(self.tropo_rate_any.conversion_rate, billable_item.conversion_rate)
            self.assertEqual(self.dimagi_surcharge.base_fee, billable_item.dimagi_surcharge)
            self.assertEqual(tropo_id, billable_item.tropo_id)
            billable_item.delete()
            if billable_item.has_error:
                raise Exception("There were recorded errors creating an outgoing International Tropo billing rate: %s" %
                                billable_item.error_message)
        else:
            raise Exception("There were unknown errors creating an outgoing International Tropo billing rate!")
コード例 #21
0
    def testOutgoingUnicelApi(self):
        self.assertEqual(self.unicel_rate.conversion_rate, self.usd_rate.conversion)
        msg = SMSLog(domain = self.domain,
            direction = OUTGOING,
            date = datetime.datetime.utcnow(),
            text = self.test_message)
        msg.save()

        if self.sms_config and self.sms_config.get("unicel") and self.unicel_backend:
            logging.info("\n\n[Billing - LIVE] UNICEL: Outgoing SMS Test.")
            msg.phone_number = self.sms_config.get("unicel")
            msg.save()
            data = self.unicel_backend.send(msg, delay=False)
        else:
            logging.info("\n\n[Billing] UNICEL: Outgoing SMS Test")
            data = "successful23541253235"
            msg.phone_number = "+555555555"
            msg.save()
            bill_client_for_sms(UnicelSMSBillable, msg.get_id, **dict(response=data))

        logging.info("Response from UNICEL: %s" % data)

        billable_items = UnicelSMSBillable.by_domain_and_direction(self.domain, OUTGOING)
        if billable_items:
            billable_item = billable_items[0]
            self.assertEqual(self.unicel_rate.base_fee * self.unicel_rate.conversion_rate,
                       billable_item.billable_amount)
            self.assertEqual(self.unicel_rate._id, billable_item.rate_id)
            self.assertEqual(msg._id, billable_item.log_id)
            self.assertEqual(self.unicel_rate.conversion_rate, billable_item.conversion_rate)
            self.assertEqual(self.dimagi_surcharge.base_fee, billable_item.dimagi_surcharge)
            self.assertEqual(data, billable_item.unicel_id)
            if billable_item.has_error:
                raise Exception("There were recorded errors creating an outgoing UNICEL billing rate: %s" %
                                billable_item.error_message)
        else:
            raise Exception("There were unknown errors creating an outgoing UNICEL billing rate!")
コード例 #22
0
ファイル: api.py プロジェクト: mchampanis/core-hq
def incoming(phone_number, text, backend_api):
    phone_without_plus = str(phone_number)
    if phone_without_plus[0] == "+":
        phone_without_plus = phone_without_plus[1:]
    phone_with_plus = "+" + phone_without_plus
    
    # Circular Import
    from corehq.apps.reminders.models import SurveyKeyword
    
    v = VerifiedNumber.view("sms/verified_number_by_number",
        key=phone_without_plus,
        include_docs=True
    ).one()
    
    # Log message in message log
    msg = SMSLog(
        phone_number    = phone_with_plus,
        direction       = INCOMING,
        date            = datetime.utcnow(),
        text            = text,
        backend_api     = backend_api
    )
    if v is not None:
        msg.couch_recipient_doc_type    = v.owner_doc_type
        msg.couch_recipient             = v.owner_id
        msg.domain                      = v.domain
    msg.save()
    
    # Handle incoming sms
    if v is not None:
        session = XFormsSession.view("smsforms/open_sessions_by_connection",
                                     key=[v.domain, v.owner_id],
                                     include_docs=True).one()
        
        text_words = text.upper().split()
        
        # Respond to "#START <keyword>" command
        if len(text_words) > 0 and text_words[0] == "#START":
            if len(text_words) > 1:
                sk = SurveyKeyword.get_keyword(v.domain, text_words[1])
                if sk is not None:
                    if session is not None:
                        session.end(False)
                        session.save()
                    start_session_from_keyword(sk, v)
                else:
                    send_sms_to_verified_number(v, "Survey '" + text_words[1] + "' not found.")
            else:
                send_sms_to_verified_number(v, "Usage: #START <keyword>")
        
        # Respond to "#STOP" keyword
        elif len(text_words) > 0 and text_words[0] == "#STOP":
            if session is not None:
                session.end(False)
                session.save()
        
        # Respond to "#CURRENT" keyword
        elif len(text_words) > 0 and text_words[0] == "#CURRENT":
            if session is not None:
                resp = current_question(session.session_id)
                send_sms_to_verified_number(v, resp.event.text_prompt)
        
        # Respond to unknown command
        elif len(text_words) > 0 and text_words[0][0] == "#":
            send_sms_to_verified_number(v, "Unknown command '" + text_words[0] + "'")
        
        # If there's an open session, treat the inbound text as the answer to the next question
        elif session is not None:
            resp = current_question(session.session_id)
            event = resp.event
            valid = False
            error_msg = None
            
            # Validate select questions
            if event.datatype == "select":
                try:
                    answer = int(text.strip())
                    if answer >= 1 and answer <= len(event._dict["choices"]):
                        valid = True
                except Exception:
                    pass
                if not valid:
                    error_msg = "Invalid Response. " + event.text_prompt
            
            # For now, anything else passes
            else:
                valid = True
            
            if valid:
                responses = get_responses(msg)
                if len(responses) > 0:
                    response_text = format_message_list(responses)
                    send_sms_to_verified_number(v, response_text)
            else:
                send_sms_to_verified_number(v, error_msg)
        
        # Try to match the text against a keyword to start a survey
        elif len(text_words) > 0:
            sk = SurveyKeyword.get_keyword(v.domain, text_words[0])
            if sk is not None:
                start_session_from_keyword(sk, v)
    else:
        #TODO: Registration via SMS
        pass
コード例 #23
0
ファイル: api.py プロジェクト: tsinkala/commcare-hq
def incoming(phone_number,
             text,
             backend_api,
             timestamp=None,
             domain_scope=None,
             delay=True):
    """
    entry point for incoming sms

    phone_number - originating phone number
    text - message content
    backend_api - backend ID of receiving sms backend
    timestamp - message received timestamp; defaults to now (UTC)
    domain_scope - if present, only messages from phone numbers that can be
      definitively linked to this domain will be processed; others will be
      dropped (useful to provide security when simulating incoming sms)
    """
    phone_number = clean_phone_number(phone_number)
    v = VerifiedNumber.by_phone(phone_number, include_pending=True)
    if domain_scope:
        # only process messages for phones known to be associated with this domain
        if v is None or v.domain != domain_scope:
            raise RuntimeError(
                'attempted to simulate incoming sms from phone number not verified with this domain'
            )

    # Log message in message log
    msg = SMSLog(phone_number=phone_number,
                 direction=INCOMING,
                 date=timestamp or datetime.utcnow(),
                 text=text,
                 backend_api=backend_api)
    if v is not None and v.verified:
        msg.couch_recipient_doc_type = v.owner_doc_type
        msg.couch_recipient = v.owner_id
        msg.domain = v.domain
    msg.save()

    create_billable_for_sms(msg, backend_api, delay=delay)

    if v is not None and v.verified:
        for h in settings.SMS_HANDLERS:
            try:
                handler = to_function(h)
            except:
                logging.exception('error loading sms handler: %s' % h)
                continue

            try:
                was_handled = handler(v, text)
            except:
                logging.exception(
                    'unhandled error in sms handler %s for message [%s]' %
                    (h, text))
                was_handled = False

            if was_handled:
                break
    else:
        if not process_sms_registration(msg):
            import verify
            verify.process_verification(phone_number, text)

    return msg