Beispiel #1
0
def send_spam(user_id, contact_id):  # pragma: no cover
    """
    Processses a single incoming message through our queue.
    """
    from django.contrib.auth.models import User
    from temba.contacts.models import Contact, TEL_SCHEME
    from temba.msgs.models import Broadcast

    contact = Contact.all().get(pk=contact_id)
    user = User.objects.get(pk=user_id)
    channel = contact.org.get_send_channel(TEL_SCHEME)

    if not channel:  # pragma: no cover
        print("Sorry, no channel to be all spammy with")
        return

    long_text = (
        "Test Message #%d. The path of the righteous man is beset on all sides by the iniquities of the "
        "selfish and the tyranny of evil men. Blessed is your face."
    )

    # only trigger sync on the last one
    for idx in range(10):
        broadcast = Broadcast.create(contact.org, user, long_text % (idx + 1), contacts=[contact])
        broadcast.send(trigger_send=(idx == 149))
Beispiel #2
0
    def save(self):
        """
        Create a new broadcast to send out
        """
        contact_urns = []
        for urn in self.validated_data.get("urns", []):
            # create contacts for URNs if necessary
            __, contact_urn = Contact.get_or_create(self.context["org"], urn, user=self.context["user"])
            contact_urns.append(contact_urn)

        text, base_language = self.validated_data["text"]

        # create the broadcast
        broadcast = Broadcast.create(
            self.context["org"],
            self.context["user"],
            text=text,
            base_language=base_language,
            groups=self.validated_data.get("groups", []),
            contacts=self.validated_data.get("contacts", []),
            urns=contact_urns,
            channel=self.validated_data.get("channel"),
        )

        # send in task
        on_transaction_commit(lambda: send_broadcast_task.delay(broadcast.id))

        return broadcast
Beispiel #3
0
    def restore_object(self, attrs, instance=None):
        """
        Create a new broadcast to send out
        """
        if instance: # pragma: no cover
            raise ValidationError("Invalid operation")

        user = self.user
        org = self.org

        if 'urn' in attrs and attrs['urn']:
            urns = attrs.get('urn', [])
        else:
            urns = attrs.get('phone', [])

        channel = attrs['channel']
        contacts = list()
        for urn in urns:
            # treat each urn as a separate contact
            contacts.append(Contact.get_or_create(user, channel.org, urns=[urn], channel=channel))

        # add any contacts specified by uuids
        uuid_contacts = attrs.get('contact', [])
        for contact in uuid_contacts:
            contacts.append(contact)

        # create the broadcast
        broadcast = Broadcast.create(org, user, attrs['text'], recipients=contacts)

        # send it
        broadcast.send()
        return broadcast
Beispiel #4
0
    def save(self):
        """
        Create a new broadcast to send out
        """
        if "urn" in self.validated_data and self.validated_data["urn"]:
            urns = self.validated_data.get("urn")
        else:
            urns = self.validated_data.get("phone", [])

        channel = self.validated_data.get("channel")
        contacts = list()
        for urn in urns:
            # treat each urn as a separate contact
            contact, urn_obj = Contact.get_or_create(channel.org, urn, user=self.user)
            contacts.append(contact)

        # add any contacts specified by uuids
        uuid_contacts = self.validated_data.get("contact", [])
        for contact in uuid_contacts:
            contacts.append(contact)

        # create the broadcast
        broadcast = Broadcast.create(
            self.org, self.user, self.validated_data["text"], contacts=contacts, channel=channel
        )

        # send it
        broadcast.send(expressions_context={})
        return broadcast
Beispiel #5
0
    def test_update_near_day_boundary(self):

        self.org.timezone = 'US/Eastern'
        self.org.save()
        tz = pytz.timezone(self.org.timezone)

        sched = self.create_schedule('D')
        Broadcast.create(self.org, self.admin, 'Message', [], schedule=sched)
        sched = Schedule.objects.get(pk=sched.pk)

        update_url = reverse('schedules.schedule_update', args=[sched.pk])

        self.login(self.admin)

        # way off into the future
        start_date = datetime(2050, 1, 3, 23, 0, 0, 0)
        start_date = tz.localize(start_date)
        start_date = pytz.utc.normalize(start_date.astimezone(pytz.utc))

        post_data = dict()
        post_data['repeat_period'] = 'D'
        post_data['start'] = 'later'
        post_data['start_datetime_value'] = "%d" % time.mktime(start_date.timetuple())
        self.client.post(update_url, post_data)
        sched = Schedule.objects.get(pk=sched.pk)

        # 11pm in NY should be 4am UTC the next day
        self.assertEquals('2050-01-04 04:00:00+00:00', unicode(sched.next_fire))

        # a time in the past
        start_date = datetime(2010, 1, 3, 23, 45, 0, 0)
        start_date = tz.localize(start_date)
        start_date = pytz.utc.normalize(start_date.astimezone(pytz.utc))

        post_data = dict()
        post_data['repeat_period'] = 'D'
        post_data['start'] = 'later'
        post_data['start_datetime_value'] = "%d" % time.mktime(start_date.timetuple())
        self.client.post(update_url, post_data)
        sched = Schedule.objects.get(pk=sched.pk)

        # next fire should fall at the right hour and minute
        self.assertIn('04:45:00+00:00', unicode(sched.next_fire))
