def setUp(self):
     self.started_at = dt_now()
     cert, key = generate_cert_and_pkey()
     self.service = APNService.objects.create(name='service', hostname='127.0.0.1',
                                              private_key=key, certificate=cert)
     self.service.PORT = 2195
     self.device = Device.objects.create(token=TOKEN, service=self.service)
 def set_devices_last_notified_at(self, devices):
     if isinstance(devices, models.query.QuerySet):
         devices.update(last_notified_at=dt_now())
     else:
         # Rather than do a save on every object
         # fetch another queryset and use it to update
         # the devices in a single query.
         Device.objects.filter(pk__in=[d.pk for d in devices]).update(last_notified_at=dt_now())
 def setUp(self):
     self.started_at = dt_now()
     cert, key = generate_cert_and_pkey()
     self.service = APNService.objects.create(name='service',
                                              hostname='127.0.0.1',
                                              private_key=key,
                                              certificate=cert)
     self.service.PORT = 2195
     self.device = Device.objects.create(token=TOKEN, service=self.service)
Esempio n. 4
0
 def set_devices_last_notified_at(self, devices):
     # Rather than do a save on every object,
     # fetch another queryset and use it to update
     # the devices in a single query.
     # Since the devices argument could be a sliced queryset
     # we can't rely on devices.update() even if devices is
     # a queryset object.
     Device.objects.filter(pk__in=[d.pk for d in devices]).update(
         last_notified_at=dt_now())
Esempio n. 5
0
    def setUp(self):
        self.started_at = dt_now()
        cert, key = generate_cert_and_pkey()
        self.service = APNService.objects.create(name='service', hostname='127.0.0.1',
                                                 private_key=key, certificate=cert)
        self.service.PORT = 2195
        self.device = Device.objects.create(token=TOKEN, service=self.service)

        self.IOS_NOTIFICATIONS_PERSIST_NOTIFICATIONS = getattr(settings, 'IOS_NOTIFICATIONS_PERSIST_NOTIFICATIONS', 'NotSpecified')
Esempio n. 6
0
    def _write_message(self, notification, devices, chunk_size):
        """
        Writes the message for the supplied devices to
        the APN Service SSL socket.
        """
        if not isinstance(notification, Notification):
            raise TypeError(
                'notification should be an instance of ios_notifications.models.Notification'
            )

        if not isinstance(chunk_size, int) or chunk_size < 1:
            raise ValueError(
                'chunk_size must be an integer greater than zero.')

        payload = notification.payload

        # Split the devices into manageable chunks.
        # Chunk sizes being determined by the `chunk_size` arg.
        device_length = devices.count() if isinstance(
            devices, models.query.QuerySet) else len(devices)
        chunks = [
            devices[i:i + chunk_size]
            for i in xrange(0, device_length, chunk_size)
        ]

        for index in xrange(len(chunks)):
            chunk = chunks[index]
            self._connect()

            for device in chunk:
                if not device.is_active:
                    continue
                try:
                    self.connection.send(self.pack_message(payload, device))
                except (OpenSSL.SSL.WantWriteError, socket.error) as e:
                    if isinstance(e, socket.error) and isinstance(
                            e.args, tuple) and e.args[0] != errno.EPIPE:
                        raise e  # Unexpected exception, raise it.
                    self._disconnect()
                    i = chunk.index(device)
                    self.set_devices_last_notified_at(chunk[:i])
                    # Start again from the next device.
                    # We start from the next device since
                    # if the device no longer accepts push notifications from your app
                    # and you send one to it anyways, Apple immediately drops the connection to your APNS socket.
                    # http://stackoverflow.com/a/13332486/1025116
                    self._write_message(notification, chunk[i + 1:],
                                        chunk_size)

            self._disconnect()

            self.set_devices_last_notified_at(chunk)

        if notification.pk or notification.persist:
            notification.last_sent_at = dt_now()
            notification.save()
Esempio n. 7
0
    def clean_scheduling_dt(self):
        """validation"""
        sch_dt = self.cleaned_data['scheduling_dt']

        if not sch_dt:
            raise ValidationError(_("This field is required"))

        if sch_dt < dt_now():
            raise ValidationError(_("The scheduling date must be in future"))

        return sch_dt
