コード例 #1
0
 def save_history(self,
                  message_content,
                  participant_phone,
                  message_type,
                  message_status=None,
                  message_id=None,
                  failure_reason=None,
                  timestamp=None,
                  reference_metadata=None):
     if timestamp:
         timestamp = time_to_vusion_format(timestamp)
     else:
         timestamp = time_to_vusion_format(self.get_local_time())
     history = {
         'message-id': message_id,
         'message-content': message_content,
         'participant-phone': participant_phone,
         'message-type': message_type,
         'message-status': message_status,
         'timestamp': timestamp,
     }
     if failure_reason is not None:
         history['failure-reason'] = failure_reason
     if reference_metadata is None:
         reference_metadata = {}
     for key, value in reference_metadata.iteritems():
         history[key] = value
     self.collections['history'].save(history)
コード例 #2
0
    def test05_send_scheduled_messages(self):
        dialogue = self.dialogue_annoucement_2
        participant = {'phone': '06'}
        mytimezone = self.program_settings[2]['value']
        dNow = datetime.utcnow().replace(tzinfo=pytz.utc).astimezone(pytz.timezone(mytimezone))
        dNow = dNow - timedelta(minutes=1)
        dPast = dNow - timedelta(minutes=30)
        dFuture = dNow + timedelta(minutes=30)

        self.collections['dialogues'].save(dialogue)
        self.collections['participants'].save(participant)
        for program_setting in self.program_settings:
            self.collections['program_settings'].save(program_setting)
        unattached_message = self.collections['unattached_messages'].save({
            'date-time': time_to_vusion_format(dNow),
            'content': 'Hello unattached',
            'to': 'all participants',
            'type-interaction': 'annoucement'
        })
        self.collections['schedules'].save({
            'date-time': dPast.strftime(self.time_format),
            'dialogue-id': '2',
            'interaction-id': '0',
            'participant-phone': '09'})
        self.collections['schedules'].save({
            'date-time': dNow.strftime(self.time_format),
            'dialogue-id': '2',
            'interaction-id': '1',
            'participant-phone': '09'})
        self.collections['schedules'].save({
            'date-time': dFuture.strftime(self.time_format),
            'dialogue-id': '2',
            'interaction-id': '2',
            'participant-phone': '09'})
        self.collections['schedules'].save({
            'date-time': time_to_vusion_format(dNow),
            'unattach-id': unattached_message,
            'participant-phone': '09'
        })
        self.collections['schedules'].save({
            'date-time': time_to_vusion_format(dNow),
            'type-content': 'feedback',
            'content': 'Thank you',
            'participant-phone': '09'
            })
        self.worker.load_data()

        yield self.worker.send_scheduled()

        messages = self.broker.get_messages('vumi', 'test.outbound')
        self.assertEqual(len(messages), 3)
        self.assertEqual(messages[0]['content'], 'Today will be sunny')
        self.assertEqual(messages[1]['content'], 'Hello unattached')
        self.assertEqual(messages[2]['content'], 'Thank you')

        self.assertEquals(self.collections['schedules'].count(), 1)
        self.assertEquals(self.collections['history'].count(), 4)
コード例 #3
0
    def consume_user_message(self, msg):
        regex_KEYWORD = re.compile('KEYWORD')

        log.debug("Consumer user message %s" % (msg,))
        if msg['timestamp']:
            timestamp = time_to_vusion_format(msg['timestamp'])
        self.unmatchable_reply_collection.save(
            {'participant-phone': msg['from_addr'],
             'to': msg['to_addr'],
             'message-content': msg['content'],
             'timestamp': timestamp,
             })

        code = self.shortcodes_collection.find_one({
            'shortcode': msg['to_addr']})
        if code is None:
            return
        template = self.templates_collection.find_one({
            '_id': ObjectId(code['error-template'])})
        if template is None:
            return
        error_message = TransportUserMessage(**{
            'from_addr': msg['to_addr'],
            'to_addr': msg['from_addr'],
            'transport_name': msg['transport_name'],
            'transport_type': msg['transport_type'],
            'transport_metadata': msg['transport_metadata'],
            'content': re.sub(
                regex_KEYWORD, get_first_word(msg['content']),
                template['template']
            )
        })
        yield self.transport_publisher.publish_message(error_message)
        log.debug("Reply '%s' sent to %s" %
                  (error_message['content'], error_message['to_addr']))