Beispiel #6
0
    def test_calculating_next_fire(self):

        self.org.timezone = 'US/Eastern'
        self.org.save()

        tz = self.org.get_tzinfo()
        eleven_pm_est = datetime(2013, 1, 3, hour=23, minute=0, second=0, microsecond=0).replace(tzinfo=tz)

        # Test date is 10am on a Thursday, Jan 3rd
        schedule = self.create_schedule('D', start_date=eleven_pm_est)
        schedule.save()

        Broadcast.create(self.org, self.admin, 'Message', [], schedule=schedule)
        schedule = Schedule.objects.get(pk=schedule.pk)

        # when is the next fire once our first one passes
        sched_date = datetime(2013, 1, 3, hour=23, minute=30, second=0, microsecond=0).replace(tzinfo=tz)
        schedule.update_schedule(sched_date)
        self.assertEquals('2013-01-04 23:00:00-05:00', unicode(schedule.next_fire))
Beispiel #7
0
    def test_update_near_day_boundary(self):

        self.org.timezone = pytz.timezone("US/Eastern")
        self.org.save()
        tz = self.org.timezone

        sched = self.create_schedule("D")
        Broadcast.create(self.org, self.admin, "Message", schedule=sched, contacts=[self.joe])
        sched = Schedule.objects.get(pk=sched.pk)

        update_url = reverse("schedules.schedule_update", args=[sched.pk])

        self.login(self.admin)

        # way off into the future
        start_date = datetime(2050, 1, 3, 23, 0, 0, 0)
        start_date = tz.localize(start_date)
        start_date = pytz.utc.normalize(start_date.astimezone(pytz.utc))

        post_data = dict()
        post_data["repeat_period"] = "D"
        post_data["start"] = "later"
        post_data["start_datetime_value"] = "%d" % time.mktime(start_date.timetuple())
        self.client.post(update_url, post_data)
        sched = Schedule.objects.get(pk=sched.pk)

        # 11pm in NY should be 4am UTC the next day
        self.assertEqual("2050-01-04 04:00:00+00:00", str(sched.next_fire))

        # a time in the past
        start_date = datetime(2010, 1, 3, 23, 45, 0, 0)
        start_date = tz.localize(start_date)
        start_date = pytz.utc.normalize(start_date.astimezone(pytz.utc))

        post_data = dict()
        post_data["repeat_period"] = "D"
        post_data["start"] = "later"
        post_data["start_datetime_value"] = "%d" % time.mktime(start_date.timetuple())
        self.client.post(update_url, post_data)
        sched = Schedule.objects.get(pk=sched.pk)

        # next fire should fall at the right hour and minute
        self.assertIn("04:45:00+00:00", str(sched.next_fire))
Beispiel #8
0
    def test_update_near_day_boundary(self):

        self.org.timezone = pytz.timezone("US/Eastern")
        self.org.save()
        tz = self.org.timezone

        sched = self.create_schedule("D")
        Broadcast.create(self.org, self.admin, "Message", schedule=sched, contacts=[self.joe])
        sched = Schedule.objects.get(pk=sched.pk)

        update_url = reverse("schedules.schedule_update", args=[sched.pk])

        self.login(self.admin)

        # way off into the future
        start_date = datetime(2050, 1, 3, 23, 0, 0, 0)
        start_date = tz.localize(start_date)
        start_date = pytz.utc.normalize(start_date.astimezone(pytz.utc))

        post_data = dict()
        post_data["repeat_period"] = "D"
        post_data["start"] = "later"
        post_data["start_datetime_value"] = "%d" % time.mktime(start_date.timetuple())
        self.client.post(update_url, post_data)
        sched = Schedule.objects.get(pk=sched.pk)

        # 11pm in NY should be 4am UTC the next day
        self.assertEqual("2050-01-04 04:00:00+00:00", str(sched.next_fire))

        # a time in the past
        start_date = datetime(2010, 1, 3, 23, 45, 0, 0)
        start_date = tz.localize(start_date)
        start_date = pytz.utc.normalize(start_date.astimezone(pytz.utc))

        post_data = dict()
        post_data["repeat_period"] = "D"
        post_data["start"] = "later"
        post_data["start_datetime_value"] = "%d" % time.mktime(start_date.timetuple())
        self.client.post(update_url, post_data)
        sched = Schedule.objects.get(pk=sched.pk)

        # next fire should fall at the right hour and minute
        self.assertIn("04:45:00+00:00", str(sched.next_fire))
