Beispiel #1
0
    def test_jsbox_js_config_no_config(self):
        config = {
            'jsbox_app_config': {
            }
        }

        self.assertEqual(utils.jsbox_js_config(config), {})
Beispiel #2
0
 def get_jsbox_js_config(self, conv):
     try:
         return jsbox_js_config(conv.config)
     except Exception:
         log.err("Bad jsbox js config: %s" %
                 (jsbox_config_value(conv.config, 'config'), ))
         return
Beispiel #3
0
 def get_jsbox_js_config(self, conv):
     try:
         return jsbox_js_config(conv.config)
     except Exception:
         log.err(
             "Bad jsbox js config: %s"
             % (jsbox_config_value(conv.config, 'config'),))
         return
Beispiel #4
0
    def test_jsbox_js_config(self):
        config = {
            'jsbox_app_config': {
                'config': {
                    'key': 'config',
                    'value': json.dumps({'foo': 'bar'})
                }
            }
        }

        self.assertEqual(utils.jsbox_js_config(config), {'foo': 'bar'})
Beispiel #5
0
    def test_jsbox_js_config(self):
        config = {
            'jsbox_app_config': {
                'config': {
                    'key': 'config',
                    'value': json.dumps({'foo': 'bar'})
                }
            }
        }

        self.assertEqual(utils.jsbox_js_config(config), {'foo': 'bar'})
Beispiel #6
0
    def configured_endpoints(self, config):
        try:
            js_config = jsbox_js_config(config)
        except Exception:
            return []

        # vumi-jssandbox-toolkit v2 endpoints
        try:
            v2_endpoints = list(js_config["endpoints"].keys())
        except Exception:
            v2_endpoints = []
        # vumi-jssandbox-toolkit v1 endpoints
        try:
            pool, tag = js_config["sms_tag"]
            v1_endpoints = [u"%s:%s" % (pool, tag)]
        except Exception:
            v1_endpoints = []

        endpoints = v1_endpoints + v2_endpoints
        endpoints = [ep for ep in endpoints if isinstance(ep, unicode)]
        return sorted(set(endpoints))
Beispiel #7
0
    def configured_endpoints(self, config):
        try:
            js_config = jsbox_js_config(config)
        except Exception:
            return []

        # vumi-jssandbox-toolkit v2 endpoints
        try:
            v2_endpoints = list(js_config["endpoints"].keys())
        except Exception:
            v2_endpoints = []
        # vumi-jssandbox-toolkit v1 endpoints
        try:
            pool, tag = js_config["sms_tag"]
            v1_endpoints = [u"%s:%s" % (pool, tag)]
        except Exception:
            v1_endpoints = []

        endpoints = v1_endpoints + v2_endpoints
        endpoints = [ep for ep in endpoints if isinstance(ep, unicode)]
        return sorted(set(endpoints))
Beispiel #8
0
    def test_jsbox_js_config_no_config(self):
        config = {'jsbox_app_config': {}}

        self.assertEqual(utils.jsbox_js_config(config), {})
Beispiel #9
0
class JsBoxSendWorker(Worker):

    WORKER_QUEUE = DeferredQueue()

    stdout = sys.stdout
    stderr = sys.stderr

    JSBOX_CONFIG = {
        'jsbox': lambda conv: jsbox_js_config(conv.config),
        'dialogue': dialogue_js_config,
    }
    SUPPORTED_APPS = tuple(JSBOX_CONFIG.keys())
    SEND_DELAY = 0.01  # No more than 100 msgs/second to the queue.

    def send_inbound_push_trigger(self, to_addr, conversation):
        self.emit('Starting %r [%s] -> %s' %
                  (conversation.name, conversation.key, to_addr))
        msg = mk_inbound_push_trigger(to_addr, conversation)
        return self.send_to_conv(conversation, msg)

    @inlineCallbacks
    def send_jsbox(self,
                   user_account_key,
                   conversation_key,
                   hz=60,
                   addr_exclude_path=None):
        conv = yield self.get_conversation(user_account_key, conversation_key)
        delivery_class = self.get_delivery_class(conv)
        excluded_addrs = self.get_excluded_addrs(addr_exclude_path)
        to_addrs = yield self.get_contact_addrs_for_conv(
            conv, delivery_class, excluded_addrs)
        ticker = Ticker(hz=hz)
        for i, to_addr in enumerate(to_addrs):
            yield self.send_inbound_push_trigger(to_addr, conv)
            if (i + 1) % 100 == 0:
                self.emit("Messages sent: %s / %s" % (i + 1, len(to_addrs)))
            yield ticker.tick()

    def get_delivery_class(self, conv):
        config_loader = self.JSBOX_CONFIG[conv.conversation_type]
        config = config_loader(conv)
        return config.get('delivery_class')

    def get_excluded_addrs(self, addr_exclude_path):
        if addr_exclude_path is None:
            return set()

        excluded_addrs = set()
        with open(addr_exclude_path, 'r') as exclude_file:
            for line in exclude_file.readlines():
                line = line.strip()
                if line:
                    excluded_addrs.add(line)
        return excluded_addrs

    @inlineCallbacks
    def get_contact_addrs_for_conv(self, conv, delivery_class, excluded_addrs):
        addrs = []
        for contacts in (yield
                         conv.get_opted_in_contact_bunches(delivery_class)):
            for contact in (yield contacts):
                addr = contact.addr_for(delivery_class)
                if addr not in excluded_addrs:
                    addrs.append(addr)
            self.emit("Addresses collected: %s" % (len(addrs), ))
        returnValue(addrs)

    @inlineCallbacks
    def send_to_conv(self, conv, msg):
        publisher = self._publishers[conv.conversation_type]
        yield publisher.publish_message(msg)
        # Give the reactor time to actually send the message.
        yield deferLater(reactor, self.SEND_DELAY, lambda: None)

    @inlineCallbacks
    def make_publisher(self, conv_type):
        routing_key = '%s_transport.inbound' % (conv_type, )
        self._publishers[conv_type] = yield self.publish_to(routing_key)

    @inlineCallbacks
    def get_conversation(self, user_account_key, conversation_key):
        user_api = self.vumi_api.get_user_api(user_account_key)
        conv = yield user_api.get_wrapped_conversation(conversation_key)
        if conv is None:
            raise ScriptError("Conversation not found: %s" %
                              (conversation_key, ))
        if conv.conversation_type not in self.SUPPORTED_APPS:
            raise ScriptError("Unsupported conversation type: %s" %
                              (conv.conversation_type, ))
        returnValue(conv)

    @inlineCallbacks
    def startWorker(self):
        self.vumi_api = yield VumiApi.from_config_async(
            self.config, self._amqp_client)
        self._publishers = {}
        for conv_type in self.SUPPORTED_APPS:
            yield self.make_publisher(conv_type)
        self.WORKER_QUEUE.put(self)

    def emit(self, obj, err=False):
        msg = '%s\n' % (obj, )
        if err:
            self.stderr.write(msg)
        else:
            self.stdout.write(msg)