コード例 #4
0
    def test21_schedule_unattach_message(self):
        participants = [{'phone': '06'},
                        {'phone': '07'}]

        mytimezone = self.program_settings[2]['value']
        dNow = datetime.utcnow().replace(tzinfo=pytz.utc).astimezone(pytz.timezone(mytimezone))
        dFuture = dNow + timedelta(minutes=30)
        dPast = dNow - timedelta(minutes=30)

        unattach_messages = [
            {
                'to': 'all participants',
                'content': 'Hello everyone',
                'schedule': 'fixed-time',
                'fixed-time': time_to_vusion_format(dFuture)},
            {
                'to': 'all participants',
                'content': 'Hello again',
                'schedule': 'fixed-time',
                'fixed-time': time_to_vusion_format(dPast)}]

        for program_setting in self.program_settings:
            self.collections['program_settings'].save(program_setting)
        for participant in participants:
            self.collections['participants'].save(participant)

        unattach_id = self.collections['unattached_messages'].save(unattach_messages[0])
        self.collections['unattached_messages'].save(unattach_messages[1])

        self.collections['history'].save({
            'participant-phone': '06',
            'message-type': 'sent',
            'message-status': 'delivered',
            'unattach-id': unattach_id
        })

        self.worker.load_data()

        self.worker.schedule_participants_unattach_messages(
            participants)

        schedules_count = self.collections['schedules'].count()
        self.assertEqual(schedules_count, 1)
        schedules = self.collections['schedules'].find()
        self.assertEqual(schedules[0]['participant-phone'], '07')
コード例 #5
0
    def test21_schedule_unattach_message(self):
        participants = [{'phone': '06'}, {'phone': '07'}]

        mytimezone = self.program_settings[2]['value']
        dNow = datetime.utcnow().replace(tzinfo=pytz.utc).astimezone(
            pytz.timezone(mytimezone))
        dFuture = dNow + timedelta(minutes=30)
        dPast = dNow - timedelta(minutes=30)

        unattach_messages = [{
            'to': 'all participants',
            'content': 'Hello everyone',
            'schedule': 'fixed-time',
            'fixed-time': time_to_vusion_format(dFuture)
        }, {
            'to': 'all participants',
            'content': 'Hello again',
            'schedule': 'fixed-time',
            'fixed-time': time_to_vusion_format(dPast)
        }]

        for program_setting in self.program_settings:
            self.collections['program_settings'].save(program_setting)
        for participant in participants:
            self.collections['participants'].save(participant)

        unattach_id = self.collections['unattached_messages'].save(
            unattach_messages[0])
        self.collections['unattached_messages'].save(unattach_messages[1])

        self.collections['history'].save({
            'participant-phone': '06',
            'message-type': 'sent',
            'message-status': 'delivered',
            'unattach-id': unattach_id
        })

        self.worker.load_data()

        self.worker.schedule_participants_unattach_messages(participants)

        schedules_count = self.collections['schedules'].count()
        self.assertEqual(schedules_count, 1)
        schedules = self.collections['schedules'].find()
        self.assertEqual(schedules[0]['participant-phone'], '07')
コード例 #6
0
 def save_history(self, message_content, participant_phone, message_type,
                 message_status=None, message_id=None, failure_reason=None,
                 timestamp=None, reference_metadata=None):
     if timestamp:
         timestamp = time_to_vusion_format(timestamp)
     else:
         timestamp = time_to_vusion_format(self.get_local_time())
     history = {
         'message-id': message_id,
         'message-content': message_content,
         'participant-phone': participant_phone,
         'message-type': message_type,
         'message-status': message_status,
         'timestamp': timestamp,
     }
     if failure_reason is not None:
         history['failure-reason'] = failure_reason
     if reference_metadata is None:
         reference_metadata = {}
     for key, value in reference_metadata.iteritems():
         history[key] = value
     self.collections['history'].save(history)
コード例 #7
0
 def log(self, msg, level='msg'):
     timezone = None
     local_time = self.get_local_time()
     rkey = "%slogs" % (self.r_prefix, )
     self.r_server.zremrangebyscore(
         rkey, 1,
         get_local_time_as_timestamp(local_time - timedelta(hours=2)))
     self.r_server.zadd(
         rkey, "[%s] %s" % (time_to_vusion_format(local_time), msg),
         get_local_time_as_timestamp(local_time))
     if (level == 'msg'):
         log.msg('[%s] %s' % (self.control_name, msg))
     else:
         log.error('[%s] %s' % (self.control_name, msg))
