def test_send(self): patch_channel_url = Mock() patch_channel_url.return_value = '/the/channel/' self.type = WhatsAppDirectType() responses.add( responses.POST, 'https://wassup.p16n.org/api/v1/messages/', json={ 'uuid': 'the-uuid', }) joe = self.create_contact("Joe Biden", "+254788383383") msg = joe.send("Hey Joe, it's Obama, pick up!", self.admin)[0] msg_struct = dict_to_struct( 'MsgStruct', msg.as_task_json()) channel_struct = dict_to_struct( 'ChannelStruct', self.channel.as_cached_json()) with patch('temba.channels.models.Channel.success') as patch_success: self.type.send(channel_struct, msg_struct, 'hello world') [(args, kwargs)] = patch_success.call_args_list self.assertEqual(args[0], channel_struct) self.assertEqual(args[1], msg_struct) self.assertEqual(kwargs['external_id'], 'the-uuid')
def __init__(self, status_code, text, method="GET", url="http://foo.com/", headers=None): if headers is None: headers = {} self.text = force_text(text) self.content = force_bytes(text) self.body = force_text(text) self.status_code = status_code self.headers = CaseInsensitiveDict(data=headers) self.url = url self.ok = True self.cookies = dict() self.streaming = False self.charset = "utf-8" self.connection = dict() self.raw = dict_to_struct( "MockRaw", dict(version="1.1", status=status_code, headers=headers)) self.reason = "" # mock up a request object on our response as well self.request = dict_to_struct( "MockRequest", dict(method=method, url=url, body="request body", headers=headers))
def __init__(self, status_code: int, body, method="GET", url="http://foo.com/", headers=None): if headers is None: headers = {} # convert dictionaries to json if the body is passed that way if isinstance(body, dict): body = json.dumps(body) self.body = force_text(body) self.text = self.body self.content = force_bytes(self.body) self.status_code = status_code self.headers = CaseInsensitiveDict(data=headers) self.url = url self.ok = True self.cookies = dict() self.streaming = False self.charset = "utf-8" self.connection = dict() self.raw = dict_to_struct("MockRaw", dict(version="1.1", status=status_code, headers=headers)) self.reason = "" # mock up a request object on our response as well self.request = dict_to_struct( "MockRequest", dict(method=method, url=url, body="request body", headers=headers) )
def test_send(self): joe = self.create_contact("Joe", "+250788383383") self.create_group("Reporters", [joe]) inbound = Msg.create_incoming(self.channel, "tel:+250788383383", "Send an inbound message", external_id='vumi-message-id', msg_type=USSD) msg = inbound.reply("Test message", self.admin, trigger_send=False)[0] self.assertEqual(inbound.msg_type, USSD) self.assertEqual(msg.msg_type, USSD) # our outgoing message msg.refresh_from_db() r = get_redis_connection() try: settings.SEND_MESSAGES = True with patch('requests.put') as mock: mock.return_value = MockResponse(200, '{ "message_id": "1515" }') # manually send it off Channel.send_message( dict_to_struct('MsgStruct', msg.as_task_json())) # check the status of the message is now sent msg.refresh_from_db() self.assertEquals(WIRED, msg.status) self.assertTrue(msg.sent_on) self.assertEquals("1515", msg.external_id) self.assertEquals(1, mock.call_count) # should have a failsafe that it was sent self.assertTrue( r.sismember(timezone.now().strftime(MSG_SENT_KEY), str(msg.id))) # try sending again, our failsafe should kick in Channel.send_message( dict_to_struct('MsgStruct', msg.as_task_json())) # we shouldn't have been called again self.assertEquals(1, mock.call_count) self.clear_cache() finally: settings.SEND_MESSAGES = False
def test_send_default_url(self): joe = self.create_contact("Joe", "+250788383383") self.create_group("Reporters", [joe]) inbound = Msg.create_incoming(self.channel, "tel:+250788383383", "Send an inbound message", external_id='vumi-message-id') msg = inbound.reply("Test message", self.admin, trigger_send=False) # our outgoing message msg.refresh_from_db() try: settings.SEND_MESSAGES = True with patch('requests.put') as mock: mock.return_value = MockResponse(200, '{ "message_id": "1515" }') # manually send it off Channel.send_message( dict_to_struct('MsgStruct', msg.as_task_json())) self.assertEqual( mock.call_args[0][0], 'https://go.vumi.org/api/v1/go/http_api_nostream/key/messages.json' ) self.clear_cache() finally: settings.SEND_MESSAGES = False
def send_msg_task(): """ Pops the next message off of our msg queue to send. """ # pop off the next task msg_tasks = pop_task(SEND_MSG_TASK) # it is possible we have no message to send, if so, just return if not msg_tasks: return if not isinstance(msg_tasks, list): msg_tasks = [msg_tasks] r = get_redis_connection() # acquire a lock on our contact to make sure two sets of msgs aren't being sent at the same time try: with r.lock('send_contact_%d' % msg_tasks[0]['contact'], timeout=300): # send each of our msgs while msg_tasks: msg_task = msg_tasks.pop(0) msg = dict_to_struct('MockMsg', msg_task, datetime_fields=['modified_on', 'sent_on', 'created_on', 'queued_on', 'next_attempt']) Channel.send_message(msg) # if there are more messages to send for this contact, sleep a second before moving on if msg_tasks: time.sleep(1) finally: # pragma: no cover # if some msgs weren't sent for some reason, then requeue them for later sending if msg_tasks: # requeue any unsent msgs push_task(msg_tasks[0]['org'], MSG_QUEUE, SEND_MSG_TASK, msg_tasks)
def __init__(self, status_code, text, method='GET', url='http://foo.com/'): self.text = text self.status_code = status_code # mock up a request object on our response as well self.request = dict_to_struct('MockRequest', dict(method=method, url=url))
def __init__(self, status_code, text, method='GET', url='http://foo.com/'): self.text = text self.content = text self.status_code = status_code # mock up a request object on our response as well self.request = dict_to_struct('MockRequest', dict(method=method, url=url))
def __init__(self, status_code, text, method='GET', url='http://foo.com/', headers=None): self.text = text self.content = text self.status_code = status_code self.headers = headers if headers else {} # mock up a request object on our response as well self.request = dict_to_struct('MockRequest', dict(method=method, url=url))
def test_ack(self): joe = self.create_contact("Joe", "+250788383383") self.create_group("Reporters", [joe]) inbound = Msg.create_incoming(self.channel, "tel:+250788383383", "Send an inbound message", external_id='vumi-message-id', msg_type=USSD) msg = inbound.reply("Test message", self.admin, trigger_send=False)[0] # our outgoing message msg.refresh_from_db() try: settings.SEND_MESSAGES = True with patch('requests.put') as mock: mock.return_value = MockResponse(200, '{ "message_id": "1515" }') # manually send it off Channel.send_message( dict_to_struct('MsgStruct', msg.as_task_json())) # check the status of the message is now sent msg.refresh_from_db() self.assertEquals(WIRED, msg.status) self.assertTrue(msg.sent_on) self.assertEquals("1515", msg.external_id) self.assertEquals(1, mock.call_count) # simulate Vumi calling back to us sending an ACK event data = { "transport_name": "ussd_transport", "event_type": "ack", "event_id": six.text_type(uuid.uuid4()), "sent_message_id": six.text_type(uuid.uuid4()), "helper_metadata": {}, "routing_metadata": {}, "message_version": "20110921", "timestamp": six.text_type(timezone.now()), "transport_metadata": {}, "user_message_id": msg.external_id, "message_type": "event" } callback_url = reverse('handlers.vumi_handler', args=['event', self.channel.uuid]) self.client.post(callback_url, json.dumps(data), content_type="application/json") # it should be SENT now msg.refresh_from_db() self.assertEquals(SENT, msg.status) self.clear_cache() finally: settings.SEND_MESSAGES = False
def test_nack(self): joe = self.create_contact("Joe", "+250788383383") self.create_group("Reporters", [joe]) msg = joe.send("Test message", self.admin, trigger_send=False) # our outgoing message msg.refresh_from_db() r = get_redis_connection() try: settings.SEND_MESSAGES = True with patch('requests.put') as mock: mock.return_value = MockResponse(200, '{ "message_id": "1515" }') # manually send it off Channel.send_message( dict_to_struct('MsgStruct', msg.as_task_json())) # check the status of the message is now sent msg.refresh_from_db() self.assertEquals(WIRED, msg.status) self.assertTrue(msg.sent_on) self.assertEquals("1515", msg.external_id) self.assertEquals(1, mock.call_count) # should have a failsafe that it was sent self.assertTrue( r.sismember(timezone.now().strftime(MSG_SENT_KEY), str(msg.id))) # simulate Vumi calling back to us sending an NACK event data = { "transport_name": "ussd_transport", "event_type": "nack", "nack_reason": "Unknown address.", "event_id": six.text_type(uuid.uuid4()), "timestamp": six.text_type(timezone.now()), "message_version": "20110921", "transport_metadata": {}, "user_message_id": msg.external_id, "message_type": "event" } callback_url = reverse('handlers.vumi_handler', args=['event', self.channel.uuid]) response = self.client.post(callback_url, json.dumps(data), content_type="application/json") self.assertEqual(response.status_code, 200) self.assertTrue( self.create_contact("Joe", "+250788383383").is_stopped) self.clear_cache() finally: settings.SEND_MESSAGES = False
def test_channellog(self): contact = self.create_contact("Test", "+250788383383") msg = Msg.create_outgoing(self.org, self.admin, contact, "This is a test message") msg = dict_to_struct('MockMsg', msg.as_task_json()) with SegmentProfiler("Channel Log inserts (10,000)", self, force_profile=True): for i in range(10000): ChannelLog.log_success(msg, "Sent Message", method="GET", url="http://foo", request="GET http://foo", response="Ok", response_status="201")
def test_send_with_attachment(self): def cb(request): self.assertTrue('image_attachment' in request.body) return ( 201, {'Content-Type': 'application/json'}, json.dumps({'uuid': 'the-uuid'})) responses.add_callback( responses.POST, 'https://wassup.p16n.org/api/v1/messages/', callback=cb, content_type='application/json') fixture = pkg_resources.resource_filename( 'warapidpro', 'tests/fixtures/placeholder-640x640.jpg') with open(fixture, 'rb') as fp: responses.add(responses.GET, 'https://example.com/pic.jpg', body=fp.read(), content_type='image/jpg', status=200, adding_headers={'Transfer-Encoding': 'chunked'}) self.type = WhatsAppDirectType() joe = self.create_contact("Joe Biden", "+254788383383") msg = joe.send( "Hey Joe, it's Obama, pick up!", self.admin, attachments=['image/jpeg:https://example.com/pic.jpg'])[0] msg_struct = dict_to_struct( 'MsgStruct', msg.as_task_json()) channel_struct = dict_to_struct( 'ChannelStruct', self.channel.as_cached_json()) with patch('temba.channels.models.Channel.success') as patch_success: self.type.send(channel_struct, msg_struct, 'hello world') [(args, kwargs)] = patch_success.call_args_list self.assertEqual(args[0], channel_struct) self.assertEqual(args[1], msg_struct) self.assertEqual(kwargs['external_id'], 'the-uuid')
def test_send(self): patch_channel_url = Mock() patch_channel_url.return_value = '/the/channel/' self.type = WhatsAppGroupType() def cb(request): data = json.loads(request.body) self.assertEqual(data, { 'to_addr': '+254788383383', 'number': '+27000000000', 'content': 'the text to send', 'group': 'group-uuid', 'in_reply_to': '', }) return (201, {}, json.dumps({ 'uuid': 'the-uuid' })) responses.add_callback( responses.POST, 'https://wassup.p16n.org/api/v1/messages/', callback=cb, content_type='application/json') joe = self.create_contact("Joe Biden", "+254788383383") msg = joe.send("Hey Joe, it's Obama, pick up!", self.admin)[0] msg_struct = dict_to_struct( 'MsgStruct', msg.as_task_json()) channel_struct = dict_to_struct( 'ChannelStruct', self.channel.as_cached_json()) text = 'the text to send' with patch('temba.channels.models.Channel.success') as patch_success: self.type.send(channel_struct, msg_struct, text) [(args, kwargs)] = patch_success.call_args_list self.assertEqual(args[0], channel_struct) self.assertEqual(args[1], msg_struct) self.assertEqual(kwargs['external_id'], 'the-uuid')
def __init__(self, status_code, text, method="GET", url="http://foo.com/", headers=None): self.text = force_text(text) self.content = force_bytes(text) self.body = force_text(text) self.status_code = status_code self.headers = headers if headers else {} self.url = url self.ok = True self.cookies = dict() self.streaming = False self.charset = "utf-8" # mock up a request object on our response as well self.request = dict_to_struct("MockRequest", dict(method=method, url=url, body="request body"))
def send_msg_task(): """ Pops the next message off of our msg queue to send. """ # pop off the next task task = pop_task(SEND_MSG_TASK) # it is possible we have no message to send, if so, just return if not task: return msg = dict_to_struct('MockMsg', task, datetime_fields=['delivered_on', 'sent_on', 'created_on', 'queued_on', 'next_attempt']) # send it off Channel.send_message(msg)
def send_msg_task(): """ Pops the next message off of our msg queue to send. """ # pop off the next task cur_task = pop_task(SEND_MSG_TASK) # it is possible we have no message to send, if so, just return if not cur_task: return msg = dict_to_struct('MockMsg', cur_task, datetime_fields=['modified_on', 'sent_on', 'created_on', 'queued_on', 'next_attempt']) # send it off r = get_redis_connection() with r.lock('send_msg_%d' % msg.id, timeout=300): Channel.send_message(msg)
def send_msg_task(): """ Pops the next message off of our msg queue to send. """ # pop off the next task org_id, msg_tasks = start_task(SEND_MSG_TASK) # it is possible we have no message to send, if so, just return if not msg_tasks: # pragma: needs cover return if not isinstance(msg_tasks, list): # pragma: needs cover msg_tasks = [msg_tasks] r = get_redis_connection() # acquire a lock on our contact to make sure two sets of msgs aren't being sent at the same time try: with r.lock("send_contact_%d" % msg_tasks[0]["contact"], timeout=300): # send each of our msgs while msg_tasks: msg_task = msg_tasks.pop(0) msg = dict_to_struct( "MockMsg", msg_task, datetime_fields=[ "modified_on", "sent_on", "created_on", "queued_on", "next_attempt" ], ) Channel.send_message(msg) # if there are more messages to send for this contact, sleep a second before moving on if msg_tasks: time.sleep(1) finally: # pragma: no cover # mark this worker as done complete_task(SEND_MSG_TASK, org_id) # if some msgs weren't sent for some reason, then requeue them for later sending if msg_tasks: # requeue any unsent msgs push_task(org_id, MSG_QUEUE, SEND_MSG_TASK, msg_tasks)
def __init__(self, status_code, text, method="GET", url="http://foo.com/", headers=None): self.text = force_text(text) self.content = force_bytes(text) self.body = force_text(text) self.status_code = status_code self.headers = headers if headers else {} self.url = url self.ok = True self.cookies = dict() self.streaming = False self.charset = "utf-8" # mock up a request object on our response as well self.request = dict_to_struct( "MockRequest", dict(method=method, url=url, body="request body"))
def send_msg_task(): """ Pops the next message off of our msg queue to send. """ # pop off the next task task = pop_task(SEND_MSG_TASK) # it is possible we have no message to send, if so, just return if not task: return msg = dict_to_struct('MockMsg', task, datetime_fields=[ 'delivered_on', 'sent_on', 'created_on', 'queued_on', 'next_attempt' ]) # send it off Channel.send_message(msg)
def send_msg_task(): """ Pops the next message off of our msg queue to send. """ logger = send_msg_task.get_logger() # pop off the next task task = pop_task(SEND_MSG_TASK) # it is possible we have no message to send, if so, just return if not task: return msg = dict_to_struct('MockMsg', task, datetime_fields=['modified_on', 'sent_on', 'created_on', 'queued_on', 'next_attempt']) # send it off r = get_redis_connection() with r.lock('send_msg_%d' % msg.id, timeout=300): Channel.send_message(msg)
def send_msg_task(): """ Pops the next message off of our msg queue to send. """ # pop off the next task org_id, msg_tasks = start_task(SEND_MSG_TASK) # it is possible we have no message to send, if so, just return if not msg_tasks: # pragma: needs cover return if not isinstance(msg_tasks, list): # pragma: needs cover msg_tasks = [msg_tasks] r = get_redis_connection() # acquire a lock on our contact to make sure two sets of msgs aren't being sent at the same time try: with r.lock("send_contact_%d" % msg_tasks[0]["contact"], timeout=300): # send each of our msgs while msg_tasks: msg_task = msg_tasks.pop(0) msg = dict_to_struct( "MockMsg", msg_task, datetime_fields=["modified_on", "sent_on", "created_on", "queued_on", "next_attempt"], ) Channel.send_message(msg) # if there are more messages to send for this contact, sleep a second before moving on if msg_tasks: time.sleep(1) finally: # pragma: no cover # mark this worker as done complete_task(SEND_MSG_TASK, org_id) # if some msgs weren't sent for some reason, then requeue them for later sending if msg_tasks: # requeue any unsent msgs push_task(org_id, MSG_QUEUE, SEND_MSG_TASK, msg_tasks)
def send_msg_task(): """ Pops the next message off of our msg queue to send. """ logger = send_msg_task.get_logger() try: # pop off the next task task = pop_task(SEND_MSG_TASK) # it is possible we have no message to send, if so, just return if not task: return msg = dict_to_struct('MockMsg', task, datetime_fields=['delivered_on', 'sent_on', 'created_on', 'queued_on', 'next_attempt']) # send it off Channel.send_message(msg) except Exception as e: logger.exception("Error sending msg: %d" % msg.id)