Beispiel #9
0
    def test_calculating_next_fire(self):

        self.org.timezone = pytz.timezone('US/Eastern')
        self.org.save()

        tz = self.org.timezone
        eleven_fifteen_est = tz.localize(datetime(2013, 1, 3, hour=23, minute=15, second=0, microsecond=0))

        # Test date is 10:15am on a Thursday, Jan 3rd
        schedule = self.create_schedule('D', start_date=eleven_fifteen_est)
        schedule.save()

        Broadcast.create(self.org, self.admin, 'Message', [], schedule=schedule)
        schedule = Schedule.objects.get(pk=schedule.pk)

        # when is the next fire once our first one passes
        sched_date = tz.localize(datetime(2013, 1, 3, hour=23, minute=30, second=0, microsecond=0))

        schedule.update_schedule(sched_date)
        self.assertEquals('2013-01-04 23:15:00-05:00', unicode(schedule.next_fire))
Beispiel #10
0
    def test_calculating_next_fire(self):

        self.org.timezone = pytz.timezone("US/Eastern")
        self.org.save()

        tz = self.org.timezone
        eleven_fifteen_est = tz.localize(datetime(2013, 1, 3, hour=23, minute=15, second=0, microsecond=0))

        # Test date is 10:15am on a Thursday, Jan 3rd
        schedule = self.create_schedule("D", start_date=eleven_fifteen_est)
        schedule.save()

        Broadcast.create(self.org, self.admin, "Message", schedule=schedule, contacts=[self.joe])
        schedule = Schedule.objects.get(pk=schedule.pk)

        # when is the next fire once our first one passes
        sched_date = tz.localize(datetime(2013, 1, 3, hour=23, minute=30, second=0, microsecond=0))

        schedule.update_schedule(sched_date)
        self.assertEqual("2013-01-04 23:15:00-05:00", str(schedule.next_fire))
Beispiel #11
0
    def test_broadcasts(self):
        url = reverse('api.v2.broadcasts')

        self.assertEndpointAccess(url)

        reporters = self.create_group("Reporters", [self.joe, self.frank])

        bcast1 = Broadcast.create(self.org, self.admin, "Hello 1",
                                  [self.frank.get_urn('twitter')])
        bcast2 = Broadcast.create(self.org, self.admin, "Hello 2", [self.joe])
        bcast3 = Broadcast.create(self.org,
                                  self.admin,
                                  "Hello 3", [self.frank],
                                  status='S')
        bcast4 = Broadcast.create(
            self.org,
            self.admin,
            "Hello 4", [self.frank.get_urn('twitter'), self.joe, reporters],
            status='F')
        Broadcast.create(self.org2, self.admin2, "Different org...",
                         [self.hans])

        # no filtering
        with self.assertNumQueries(NUM_BASE_REQUEST_QUERIES + 5):
            response = self.fetchJSON(url)

        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.json['next'], None)
        self.assertResultsById(response, [bcast4, bcast3, bcast2, bcast1])
        self.assertEqual(
            response.json['results'][0], {
                'id': bcast4.pk,
                'urns': ["twitter:franky"],
                'contacts': [{
                    'uuid': self.joe.uuid,
                    'name': self.joe.name
                }],
                'groups': [{
                    'uuid': reporters.uuid,
                    'name': reporters.name
                }],
                'text': "Hello 4",
                'created_on': format_datetime(bcast4.created_on),
                'status': "failed"
            })

        # filter by id
        response = self.fetchJSON(url, 'id=%d' % bcast3.pk)
        self.assertResultsById(response, [bcast3])

        # filter by after
        response = self.fetchJSON(
            url, 'after=%s' % format_datetime(bcast3.created_on))
        self.assertResultsById(response, [bcast4, bcast3])

        # filter by before
        response = self.fetchJSON(
            url, 'before=%s' % format_datetime(bcast2.created_on))
        self.assertResultsById(response, [bcast2, bcast1])