コード例 #8
0
 def log(self, msg, level='msg'):
     timezone = None
     local_time = self.get_local_time()
     rkey = "%slogs" % (self.r_prefix,)
     self.r_server.zremrangebyscore(
         rkey,
         1,
         get_local_time_as_timestamp(
             local_time - timedelta(hours=2))
     )
     self.r_server.zadd(
         rkey,
         "[%s] %s" % (
             time_to_vusion_format(local_time),
             msg),
         get_local_time_as_timestamp(local_time))
     if (level == 'msg'):
         log.msg('[%s] %s' % (self.control_name, msg))
     else:
         log.error('[%s] %s' % (self.control_name, msg))
コード例 #9
0
    def send_scheduled(self):
        self.log('Checking the schedule list...')
        local_time = self.get_local_time()
        toSends = self.collections['schedules'].find(
            spec={'date-time': {'$lt': time_to_vusion_format(local_time)}},
            sort=[('date-time', 1)])
        for toSend in toSends:
            self.collections['schedules'].remove(
                {'_id': toSend['_id']})
            message_content = None
            try:
                interaction, reference_metadata = self.from_schedule_to_message(toSend)

                if not interaction:
                    continue

                message_content = self.generate_message(interaction)
                message_content = self.customize_message(
                    toSend['participant-phone'],
                    message_content)

                if (time_from_vusion_format(toSend['date-time']) <
                    (local_time - timedelta(minutes=15))):
                    raise SendingDatePassed(
                        "Message should have been send at %s" %
                        (toSend['date-time'],))

                message = TransportUserMessage(**{
                    'from_addr': self.properties['shortcode'],
                    'to_addr': toSend['participant-phone'],
                    'transport_name': self.transport_name,
                    'transport_type': self.transport_type,
                    'transport_metadata': '',
                    'content': message_content})
                yield self.transport_publisher.publish_message(message)
                self.log(
                    "Message has been send to %s '%s'" % (message['to_addr'],
                                                          message['content']))
                self.save_history(
                    message_content=message['content'],
                    participant_phone=message['to_addr'],
                    message_type='sent',
                    message_status='pending',
                    message_id=message['message_id'],
                    reference_metadata=reference_metadata)

            except VusionError as e:
                self.save_history(
                    message_content='',
                    participant_phone=toSend['participant-phone'],
                    message_type=None,
                    failure_reason=('%s' % (e,)),
                    reference_metadata=reference_metadata)
            except:
                exc_type, exc_value, exc_traceback = sys.exc_info()
                self.log(
                    "Error during consume user message: %r" %
                    traceback.format_exception(exc_type, exc_value, exc_traceback))
                self.save_history(
                    participant_phone=toSend['participant-phone'],
                    message_content='',
                    message_type='system-failed',
                    failure_reason=('%s - %s') % (sys.exc_info()[0],
                                                  sys.exc_info()[1]),
                    reference_metadata=reference_metadata)
コード例 #10
0
 def get_future_unattach_messages(self):
     return self.collections['unattached_messages'].find({
         'fixed-time': {
             '$gt': time_to_vusion_format(self.get_local_time())
         }})