Esempio n. 8
0
    def setUp(self):
        self.started_at = dt_now()
        self.test_server_proc = subprocess.Popen(SSL_SERVER_COMMAND, stdout=subprocess.PIPE)
        time.sleep(0.5)
        cert, key = generate_cert_and_pkey()
        self.service = APNService.objects.create(name='service', hostname='127.0.0.1',
                                                 private_key=key, certificate=cert)
        self.service.PORT = 2195
        self.device = Device.objects.create(token=TOKEN, service=self.service)

        self.IOS_NOTIFICATIONS_PERSIST_NOTIFICATIONS = getattr(settings, 'IOS_NOTIFICATIONS_PERSIST_NOTIFICATIONS', 'NotSpecified')
    def test_pushing_notification_in_chunks(self):
        devices = []
        for i in xrange(10):
            token = uuid.uuid1().get_hex() * 2
            device = Device.objects.create(token=token, service=self.service)
            devices.append(device)

        started_at = dt_now()
        self.service.push_notification_to_devices(self.notification, devices, chunk_size=2)
        device_count = len(devices)
        self.assertEquals(device_count,
                          Device.objects.filter(last_notified_at__gte=started_at).count())
Esempio n. 10
0
    def clean_scheduling_dt(self):
        """validate datetime"""
        sch_dt = self.cleaned_data['scheduling_dt']

        if not sch_dt:
            raise ValidationError(ugettext("This field is required"))

        if sch_dt < dt_now():
            raise ValidationError(
                ugettext("The scheduling date must be in future"))

        return sch_dt
    def setUp(self):
        self.started_at = dt_now()
        cert, key = generate_cert_and_pkey()
        self.service = APNService.objects.create(name='service',
                                                 hostname='127.0.0.1',
                                                 private_key=key,
                                                 certificate=cert)
        self.service.PORT = 2195
        self.device = Device.objects.create(token=TOKEN, service=self.service)

        self.IOS_NOTIFICATIONS_PERSIST_NOTIFICATIONS = getattr(
            settings, 'IOS_NOTIFICATIONS_PERSIST_NOTIFICATIONS',
            'NotSpecified')
Esempio n. 12
0
    def _write_message(self, notification, devices, chunk_size):
        """
        Writes the message for the supplied devices to
        the APN Service SSL socket.
        """
        if not isinstance(notification, Notification):
            raise TypeError('notification should be an instance of ios_notifications.models.Notification')

        if not isinstance(chunk_size, int) or chunk_size < 1:
            raise ValueError('chunk_size must be an integer greater than zero.')

        payload = notification.payload

        # Split the devices into manageable chunks.
        # Chunk sizes being determined by the `chunk_size` arg.
        device_length = devices.count() if isinstance(devices, models.query.QuerySet) else len(devices)
        chunks = [devices[i:i + chunk_size] for i in xrange(0, device_length, chunk_size)]

        for index in xrange(len(chunks)):
            chunk = chunks[index]

            self._connect()
            for device in chunk:
                if not device.is_active:
                    continue
                try:
                    #self.connection.send(self.pack_message(payload, device))
                    self.connection.write(self.pack_message(payload, device))
                except (OpenSSL.SSL.WantWriteError, socket.error) as e:
                    print 'openssl want write error: {0}'.format(e)
                    if isinstance(e, socket.error) and isinstance(e.args, tuple) and e.args[0] != errno.EPIPE:
                        raise e  # Unexpected exception, raise it.
                    self._disconnect()
                    i = chunk.index(device)
                    self.set_devices_last_notified_at(chunk[:i])
                    # Start again from the next device.
                    # We start from the next device since
                    # if the device no longer accepts push notifications from your app
                    # and you send one to it anyways, Apple immediately drops the connection to your APNS socket.
                    # http://stackoverflow.com/a/13332486/1025116
                    self._write_message(notification, chunk[i + 1:], chunk_size)
                


            self._disconnect()

            self.set_devices_last_notified_at(chunk)

        if notification.pk or notification.persist:
            notification.last_sent_at = dt_now()
            notification.save()
    def test_pushing_notification_in_chunks(self):
        devices = []
        for i in xrange(10):
            token = uuid.uuid1().get_hex() * 2
            device = Device.objects.create(token=token, service=self.service)
            devices.append(device)

        started_at = dt_now()
        self.service.push_notification_to_devices(self.notification,
                                                  devices,
                                                  chunk_size=2)
        device_count = len(devices)
        self.assertEquals(
            device_count,
            Device.objects.filter(last_notified_at__gte=started_at).count())
    def test_pushing_notification_in_chunks_with_feedback_service_WantWriteError(self):
        devices = []
        for i in xrange(10):
            token = uuid.uuid1().get_hex() * 2
            device = Device.objects.create(token=token, service=self.service)
            devices.append(device)

        started_at = dt_now()
        endless_success = cycle([None])
        with patch('OpenSSL.SSL.Connection') as mocked_Connection:
            conn = mocked_Connection.return_value
            conn.send.side_effect = chain([WantWriteError()], endless_success)
            self.service.push_notification_to_devices(self.notification, devices, chunk_size=2, feedback_service=True)
            device_count = len(devices)
            self.assertEquals(device_count, Device.objects.filter(last_notified_at__gte=started_at).count())
 def call(self):
     """
     Calls the feedback service and deactivates any devices the feedback service mentions.
     """
     if self.connect():
         device_tokens = []
         try:
             while True:
                 data = self.connection.recv(38)  # 38 being the length in bytes of the binary format feedback tuple.
                 timestamp, token_length, token = struct.unpack(self.fmt, data)
                 device_token = hexlify(token)
                 device_tokens.append(device_token)
         except OpenSSL.SSL.ZeroReturnError:
             # Nothing to receive
             pass
         devices = Device.objects.filter(token__in=device_tokens, service=self.apn_service)
         devices.update(is_active=False, deactivated_at=dt_now())
         self.disconnect()
         return devices.count()
