Exemplo n.º 1
0
class USSDOptOutHandler(SNAEventHandler):

    def setup_handler(self):
        self.pm_prefix = self.config['poll_manager_prefix']
        self.vumi_api = self.dispatcher.vumi_api
        self.pm = PollManager(self.vumi_api.redis, self.pm_prefix)

    def teardown_handler(self):
        self.pm.stop()

    @inlineCallbacks
    def handle_event(self, event, handler_config):
        """

        Expects the event 'content' to be a dict with the following keys
        and values:

        NOTE:   perhaps all we need here is the message_id and lookup the
                rest of the required data from the message in the message store

        :param from_addr:
            the from_addr of the user interaction that triggered the event
        :param message_id:
            the id of the message that triggered the event, used to keep an
            audit trail of opt-outs and which messages they were triggered by.
        :param transport_type:
            the transport_type that the message was received on.

        """
        account_key = event.payload['account_key']
        oo_store = OptOutStore(self.vumi_api.manager, account_key)

        event_data = event.payload['content']

        from_addr = event_data['from_addr']
        message_id = event_data['message_id']
        transport_type = event_data.get('transport_type')

        if transport_type != 'ussd':
            log.info("SNAUSSDOptOutHandler skipping non-ussd"
                     " message for %r" % (from_addr,))
            return
        contact = yield self.find_contact(account_key, from_addr)
        if contact:
            opted_out = contact.extra['opted_out']
            if opted_out is not None and opted_out.isdigit():
                if int(opted_out) > 1:
                    yield oo_store.new_opt_out('msisdn', from_addr, {
                        'message_id': message_id,
                    })
                else:
                    yield oo_store.delete_opt_out('msisdn', from_addr)
Exemplo n.º 2
0
def get_poll_config(poll_id):
    # FIXME: Do we really need this?
    redis = RedisManager.from_config(settings.VXPOLLS_REDIS_CONFIG)
    pm = PollManager(redis, settings.VXPOLLS_PREFIX)
    config = pm.get_config(poll_id)
    config.update({
        'poll_id': poll_id,
    })

    config.setdefault('repeatable', True)
    config.setdefault('survey_completed_response',
                        'Thanks for completing the survey')
    return pm, config
Exemplo n.º 3
0
def get_poll_config(poll_id):
    # FIXME: Do we really need this?
    redis = RedisManager.from_config(settings.VXPOLLS_REDIS_CONFIG)
    pm = PollManager(redis, settings.VXPOLLS_PREFIX)
    config = pm.get_config(poll_id)
    config.update({
        'poll_id': poll_id,
    })

    config.setdefault('repeatable', True)
    config.setdefault('survey_completed_response',
                      'Thanks for completing the survey')
    return pm, config
Exemplo n.º 4
0
    def setUp(self):
        self.eh_helper = self.add_helper(EventHandlerHelper())
        yield self.eh_helper.setup_event_dispatcher(
            'sisi_ni_amani', USSDOptOutHandler, {
                'poll_manager_prefix': 'vumigo.',
            })

        vumi_api = self.eh_helper.vumi_helper.get_vumi_api()
        user_helper = yield self.eh_helper.vumi_helper.get_or_create_user()
        self.contact_store = user_helper.user_api.contact_store
        self.oo_store = OptOutStore(vumi_api.manager, user_helper.account_key)

        self.pm = PollManager(vumi_api.redis, 'vumigo.')
        self.add_cleanup(self.pm.stop)

        self.eh_helper.track_event('survey_completed', 'sisi_ni_amani')
Exemplo n.º 5
0
 def setup_application(self):
     yield self._go_setup_worker()
     self.pm = PollManager(self.redis, self.poll_prefix)