コード例 #11
0
 def run_action(self, participant_phone, action):
     regex_ANSWER = re.compile('ANSWER')
     
     if (action['type-action'] == 'optin'):
         self.collections['participants'].update(
             {'phone': participant_phone},
             {'$unset': {'optout': 1}}, True)
     elif (action['type-action'] == 'optout'):
         self.collections['participants'].update(
             {'phone': participant_phone},
             {'$set': {'optout': True}})
     elif (action['type-action'] == 'feedback'):
         self.collections['schedules'].save({
             'date-time': time_to_vusion_format(self.get_local_time()),
             'content': action['content'],
             'type-content': 'feedback',
             'participant-phone': participant_phone
         })
     elif (action['type-action'] == 'unmatching-answer'):
         setting = self.collections['program_settings'].find_one({
             'key': 'default-template-unmatching-answer'})
         if setting is None:
             return
         template = self.collections['templates'].find_one({
             '_id': ObjectId(setting['value'])})
         if template is None:
             return
         error_message = TransportUserMessage(**{
             'from_addr': '8282',
             'to_addr': participant_phone,
             'transport_name': None,
             'transport_type': None,
             'transport_metadata': None,
             'content': re.sub(regex_ANSWER, action['answer'], template['template'])
         })
         self.collections['schedules'].save({
             'date-time': time_to_vusion_format(self.get_local_time()),
             'content': error_message['content'],
             'type-content': 'feedback',
             'participant-phone': participant_phone
         })
         log.debug("Reply '%s' sent to %s" %
             (error_message['content'], error_message['to_addr']))
     elif (action['type-action'] == 'tagging'):
         self.collections['participants'].update(
             {'phone': participant_phone,
              'tags': {'$ne': action['tag']}},
             {'$push': {'tags': action['tag']}})
     elif (action['type-action'] == 'enrolling'):
         self.collections['participants'].update(
             {'phone': participant_phone,
              'enrolled': {'$ne': action['enroll']}},
             {'$push': {'enrolled': action['enroll']}}, True)
         dialogue = self.get_current_dialogue(action['enroll'])
         participant = self.collections['participants'].find_one(
             {'phone': participant_phone})
         self.schedule_participant_dialogue(participant, dialogue)
     elif (action['type-action'] == 'profiling'):
         self.collections['participants'].update(
             {'phone': participant_phone},
             {'$set': {action['label']: action['value']}})
     else:
         self.log("The action is not supported %s" % action['type-action'])
コード例 #12
0
    def send_scheduled(self):
        self.log('Checking the schedule list...')
        local_time = self.get_local_time()
        toSends = self.collections['schedules'].find(
            spec={'date-time': {
                '$lt': time_to_vusion_format(local_time)
            }},
            sort=[('date-time', 1)])
        for toSend in toSends:
            self.collections['schedules'].remove({'_id': toSend['_id']})
            message_content = None
            try:
                interaction, reference_metadata = self.from_schedule_to_message(
                    toSend)

                if not interaction:
                    continue

                message_content = self.generate_message(interaction)
                message_content = self.customize_message(
                    toSend['participant-phone'], message_content)

                if (time_from_vusion_format(toSend['date-time']) <
                    (local_time - timedelta(minutes=15))):
                    raise SendingDatePassed(
                        "Message should have been send at %s" %
                        (toSend['date-time'], ))

                message = TransportUserMessage(
                    **{
                        'from_addr': self.properties['shortcode'],
                        'to_addr': toSend['participant-phone'],
                        'transport_name': self.transport_name,
                        'transport_type': self.transport_type,
                        'transport_metadata': '',
                        'content': message_content
                    })
                yield self.transport_publisher.publish_message(message)
                self.log("Message has been send to %s '%s'" %
                         (message['to_addr'], message['content']))
                self.save_history(message_content=message['content'],
                                  participant_phone=message['to_addr'],
                                  message_type='sent',
                                  message_status='pending',
                                  message_id=message['message_id'],
                                  reference_metadata=reference_metadata)

            except VusionError as e:
                self.save_history(
                    message_content='',
                    participant_phone=toSend['participant-phone'],
                    message_type=None,
                    failure_reason=('%s' % (e, )),
                    reference_metadata=reference_metadata)
            except:
                exc_type, exc_value, exc_traceback = sys.exc_info()
                self.log("Error during consume user message: %r" %
                         traceback.format_exception(exc_type, exc_value,
                                                    exc_traceback))
                self.save_history(
                    participant_phone=toSend['participant-phone'],
                    message_content='',
                    message_type='system-failed',
                    failure_reason=('%s - %s') %
                    (sys.exc_info()[0], sys.exc_info()[1]),
                    reference_metadata=reference_metadata)
コード例 #13
0
 def get_future_unattach_messages(self):
     return self.collections['unattached_messages'].find({
         'fixed-time': {
             '$gt': time_to_vusion_format(self.get_local_time())
         }
     })
