def mkmsg_out(self, content='hello world', session_event=TransportUserMessage.SESSION_NONE, message_id='1', to_addr='+41791234567', from_addr='9292', group=None, in_reply_to=None, transport_type=None, transport_metadata=None, helper_metadata=None, transport_name=None): if transport_type is None: transport_type = transport_type if transport_metadata is None: transport_metadata = {} if helper_metadata is None: helper_metadata = {} params = dict( to_addr=to_addr, from_addr=from_addr, group=group, message_id=message_id, transport_name=transport_name, transport_type=transport_type, transport_metadata=transport_metadata, content=content, session_event=session_event, in_reply_to=in_reply_to, helper_metadata=helper_metadata, ) return TransportUserMessage(**params)
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']))
def mk_inbound_push_trigger(to_addr, conversation): """ Construct a dummy inbound message used to trigger a push of a new message from a sandbox application. """ msg_options = { 'transport_name': None, 'transport_type': None, 'helper_metadata': {}, # mark this message as special so that it can be idenitified # if it accidentally ends up elsewhere. INBOUND_PUSH_TRIGGER: True, } conversation.set_go_helper_metadata(msg_options['helper_metadata']) # We reverse the to_addr & from_addr since we're faking input # from the client to start the survey. # This generates a fake message id that is then used in the # in_reply_to field of the outbound message. We filter these # replies out and convert them into sends in the outbound # resource below msg = TransportUserMessage(from_addr=to_addr, to_addr=None, content=None, **msg_options) return msg
def mk_msg(self, to_addr, tag=None, from_addr="12345"): msg = TransportUserMessage(to_addr=to_addr, from_addr=from_addr, transport_name="dummy_connector", transport_type="dummy_transport_type") if tag is not None: TaggingMiddleware.add_tag_to_msg(msg, tag) return msg
def test_outbound_non_reply_logs_error(self): msg = TransportUserMessage(to_addr="1234", from_addr="5678", transport_name="test_infobip", transport_type="ussd", transport_metadata={}) with LogCatcher() as logger: self.broker.publish_message("vumi", "test_infobip.outbound", msg) yield self.broker.kick_delivery() [error, logged_failure] = logger.errors expected_error = ("Infobip transport cannot process outbound message" " that is not a reply.") twisted_failure = logged_failure['failure'] self.assertEqual(self.flushLoggedErrors(PermanentFailure), [twisted_failure]) failure = twisted_failure.value self.assertEqual(failure.failure_code, FailureMessage.FC_PERMANENT) self.assertEqual(str(failure), expected_error) [errmsg] = error['message'] expected_logged_error = "'" + expected_error.replace('.', ':') self.assertTrue(errmsg.startswith(expected_logged_error)) [msg] = yield self.broker.wait_messages("vumi", "test_infobip.failures", 1) self.assertEqual(msg['failure_code'], "permanent") last_line = msg['reason'].splitlines()[-1].strip() self.assertTrue(last_line.endswith(expected_error))
def test_inbound_resume_continue(self): url = "%s%s?%s" % ( self.transport_url, self.config['web_path'], urlencode({ 'ussdSessionId': 123, 'msisdn': 555, 'provider': 'web', 'request': 1, }) ) d = http_request(url, '', method='GET') msg, = yield self.wait_for_dispatched_messages(1) payload = msg.payload self.assertEqual(payload['transport_name'], self.transport_name) self.assertEqual(payload['transport_type'], "ussd") self.assertEqual(payload['transport_metadata'], {"session_id": "123"}) self.assertEqual(payload['session_event'], TransportUserMessage.SESSION_RESUME) self.assertEqual(payload['from_addr'], '555') self.assertEqual(payload['to_addr'], '') self.assertEqual(payload['content'], '1') tum = TransportUserMessage(**payload) rep = tum.reply("OK") self.dispatch(rep) response = yield d correct_response = '<request>\n\t<headertext>OK</headertext>\n\t' \ '<options>\n\t\t<option command="1" order="1" ' \ 'callback="http://localhost/foo" display="False" >' \ '</option>\n\t</options>\n</request>' self.assertEqual(response, correct_response)
def test_send_reply_message(self): '''send_reply_message should place the correct reply message on the correct queue''' channel = yield self.create_channel(self.service, self.redis, id='channel-id') in_msg = TransportUserMessage(from_addr='+2789', to_addr='+1234', transport_name='channel-id', transport_type='_', transport_metadata={'foo': 'bar'}) yield self.api.inbounds.store_vumi_message('channel-id', in_msg) msg = yield channel.send_reply_message( self.message_sender, self.outbounds, self.inbounds, { 'reply_to': in_msg['message_id'], 'content': 'testcontent', }) expected = in_msg.reply(content='testcontent') expected = conjoin(api_from_message(expected), { 'timestamp': msg['timestamp'], 'message_id': msg['message_id'] }) self.assertEqual(msg, expected) [dispatched] = self.get_dispatched_messages('channel-id.outbound') self.assertEqual(msg['message_id'], dispatched['message_id']) self.assertEqual(api_from_message(dispatched), expected)
def mkmsg_in(self, content='hello world', message_id='abc', to_addr='9292', from_addr='+41791234567', group=None, session_event=None, transport_type=None, helper_metadata=None, transport_metadata=None): if transport_type is None: transport_type = self.transport_type if helper_metadata is None: helper_metadata = {} if transport_metadata is None: transport_metadata = {} return TransportUserMessage( from_addr=from_addr, to_addr=to_addr, group=group, message_id=message_id, transport_name=self.transport_name, transport_type=transport_type, transport_metadata=transport_metadata, helper_metadata=helper_metadata, content=content, session_event=session_event, timestamp=datetime.now(), )
def mkmsg_in(self, content='hello world', from_addr='+41791234567', to_addr='9292', session_event=TransportUserMessage.SESSION_NONE, message_id='abc', transport_type=None, transport_metadata=None, transport_name=None, timestamp=None): if timestamp is None: timestamp = datetime.now() if transport_type is None: transport_type = transport_type if transport_metadata is None: transport_metadata = {} return TransportUserMessage( from_addr=from_addr, to_addr=to_addr, group=None, message_id=message_id, transport_name=transport_name, transport_type=transport_type, transport_metadata=transport_metadata, content=content, session_event=session_event, timestamp=timestamp, )
def test_send_reply_message_with_event_auth_token(self): '''Sending a message with a specified event auth token should store the token for sending events in the future''' channel = yield self.create_channel(self.service, self.redis, id='channel-id') in_msg = TransportUserMessage(from_addr='+2789', to_addr='+1234', transport_name='channel-id', transport_type='_', transport_metadata={'foo': 'bar'}) yield self.api.inbounds.store_vumi_message('channel-id', in_msg) msg = yield channel.send_reply_message( self.message_sender, self.outbounds, self.inbounds, { 'reply_to': in_msg['message_id'], 'content': 'testcontent', 'event_url': 'http://test.org', 'event_auth_token': "the-auth-token", }) event_auth_token = yield self.outbounds.load_event_auth_token( 'channel-id', msg['message_id']) self.assertEqual(event_auth_token, "the-auth-token")
def process_line(self, line): data = { 'transport_name': self.transport_name, 'transport_metadata': {}, } data.update(json.loads(line)) self.publisher.publish_message(TransportUserMessage(**to_kwargs(data)))
def make_request(self, session_type, session_id, reply=None, continue_session=True, expect_msg=True, defer_response=False, **kw): url_suffix = "session/%s/%s" % (session_id, session_type) method = self.SESSION_HTTP_METHOD.get(session_type, "POST") request_data = self.DEFAULT_SESSION_DATA[session_type].copy() request_data.update(kw) deferred_req = http_request(self.worker_url + url_suffix, json.dumps(request_data), method=method) if not expect_msg: msg = None else: [msg] = yield self.broker.wait_messages("vumi", "test_infobip.inbound", 1) self.broker.clear_messages("vumi", "test_infobip.inbound") msg = TransportUserMessage(**msg.payload) if reply is not None: reply_msg = msg.reply(reply, continue_session=continue_session) self.broker.publish_message("vumi", "test_infobip.outbound", reply_msg) if defer_response: response = deferred_req else: response = yield deferred_req returnValue((msg, response))
def assertDelivered(self, message): delivered_messages = [ TransportUserMessage(**to_kwargs(payload)) for _, payload in self._delivery_history ] self.assertIn(message['message_id'], [msg['message_id'] for msg in delivered_messages])
def make_batch(self, batch_no, num_msgs): return [ TransportUserMessage(to_addr="1234", from_addr="5678", transport_name="bench", transport_type="sms", content="Batch: %d. Msg: %d" % (batch_no, i)) for i in range(num_msgs) ]
def mkmsg(content): return TransportUserMessage( from_addr='from', to_addr='to', transport_name='sphex', transport_type='test', transport_metadata={}, content=content, )
def handle_raw_inbound_message(self, request): try: data = json.loads(request.content.read()) msg = TransportUserMessage(_process_fields=True, **to_kwargs(data)) yield self.handle_inbound_message(msg) request.finish() except Exception as e: log.err(e) request.setResponseCode(400) request.finish()
def test_inbound(self): d = http_request(self.worker_url + "foo", '', method='GET') msg, = yield self.broker.wait_messages("vumi", "test_ok_transport.inbound", 1) payload = msg.payload tum = TransportUserMessage(**payload) rep = tum.reply("OK") self.broker.publish_message("vumi", "test_ok_transport.outbound", rep) response = yield d self.assertEqual(response, 'OK')
def send(self, content, session_event=None): msg = TransportUserMessage(content=content, session_event=session_event, from_addr='+1234', to_addr='+134567', transport_name='test', transport_type='fake', transport_metadata={}) self.broker.publish_message('vumi', '%s.inbound' % self.transport_name, msg) yield self.broker.kick_delivery()
def publish_message(self, **kw): """ Publish a :class:`TransportUserMessage` message. Some default parameters are handled, so subclasses don't have to provide a lot of boilerplate. """ kw.setdefault('transport_name', self.transport_name) kw.setdefault('transport_metadata', {}) msg = TransportUserMessage(**kw) return self.connectors[self.transport_name].publish_inbound(msg)
def mk_msg(self, **kwargs): defaults = { 'to_addr': '27761234567', 'from_addr': '27761234567', 'content': 'hello world', 'transport_name': self.transport_name, 'transport_type': 'sms', 'transport_metadata': {}, } defaults.update(kwargs) return TransportUserMessage(**defaults)
def mkmsg_out(self, transport_name, content='hello world', **kw): msg_kw = dict( to_addr='+41791234567', from_addr='9292', transport_name=transport_name, transport_type='sms', transport_metadata={}, content=content, ) msg_kw.update(kw) return TransportUserMessage(**msg_kw)
def make_message(self, **extra_fields): fields = dict( # message_id='abc', to_addr='+27831234567', from_addr='12345', # content='heya', transport_name='sphex', transport_type='sms', # transport_metadata={}, ) fields.update(extra_fields) return TransportUserMessage(**fields)
def mkmsg_out(self, in_reply_to=None): return TransportUserMessage( to_addr='+41791234567', from_addr='9292', message_id='1', transport_name='vas2nets', transport_type='sms', transport_metadata={ 'network_id': 'network-id', }, content='hello world', in_reply_to=in_reply_to, )
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)
def publish_message(self, **kw): """ Publish a :class:`TransportUserMessage` message. Some default parameters are handled, so subclasses don't have to provide a lot of boilerplate. """ kw.setdefault('transport_name', self.transport_name) kw.setdefault('transport_metadata', {}) msg = TransportUserMessage(**kw) d = self._middlewares.apply_publish("inbound", msg, self.transport_name) d.addCallback(self.message_publisher.publish_message) return d
def test_consume_events(self): conversation = yield self.setup_conversation() yield self.app_helper.start_conversation(conversation) batch_id = conversation.batch.key yield self.app_helper.dispatch_command( "bulk_send", user_account_key=conversation.user_account.key, conversation_key=conversation.key, batch_id=batch_id, dedupe=False, content="hello world", delivery_class="sms", msg_options={}, ) window_id = self.app.get_window_id(conversation.key, batch_id) yield self.app_helper.kick_delivery() self.clock.advance(self.app.monitor_interval + 1) yield self.wait_for_window_monitor() [msg1, msg2] = yield self.app_helper.get_dispatched_outbound() yield self.app_helper.store_outbound( conversation, TransportUserMessage(**msg1.payload)) yield self.app_helper.store_outbound( conversation, TransportUserMessage(**msg2.payload)) # We should have two in flight self.assertEqual( (yield self.app.window_manager.count_in_flight(window_id)), 2) # Create an ack and a nack for the messages yield self.app_helper.make_dispatch_ack(msg1) yield self.app_helper.make_dispatch_nack(msg2, nack_reason='unknown') # We should have zero in flight self.assertEqual( (yield self.app.window_manager.count_in_flight(window_id)), 0)
def reply_to(self, msg, content, continue_session=True, **kw): session_event = (None if continue_session else TransportUserMessage.SESSION_CLOSE) reply = TransportUserMessage( to_addr=msg['from_addr'], from_addr=msg['to_addr'], group=msg['group'], in_reply_to=msg['message_id'], content=content, session_event=session_event, transport_name=msg['transport_name'], transport_type=msg['transport_type'], transport_metadata=msg['transport_metadata'], helper_metadata=msg['helper_metadata'], **kw) yield self.dispatch(reply)
def match_results(self, batch_id, direction, token, start, stop): path = 'batch/%s/%s/match/' % (batch_id, direction) response = self.do_get(path, params={ 'token': token, 'start': start, 'stop': stop, }) in_progress = bool(int(response.headers['x-vms-match-in-progress'])) total_count = int(response.headers['x-vms-result-count']) results = [ TransportUserMessage(_process_fields=False, **payload) for payload in response.json ] return in_progress, total_count, results
def test_inbound_begin(self): deferred = self.mk_request(INPUT="*120*1#") [msg] = yield self.wait_for_dispatched_messages(1) self.assertEqual(msg['content'], '*120*1#') self.assertEqual(msg['to_addr'], '*120*1#') self.assertEqual(msg['from_addr'], '27761234567'), self.assertEqual(msg['session_event'], TransportUserMessage.SESSION_NEW) self.assertEqual(msg['transport_metadata'], { 'session_id': '1', }) reply = TransportUserMessage(**msg.payload).reply("ussd message") self.dispatch(reply) response = yield deferred self.assertEqual(response, '1|ussd message|null|null|null|null')
def test_outbound_message(self): transport = yield self.mk_transport() yield self.dispatch(TransportUserMessage( to_addr='*****@*****.**', from_addr='*****@*****.**', content='hello world', transport_name='test_xmpp', transport_type='xmpp', transport_metadata={}), rkey='test_xmpp.outbound') xmlstream = transport.xmpp_protocol.xmlstream self.assertEqual(len(xmlstream.outbox), 1) message = xmlstream.outbox[0] self.assertEqual(message['to'], '*****@*****.**') self.assertTrue(message['id']) self.assertEqual(str(message.children[0]), 'hello world')