Beispiel #12
0
    def test_queue_broadcast(self):
        jim = self.create_contact("Jim", phone="+12065551212")
        bobs = self.create_group(
            "Bobs", [self.create_contact("Bob", phone="+12065551313")])
        ticketer = Ticketer.create(self.org, self.admin, "mailgun",
                                   "Support Tickets", {})
        ticket = self.create_ticket(ticketer, jim, "Help!")

        bcast = Broadcast.create(
            self.org,
            self.admin,
            {
                "eng": "Welcome to mailroom!",
                "spa": "¡Bienvenidx a mailroom!"
            },
            groups=[bobs],
            contacts=[jim],
            urns=["tel:+12065556666"],
            base_language="eng",
            ticket=ticket,
        )

        bcast.send_async()

        self.assert_org_queued(self.org, "batch")
        self.assert_queued_batch_task(
            self.org,
            {
                "type": "send_broadcast",
                "org_id": self.org.id,
                "task": {
                    "translations": {
                        "eng": {
                            "text": "Welcome to mailroom!"
                        },
                        "spa": {
                            "text": "\u00a1Bienvenidx a mailroom!"
                        },
                    },
                    "template_state": "legacy",
                    "base_language": "eng",
                    "urns": ["tel:+12065556666"],
                    "contact_ids": [jim.id],
                    "group_ids": [bobs.id],
                    "broadcast_id": bcast.id,
                    "org_id": self.org.id,
                    "ticket_id": ticket.id,
                },
                "queued_on": matchers.ISODate(),
            },
        )
Beispiel #13
0
    def test_queue_broadcast(self):
        jim = self.create_contact("Jim", "+12065551212")
        bobs = self.create_group("Bobs",
                                 [self.create_contact("Bob", "+12065551313")])

        bcast = Broadcast.create(
            self.org,
            self.admin,
            {
                "eng": "Welcome to mailroom!",
                "spa": "¡Bienvenidx a mailroom!"
            },
            groups=[bobs],
            contacts=[jim],
            urns=[jim.urns.get()],
            base_language="eng",
        )

        with override_settings(TESTING=False):
            bcast.send()

        self.assert_org_queued(self.org, "batch")
        self.assert_queued_batch_task(
            self.org,
            {
                "type": "send_broadcast",
                "org_id": self.org.id,
                "task": {
                    "translations": {
                        "eng": {
                            "text": "Welcome to mailroom!"
                        },
                        "spa": {
                            "text": "\u00a1Bienvenidx a mailroom!"
                        },
                    },
                    "template_state": "legacy",
                    "base_language": "eng",
                    "urns": ["tel:+12065551212"],
                    "contact_ids": [jim.id],
                    "group_ids": [bobs.id],
                    "broadcast_id": bcast.id,
                    "org_id": self.org.id,
                },
                "queued_on": matchers.ISODate(),
            },
        )
Beispiel #14
0
    def create_broadcast(
        self,
        user,
        text,
        contacts=(),
        groups=(),
        response_to=None,
        msg_status=Msg.STATUS_SENT,
        parent=None,
        schedule=None,
    ):
        bcast = Broadcast.create(
            self.org,
            user,
            text,
            contacts=contacts,
            groups=groups,
            status=Msg.STATUS_SENT,
            parent=parent,
            schedule=schedule,
        )

        contacts = set(bcast.contacts.all())
        for group in bcast.groups.all():
            contacts.update(group.contacts.all())

        if not schedule:
            for contact in contacts:
                self._create_msg(
                    contact,
                    text,
                    Msg.DIRECTION_OUT,
                    channel=None,
                    msg_type=Msg.TYPE_INBOX,
                    attachments=(),
                    status=msg_status,
                    created_on=timezone.now(),
                    sent_on=timezone.now(),
                    response_to=response_to,
                    broadcast=bcast,
                )

        return bcast
Beispiel #15
0
    def save(self):
        """
        Create a new broadcast to send out
        """
        from temba.msgs.tasks import send_broadcast_task

        recipients = self.validated_data.get('contacts', []) + self.validated_data.get('groups', [])

        for urn in self.validated_data.get('urns', []):
            # create contacts for URNs if necessary
            contact = Contact.get_or_create(self.context['org'], self.context['user'], urns=[urn])
            contact_urn = contact.urn_objects[urn]
            recipients.append(contact_urn)

        # create the broadcast
        broadcast = Broadcast.create(self.context['org'], self.context['user'], self.validated_data['text'],
                                     recipients=recipients, channel=self.validated_data.get('channel'))

        # send in task
        send_broadcast_task.delay(broadcast.id)
        return broadcast