Exemplo n.º 6
0
class SurveyApplication(PollApplication, GoApplicationMixin):
    CONFIG_CLASS = SurveyConfig

    worker_name = 'survey_application'

    def validate_config(self):
        # vxpolls
        vxp_config = self.config.get('vxpolls', {})
        self.poll_prefix = vxp_config.get('prefix')

    @inlineCallbacks
    def setup_application(self):
        yield self._go_setup_worker()
        self.pm = PollManager(self.redis, self.poll_prefix)

    @inlineCallbacks
    def teardown_application(self):
        yield self.pm.stop()
        yield self._go_teardown_worker()

    @inlineCallbacks
    def consume_user_message(self, message):
        contact = yield self.get_contact_for_message(message, create=True)
        yield self._handle_survey_message(message, contact)

    @inlineCallbacks
    def _handle_survey_message(self, message, contact):
        helper_metadata = message['helper_metadata']
        go = helper_metadata.get('go')
        poll_id = 'poll-%s' % (go.get('conversation_key'), )
        helper_metadata['poll_id'] = poll_id

        participant = yield self.pm.get_participant(poll_id, message.user())

        poll = yield self.pm.get_poll_for_participant(poll_id, participant)
        if poll is None:
            yield self.reply_to(message,
                                'Service Unavailable. Please try again later.',
                                continue_session=False)
            return

        config = yield self.pm.get_config(poll_id)
        for key in config.get('include_labels', []):
            value = contact.extra[key]
            if value and key not in participant.labels:
                participant.set_label(key, value)

        yield self.pm.save_participant(poll_id, participant)
        yield super(SurveyApplication, self).consume_user_message(message)

    def start_survey(self, to_addr, contact, conversation, **msg_options):
        log.debug('Starting %r -> %s' % (conversation, to_addr))

        # We reverse the to_addr & from_addr since we're faking input
        # from the client to start the survey.
        from_addr = msg_options.pop('from_addr')
        conversation.set_go_helper_metadata(
            msg_options.setdefault('helper_metadata', {}))
        msg = TransportUserMessage(from_addr=to_addr,
                                   to_addr=from_addr,
                                   content='',
                                   **msg_options)

        return self._handle_survey_message(msg, contact)

    @inlineCallbacks
    def end_session(self, participant, poll, message):
        # At the end of a session we want to store the user's responses
        # as dynamic values on the contact's record in the contact database.
        # This does that.
        contact = yield self.get_contact_for_message(message, create=True)

        # Clear previous answers from this poll
        possible_labels = [q.get('label') for q in poll.questions]
        for label in possible_labels:
            if (label is not None) and (label in contact.extra):
                del contact.extra[label]

        contact.extra.update(participant.labels)
        yield contact.save()

        yield self.pm.save_participant(poll.poll_id, participant)
        yield self.trigger_event(
            message, 'survey_completed', {
                'from_addr': message['from_addr'],
                'message_id': message['message_id'],
                'transport_type': message['transport_type'],
                'participant': participant.dump(),
            })
        yield super(SurveyApplication,
                    self).end_session(participant, poll, message)

    @inlineCallbacks
    def process_command_send_survey(self, user_account_key, conversation_key,
                                    batch_id, msg_options, delivery_class,
                                    **extra_params):

        conv = yield self.get_conversation(user_account_key, conversation_key)

        if conv is None:
            log.warning("Cannot find conversation '%s' for user '%s'." %
                        (conversation_key, user_account_key))
            return

        for contacts in (yield
                         conv.get_opted_in_contact_bunches(delivery_class)):
            for contact in (yield contacts):
                to_addr = contact.addr_for(delivery_class)
                # Set some fake msg_options in case we didn't get real ones.
                msg_options.setdefault('from_addr', None)
                msg_options.setdefault('transport_name', None)
                msg_options.setdefault('transport_type', 'sms')
                yield self.start_survey(to_addr, contact, conv, **msg_options)
Exemplo n.º 7
0
 def setup_application(self):
     yield self._go_setup_worker()
     self.pm = PollManager(self.redis, self.poll_prefix)