Esempio n. 16
0
 def call(self):
     """
     Calls the feedback service and deactivates any devices the feedback service mentions.
     """
     self._connect()
     device_tokens = []
     try:
         while True:
             data = self.connection.recv(38)  # 38 being the length in bytes of the binary format feedback tuple.
             timestamp, token_length, token = struct.unpack(self.fmt, data)
             device_token = hexlify(token)
             device_tokens.append(device_token)
     except OpenSSL.SSL.ZeroReturnError:
         # Nothing to receive
         pass
     finally:
         self._disconnect()
     devices = Device.objects.filter(token__in=device_tokens, service=self.apn_service)
     devices.update(is_active=False, deactivated_at=dt_now())
     return devices.count()
    def _write_message(self, notification, devices):
        """
        Writes the message for the supplied devices to
        the APN Service SSL socket.
        """
        if not isinstance(notification, Notification):
            raise TypeError('notification should be an instance of ios_notifications.models.Notification')

        if self.connection is None:
            if not self.connect():
                return

        payload = notification.payload

        for device in devices:
            if not device.is_active:
                continue
            try:
                self.connection.send(self.pack_message(payload, device))
            except (OpenSSL.SSL.WantWriteError, socket.error) as e:
                if isinstance(e, socket.error) and isinstance(e.args, tuple) and e.args[0] != errno.EPIPE:
                    raise  # Unexpected exception, raise it.
                self.disconnect()
                i = devices.index(device)
                self.set_devices_last_notified_at(devices[:i])
                # Start again from the next device.
                # We start from the next device since
                # if the device no longer accepts push notifications from your app
                # and you send one to it anyways, Apple immediately drops the connection to your APNS socket.
                # http://stackoverflow.com/a/13332486/1025116
                return self._write_message(notification, devices[i + 1:]) if self.connect() else None

        self.set_devices_last_notified_at(devices)

        if notification.pk or notification.persist:
            notification.last_sent_at = dt_now()
            notification.save()
Esempio n. 18
0
 def __init__(self, *args, **kwargs):
     kwargs['initial'] = {'scheduling_dt': dt_now() + timedelta(minutes=5)}
     super(NewsletterSchedulingForm, self).__init__(*args, **kwargs)
Esempio n. 19
0
 def __init__(self, *args, **kwargs):
     kwargs['initial'] = {'scheduling_dt': dt_now() + timedelta(minutes=5)}
     super(NewsletterSchedulingForm, self).__init__(*args, **kwargs)
Esempio n. 20
0
 def set_devices_last_notified_at(self, devices):
     # Rather than do a save on every object,
     # fetch another queryset and use it to update
     # the devices in a single query.
     # Since the devices argument could be a sliced queryset
     # we can't rely on devices.update() even if devices is
     # a queryset object.
     Device.objects.filter(pk__in=[d.pk for d in devices]).update(last_notified_at=dt_now())
 def set_last_sent_time(self, notification):
     if notification.pk or notification.persist:
         notification.last_sent_at = dt_now()
         notification.save()
         return True
     return False
Esempio n. 22
0
    def set_devices_last_notified_at(self, devices):
        # Rather than do a save on every object,
        # fetch another queryset and use it to update
        # the devices in a single query.
        # Since the devices argument could be a sliced queryset
        # we can't rely on devices.update() even if devices is
        # a queryset object.

        try:
            Device.objects.filter(pk__in=[d.pk for d in devices]).update(last_notified_at=dt_now())
        except:
            # catchall for deadlock; should not occur, but notifications are too important to be allowed to fail\
            client = Client(dsn=settings.RAVEN_CONFIG["dsn"])
            try:
                exc_info = sys.exc_info()
                client.captureException(exc_info)
            finally:
                del exc_info