Beispiel #16
0
    def save(self):
        """
        Create a new broadcast to send out
        """
        from temba.msgs.tasks import send_broadcast_task

        recipients = self.validated_data.get('contacts', []) + self.validated_data.get('groups', [])

        for urn in self.validated_data.get('urns', []):
            # create contacts for URNs if necessary
            contact = Contact.get_or_create(self.context['org'], self.context['user'], urns=[urn])
            contact_urn = contact.urn_objects[urn]
            recipients.append(contact_urn)

        # create the broadcast
        broadcast = Broadcast.create(self.context['org'], self.context['user'], self.validated_data['text'],
                                     recipients=recipients, channel=self.validated_data.get('channel'))

        # send in task
        send_broadcast_task.delay(broadcast.id)
        return broadcast
Beispiel #17
0
    def setUpBeforeMigration(self, apps):
        contact1 = self.create_contact("Bob", twitter="bob")
        favorites = self.get_flow("favorites")

        # create schedule attached to a trigger
        self.trigger = Trigger.create(self.org,
                                      self.admin,
                                      Trigger.TYPE_SCHEDULE,
                                      flow=favorites,
                                      schedule=create_schedule(
                                          self.admin, "D"))

        # create schedule attached to a broadcast
        self.broadcast = Broadcast.create(self.org,
                                          self.admin,
                                          "hi there",
                                          contacts=[contact1],
                                          schedule=create_schedule(
                                              self.admin, "W"))

        # create orphan schedule
        create_schedule(self.admin, "M")
Beispiel #18
0
def send_spam(user_id, contact_id):  # pragma: no cover
    """
    Processses a single incoming message through our queue.
    """
    from django.contrib.auth.models import User
    from temba.contacts.models import Contact, TEL_SCHEME
    from temba.msgs.models import Broadcast

    contact = Contact.all().get(pk=contact_id)
    user = User.objects.get(pk=user_id)
    channel = contact.org.get_send_channel(TEL_SCHEME)

    if not channel:  # pragma: no cover
        print("Sorry, no channel to be all spammy with")
        return

    long_text = "Test Message #%d. The path of the righteous man is beset on all sides by the iniquities of the " "selfish and the tyranny of evil men. Blessed is your face."

    # only trigger sync on the last one
    for idx in range(10):
        broadcast = Broadcast.create(contact.org, user, long_text % (idx + 1), contacts=[contact])
        broadcast.send(trigger_send=(idx == 149))
Beispiel #19
0
    def restore_object(self, attrs, instance=None):
        """
        Create a new broadcast to send out
        """
        if instance:  # pragma: no cover
            raise ValidationError("Invalid operation")

        user = self.user
        org = self.org

        if 'urn' in attrs and attrs['urn']:
            urns = attrs.get('urn', [])
        else:
            urns = attrs.get('phone', [])

        channel = attrs['channel']
        contacts = list()
        for urn in urns:
            # treat each urn as a separate contact
            contacts.append(
                Contact.get_or_create(user,
                                      channel.org,
                                      urns=[urn],
                                      channel=channel))

        # add any contacts specified by uuids
        uuid_contacts = attrs.get('contact', [])
        for contact in uuid_contacts:
            contacts.append(contact)

        # create the broadcast
        broadcast = Broadcast.create(org,
                                     user,
                                     attrs['text'],
                                     recipients=contacts)

        # send it
        broadcast.send()
        return broadcast
