示例#1
0
    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')
示例#2
0
    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))
示例#3
0
    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)
        )
示例#4
0
    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
示例#5
0
    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
示例#6
0
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)
示例#7
0
    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))
示例#8
0
    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))
示例#9
0
    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))
示例#10
0
    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
示例#11
0
    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
示例#12
0
    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")
示例#13
0
    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')
示例#14
0
    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')
示例#15
0
    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"))
示例#16
0
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)
示例#17
0
    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")
示例#18
0
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)
示例#19
0
文件: tasks.py 项目: qoda/rapidpro
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)
示例#20
0
    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"))
示例#21
0
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)
示例#22
0
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)
示例#23
0
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)
示例#24
0
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)