コード例 #14
0
    def run_action(self, participant_phone, action):
        regex_ANSWER = re.compile('ANSWER')

        if (action['type-action'] == 'optin'):
            self.collections['participants'].update(
                {'phone': participant_phone}, {'$unset': {
                    'optout': 1
                }}, True)
        elif (action['type-action'] == 'optout'):
            self.collections['participants'].update(
                {'phone': participant_phone}, {'$set': {
                    'optout': True
                }})
        elif (action['type-action'] == 'feedback'):
            self.collections['schedules'].save({
                'date-time':
                time_to_vusion_format(self.get_local_time()),
                'content':
                action['content'],
                'type-content':
                'feedback',
                'participant-phone':
                participant_phone
            })
        elif (action['type-action'] == 'unmatching-answer'):
            setting = self.collections['program_settings'].find_one(
                {'key': 'default-template-unmatching-answer'})
            if setting is None:
                return
            template = self.collections['templates'].find_one(
                {'_id': ObjectId(setting['value'])})
            if template is None:
                return
            error_message = TransportUserMessage(
                **{
                    'from_addr':
                    '8282',
                    'to_addr':
                    participant_phone,
                    'transport_name':
                    None,
                    'transport_type':
                    None,
                    'transport_metadata':
                    None,
                    'content':
                    re.sub(regex_ANSWER, action['answer'],
                           template['template'])
                })
            self.collections['schedules'].save({
                'date-time':
                time_to_vusion_format(self.get_local_time()),
                'content':
                error_message['content'],
                'type-content':
                'feedback',
                'participant-phone':
                participant_phone
            })
            log.debug("Reply '%s' sent to %s" %
                      (error_message['content'], error_message['to_addr']))
        elif (action['type-action'] == 'tagging'):
            self.collections['participants'].update(
                {
                    'phone': participant_phone,
                    'tags': {
                        '$ne': action['tag']
                    }
                }, {'$push': {
                    'tags': action['tag']
                }})
        elif (action['type-action'] == 'enrolling'):
            self.collections['participants'].update(
                {
                    'phone': participant_phone,
                    'enrolled': {
                        '$ne': action['enroll']
                    }
                }, {'$push': {
                    'enrolled': action['enroll']
                }}, True)
            dialogue = self.get_current_dialogue(action['enroll'])
            participant = self.collections['participants'].find_one(
                {'phone': participant_phone})
            self.schedule_participant_dialogue(participant, dialogue)
        elif (action['type-action'] == 'profiling'):
            self.collections['participants'].update(
                {'phone': participant_phone},
                {'$set': {
                    action['label']: action['value']
                }})
        else:
            self.log("The action is not supported %s" % action['type-action'])
コード例 #15
0
    def test05_send_scheduled_messages(self):
        dialogue = self.dialogue_annoucement_2
        participant = {'phone': '06'}
        mytimezone = self.program_settings[2]['value']
        dNow = datetime.utcnow().replace(tzinfo=pytz.utc).astimezone(
            pytz.timezone(mytimezone))
        dNow = dNow - timedelta(minutes=1)
        dPast = dNow - timedelta(minutes=30)
        dFuture = dNow + timedelta(minutes=30)

        self.collections['dialogues'].save(dialogue)
        self.collections['participants'].save(participant)
        for program_setting in self.program_settings:
            self.collections['program_settings'].save(program_setting)
        unattached_message = self.collections['unattached_messages'].save({
            'date-time':
            time_to_vusion_format(dNow),
            'content':
            'Hello unattached',
            'to':
            'all participants',
            'type-interaction':
            'annoucement'
        })
        self.collections['schedules'].save({
            'date-time':
            dPast.strftime(self.time_format),
            'dialogue-id':
            '2',
            'interaction-id':
            '0',
            'participant-phone':
            '09'
        })
        self.collections['schedules'].save({
            'date-time':
            dNow.strftime(self.time_format),
            'dialogue-id':
            '2',
            'interaction-id':
            '1',
            'participant-phone':
            '09'
        })
        self.collections['schedules'].save({
            'date-time':
            dFuture.strftime(self.time_format),
            'dialogue-id':
            '2',
            'interaction-id':
            '2',
            'participant-phone':
            '09'
        })
        self.collections['schedules'].save({
            'date-time':
            time_to_vusion_format(dNow),
            'unattach-id':
            unattached_message,
            'participant-phone':
            '09'
        })
        self.collections['schedules'].save({
            'date-time':
            time_to_vusion_format(dNow),
            'type-content':
            'feedback',
            'content':
            'Thank you',
            'participant-phone':
            '09'
        })
        self.worker.load_data()

        yield self.worker.send_scheduled()

        messages = self.broker.get_messages('vumi', 'test.outbound')
        self.assertEqual(len(messages), 3)
        self.assertEqual(messages[0]['content'], 'Today will be sunny')
        self.assertEqual(messages[1]['content'], 'Hello unattached')
        self.assertEqual(messages[2]['content'], 'Thank you')

        self.assertEquals(self.collections['schedules'].count(), 1)
        self.assertEquals(self.collections['history'].count(), 4)