Beispiel #20
0
    def test_broadcasts(self):
        url = reverse('api.v2.broadcasts')

        self.assertEndpointAccess(url)

        reporters = self.create_group("Reporters", [self.joe, self.frank])

        bcast1 = Broadcast.create(self.org, self.admin, "Hello 1", [self.frank.get_urn('twitter')])
        bcast2 = Broadcast.create(self.org, self.admin, "Hello 2", [self.joe])
        bcast3 = Broadcast.create(self.org, self.admin, "Hello 3", [self.frank], status='S')
        bcast4 = Broadcast.create(self.org, self.admin, "Hello 4",
                                  [self.frank.get_urn('twitter'), self.joe, reporters], status='F')
        Broadcast.create(self.org2, self.admin2, "Different org...", [self.hans])

        # no filtering
        with self.assertNumQueries(NUM_BASE_REQUEST_QUERIES + 5):
            response = self.fetchJSON(url)

        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.json['next'], None)
        self.assertResultsById(response, [bcast4, bcast3, bcast2, bcast1])
        self.assertEqual(response.json['results'][0], {
            'id': bcast4.pk,
            'urns': ["twitter:franky"],
            'contacts': [{'uuid': self.joe.uuid, 'name': self.joe.name}],
            'groups': [{'uuid': reporters.uuid, 'name': reporters.name}],
            'text': "Hello 4",
            'created_on': format_datetime(bcast4.created_on)
        })

        # filter by id
        response = self.fetchJSON(url, 'id=%d' % bcast3.pk)
        self.assertResultsById(response, [bcast3])

        # filter by after
        response = self.fetchJSON(url, 'after=%s' % format_datetime(bcast3.created_on))
        self.assertResultsById(response, [bcast4, bcast3])

        # filter by before
        response = self.fetchJSON(url, 'before=%s' % format_datetime(bcast2.created_on))
        self.assertResultsById(response, [bcast2, bcast1])

        with AnonymousOrg(self.org):
            # URNs shouldn't be included
            response = self.fetchJSON(url, 'id=%d' % bcast1.pk)
            self.assertEqual(response.json['results'][0]['urns'], None)
Beispiel #21
0
    def create_broadcast(self,
                         user,
                         text,
                         contacts=(),
                         groups=(),
                         response_to=None,
                         msg_status=SENT,
                         parent=None,
                         schedule=None):
        bcast = Broadcast.create(self.org,
                                 user,
                                 text,
                                 contacts=contacts,
                                 groups=groups,
                                 status=SENT,
                                 parent=parent,
                                 schedule=schedule)

        contacts = set(bcast.contacts.all())
        for group in bcast.groups.all():
            contacts.update(group.contacts.all())

        for contact in contacts:
            self._create_msg(
                contact,
                text,
                OUTGOING,
                channel=None,
                msg_type=INBOX,
                attachments=(),
                status=msg_status,
                created_on=timezone.now(),
                sent_on=timezone.now(),
                response_to=response_to,
                broadcast=bcast,
            )

        return bcast
Beispiel #22
0
    def save(self):
        """
        Create a new broadcast to send out
        """
        recipients = self.validated_data.get('contacts', []) + self.validated_data.get('groups', [])

        for urn in self.validated_data.get('urns', []):
            # create contacts for URNs if necessary
            contact = Contact.get_or_create(self.context['org'], self.context['user'], urns=[urn])
            contact_urn = contact.urn_objects[urn]
            recipients.append(contact_urn)

        text, base_language = self.validated_data['text']

        # create the broadcast
        broadcast = Broadcast.create(self.context['org'], self.context['user'],
                                     text=text, base_language=base_language,
                                     recipients=recipients, channel=self.validated_data.get('channel'))

        # send in task
        on_transaction_commit(lambda: send_broadcast_task.delay(broadcast.id))

        return broadcast
Beispiel #23
0
    def restore_object(self, attrs, instance=None):
        """
        Create a new broadcast to send out
        """
        from temba.msgs.tasks import send_broadcast_task

        if instance:  # pragma: no cover
            raise ValidationError("Invalid operation")

        recipients = attrs.get('contacts') + attrs.get('groups')

        for urn in attrs.get('urns'):
            # create contacts for URNs if necessary
            contact = Contact.get_or_create(self.org, self.user, urns=[urn])
            contact_urn = contact.urn_objects[urn]
            recipients.append(contact_urn)

        # create the broadcast
        broadcast = Broadcast.create(self.org, self.user, attrs['text'],
                                     recipients=recipients, channel=attrs['channel'])

        # send in task
        send_broadcast_task.delay(broadcast.id)
        return broadcast
Beispiel #24
0
 def _create_broadcast(self, text, recipients):
     """
     Creates the a single broadcast to the given recipients (which can groups, contacts, URNs)
     """
     return Broadcast.create(self.org, self.user, text, recipients)
Beispiel #25
0
 def _create_broadcast(self, text, recipients):
     """
     Creates the a single broadcast to the given recipients (which can groups, contacts, URNs)
     """
     return Broadcast.create(self.org, self.user, text, recipients)