Exemplo n.º 8
0
class SurveyApplication(PollApplication, GoApplicationMixin):
    CONFIG_CLASS = SurveyConfig

    worker_name = 'survey_application'

    def validate_config(self):
        # vxpolls
        vxp_config = self.config.get('vxpolls', {})
        self.poll_prefix = vxp_config.get('prefix')

    @inlineCallbacks
    def setup_application(self):
        yield self._go_setup_worker()
        self.pm = PollManager(self.redis, self.poll_prefix)

    @inlineCallbacks
    def teardown_application(self):
        yield self.pm.stop()
        yield self._go_teardown_worker()

    @inlineCallbacks
    def consume_user_message(self, message):
        contact = yield self.get_contact_for_message(message, create=True)
        yield self._handle_survey_message(message, contact)

    @inlineCallbacks
    def _handle_survey_message(self, message, contact):
        helper_metadata = message['helper_metadata']
        go = helper_metadata.get('go')
        poll_id = 'poll-%s' % (go.get('conversation_key'),)
        helper_metadata['poll_id'] = poll_id

        participant = yield self.pm.get_participant(
            poll_id, message.user())

        poll = yield self.pm.get_poll_for_participant(poll_id, participant)
        if poll is None:
            yield self.reply_to(
                message, 'Service Unavailable. Please try again later.',
                continue_session=False)
            return

        config = yield self.pm.get_config(poll_id)
        for key in config.get('include_labels', []):
            value = contact.extra[key]
            if value and key not in participant.labels:
                participant.set_label(key, value)

        yield self.pm.save_participant(poll_id, participant)
        yield super(SurveyApplication, self).consume_user_message(message)

    def start_survey(self, to_addr, contact, conversation, **msg_options):
        log.debug('Starting %r -> %s' % (conversation, to_addr))

        # We reverse the to_addr & from_addr since we're faking input
        # from the client to start the survey.
        from_addr = msg_options.pop('from_addr')
        conversation.set_go_helper_metadata(
            msg_options.setdefault('helper_metadata', {}))
        msg = TransportUserMessage(from_addr=to_addr, to_addr=from_addr,
                                   content='', **msg_options)

        return self._handle_survey_message(msg, contact)

    @inlineCallbacks
    def end_session(self, participant, poll, message):
        # At the end of a session we want to store the user's responses
        # as dynamic values on the contact's record in the contact database.
        # This does that.
        contact = yield self.get_contact_for_message(message, create=True)

        # Clear previous answers from this poll
        possible_labels = [q.get('label') for q in poll.questions]
        for label in possible_labels:
            if (label is not None) and (label in contact.extra):
                del contact.extra[label]

        contact.extra.update(participant.labels)
        yield contact.save()

        yield self.pm.save_participant(poll.poll_id, participant)
        yield self.trigger_event(message, 'survey_completed', {
            'from_addr': message['from_addr'],
            'message_id': message['message_id'],
            'transport_type': message['transport_type'],
            'participant': participant.dump(),
        })
        yield super(SurveyApplication, self).end_session(participant, poll,
            message)

    @inlineCallbacks
    def process_command_send_survey(self, user_account_key, conversation_key,
                                    batch_id, msg_options, delivery_class,
                                    **extra_params):

        conv = yield self.get_conversation(user_account_key, conversation_key)

        if conv is None:
            log.warning("Cannot find conversation '%s' for user '%s'." % (
                conversation_key, user_account_key))
            return

        for contacts in (yield conv.get_opted_in_contact_bunches(
                delivery_class)):
            for contact in (yield contacts):
                to_addr = contact.addr_for(delivery_class)
                # Set some fake msg_options in case we didn't get real ones.
                msg_options.setdefault('from_addr', None)
                msg_options.setdefault('transport_name', None)
                msg_options.setdefault('transport_type', 'sms')
                yield self.start_survey(to_addr, contact, conv, **msg_options)
Exemplo n.º 9
0
 def setup_handler(self):
     self.pm_prefix = self.config['poll_manager_prefix']
     self.vumi_api = self.dispatcher.vumi_api
     self.pm = PollManager(self.vumi_api.redis, self.pm_prefix)