Beispiel #26
0
    def test_messages(self):
        url = reverse('api.v2.messages')

        # make sure user rights are correct
        self.assertEndpointAccess(url, "folder=inbox")

        # make sure you have to pass in something to filter by
        response = self.fetchJSON(url)
        self.assertResponseError(response, None,
                                 "You must specify one of the contact, folder, label, broadcast, id parameters")

        # create some messages
        joe_msg1 = self.create_msg(direction='I', msg_type='F', text="Howdy", contact=self.joe)
        frank_msg1 = self.create_msg(direction='I', msg_type='I', text="Bonjour", contact=self.frank, channel=self.twitter)
        joe_msg2 = self.create_msg(direction='O', msg_type='I', text="How are you?", contact=self.joe, status='Q')
        frank_msg2 = self.create_msg(direction='O', msg_type='I', text="Ça va?", contact=self.frank, status='D')
        joe_msg3 = self.create_msg(direction='I', msg_type='F', text="Good", contact=self.joe)
        frank_msg3 = self.create_msg(direction='I', msg_type='I', text="Bien", contact=self.frank, channel=self.twitter, visibility='A')

        # add a surveyor message (no URN etc)
        joe_msg4 = self.create_msg(direction='O', msg_type='F', text="Surveys!", contact=self.joe, contact_urn=None,
                                   status='S', channel=None, sent_on=timezone.now())

        # add a deleted message
        deleted_msg = self.create_msg(direction='I', msg_type='I', text="!@$!%", contact=self.frank, visibility='D')

        # add a test contact message
        self.create_msg(direction='I', msg_type='F', text="Hello", contact=self.test_contact)

        # add message in other org
        self.create_msg(direction='I', msg_type='I', text="Guten tag!", contact=self.hans, org=self.org2)

        # label some of the messages, this will change our modified on as well for our `incoming` view
        label = Label.get_or_create(self.org, self.admin, "Spam")

        # we do this in two calls so that we can predict ordering later
        label.toggle_label([frank_msg3], add=True)
        label.toggle_label([frank_msg1], add=True)
        label.toggle_label([joe_msg3], add=True)

        frank_msg1.refresh_from_db(fields=('modified_on',))
        joe_msg3.refresh_from_db(fields=('modified_on',))

        # filter by inbox
        with self.assertNumQueries(NUM_BASE_REQUEST_QUERIES + 7):
            response = self.fetchJSON(url, 'folder=INBOX')

        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.json['next'], None)
        self.assertResultsById(response, [frank_msg1])
        self.assertMsgEqual(response.json['results'][0], frank_msg1, msg_type='inbox', msg_status='queued', msg_visibility='visible')

        # filter by incoming, should get deleted messages too
        with self.assertNumQueries(NUM_BASE_REQUEST_QUERIES + 7):
            response = self.fetchJSON(url, 'folder=incoming')

        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.json['next'], None)
        self.assertResultsById(response, [joe_msg3, frank_msg1, frank_msg3, deleted_msg, joe_msg1])
        self.assertMsgEqual(response.json['results'][0], joe_msg3, msg_type='flow', msg_status='queued', msg_visibility='visible')

        # filter by folder (flow)
        response = self.fetchJSON(url, 'folder=flows')
        self.assertResultsById(response, [joe_msg3, joe_msg1])

        # filter by folder (archived)
        response = self.fetchJSON(url, 'folder=archived')
        self.assertResultsById(response, [frank_msg3])

        # filter by folder (outbox)
        response = self.fetchJSON(url, 'folder=outbox')
        self.assertResultsById(response, [joe_msg2])

        # filter by folder (sent)
        response = self.fetchJSON(url, 'folder=sent')
        self.assertResultsById(response, [joe_msg4, frank_msg2])

        # filter by invalid view
        response = self.fetchJSON(url, 'folder=invalid')
        self.assertResultsById(response, [])

        # filter by id
        response = self.fetchJSON(url, 'id=%d' % joe_msg3.pk)
        self.assertResultsById(response, [joe_msg3])

        # filter by contact
        response = self.fetchJSON(url, 'contact=%s' % self.joe.uuid)
        self.assertResultsById(response, [joe_msg4, joe_msg3, joe_msg2, joe_msg1])

        # filter by invalid contact
        response = self.fetchJSON(url, 'contact=invalid')
        self.assertResultsById(response, [])

        # filter by label name
        response = self.fetchJSON(url, 'label=Spam')
        self.assertResultsById(response, [joe_msg3, frank_msg1])

        # filter by label UUID
        response = self.fetchJSON(url, 'label=%s' % label.uuid)
        self.assertResultsById(response, [joe_msg3, frank_msg1])

        # filter by invalid label
        response = self.fetchJSON(url, 'label=invalid')
        self.assertResultsById(response, [])

        # filter by before (inclusive)
        response = self.fetchJSON(url, 'folder=incoming&before=%s' % format_datetime(frank_msg1.modified_on))
        self.assertResultsById(response, [frank_msg1, frank_msg3, deleted_msg, joe_msg1])

        # filter by after (inclusive)
        response = self.fetchJSON(url, 'folder=incoming&after=%s' % format_datetime(frank_msg1.modified_on))
        self.assertResultsById(response, [joe_msg3, frank_msg1])

        # filter by broadcast
        broadcast = Broadcast.create(self.org, self.user, "A beautiful broadcast", [self.joe, self.frank])
        broadcast.send()
        response = self.fetchJSON(url, 'broadcast=%s' % broadcast.pk)

        expected = {m.pk for m in broadcast.msgs.all()}
        results = {m['id'] for m in response.json['results']}
        self.assertEqual(expected, results)

        # can't filter by more than one of contact, folder, label or broadcast together
        for query in ('contact=%s&label=Spam' % self.joe.uuid, 'label=Spam&folder=inbox',
                      'broadcast=12345&folder=inbox', 'broadcast=12345&label=Spam'):
            response = self.fetchJSON(url, query)
            self.assertResponseError(response, None,
                                     "You may only specify one of the contact, folder, label, broadcast parameters")
Beispiel #27
0
    def test_update(self):
        # create a scheduled broadcast
        schedule = Schedule.create_blank_schedule(self.org, self.admin)
        Broadcast.create(
            self.org,
            self.admin,
            {"eng": "Hi"},
            contacts=[self.create_contact("Jim", phone="1234")],
            base_language="eng",
            schedule=schedule,
        )
        update_url = reverse("schedules.schedule_update", args=[schedule.id])

        self.assertUpdateFetch(
            update_url,
            allow_viewers=False,
            allow_editors=True,
            form_fields=["start_datetime", "repeat_period", "repeat_days_of_week"],
        )

        def datepicker_fmt(d: datetime):
            return datetime_to_str(d, "%Y-%m-%d %H:%M", self.org.timezone)

        today = timezone.now().replace(second=0, microsecond=0)
        yesterday = today - timedelta(days=1)
        tomorrow = today + timedelta(days=1)

        # update to start in past with no repeat
        self.assertUpdateSubmit(update_url, {"start_datetime": datepicker_fmt(yesterday), "repeat_period": "O"})

        schedule.refresh_from_db()
        self.assertEqual("O", schedule.repeat_period)
        self.assertIsNone(schedule.next_fire)

        # update to start in future with no repeat
        self.assertUpdateSubmit(update_url, {"start_datetime": datepicker_fmt(tomorrow), "repeat_period": "O"})

        schedule.refresh_from_db()
        self.assertEqual("O", schedule.repeat_period)
        self.assertEqual(tomorrow, schedule.next_fire)

        # update to start now with daily repeat
        self.assertUpdateSubmit(update_url, {"start_datetime": datepicker_fmt(today), "repeat_period": "D"})

        schedule.refresh_from_db()
        self.assertEqual("D", schedule.repeat_period)
        self.assertEqual(tomorrow, schedule.next_fire)

        # try to submit weekly without specifying days of week
        self.assertUpdateSubmit(
            update_url,
            {"start_datetime": datepicker_fmt(today), "repeat_period": "W"},
            form_errors={"__all__": "Must specify at least one day of the week."},
            object_unchanged=schedule,
        )

        # try to submit weekly with an invalid day of the week (UI doesn't actually allow this)
        self.assertUpdateSubmit(
            update_url,
            {"start_datetime": datepicker_fmt(today), "repeat_period": "W", "repeat_days_of_week": ["X"]},
            form_errors={"repeat_days_of_week": "Select a valid choice. X is not one of the available choices."},
            object_unchanged=schedule,
        )

        # update with valid days of the week
        self.assertUpdateSubmit(
            update_url,
            {"start_datetime": datepicker_fmt(today), "repeat_period": "W", "repeat_days_of_week": ["M", "F"]},
        )

        schedule.refresh_from_db()
        self.assertEqual("W", schedule.repeat_period)
        self.assertEqual("MF", schedule.repeat_days_of_week)

        # update to repeat monthly
        self.assertUpdateSubmit(
            update_url,
            {"start_datetime": datepicker_fmt(today), "repeat_period": "M"},
        )

        schedule.refresh_from_db()
        self.assertEqual("M", schedule.repeat_period)
        self.assertIsNone(schedule.repeat_days_of_week)

        # update with empty start date to signify unscheduling
        self.assertUpdateSubmit(update_url, {"start_datetime": "", "repeat_period": "O"})

        schedule.refresh_from_db()
        self.assertEqual("O", schedule.repeat_period)
        self.assertIsNone(schedule.next_fire)