示例#1
0
    def send_message(self, tokens, alert=None, badge=None, sound=None,
                     expiry=None, payload=None, **extra):
        """
        Send a message. This will not retry but will call the
            failed_callback in case of failure

        .. seealso::

            :py:class:`apnsclient.apns.Message` for a better description of the
                parameters

        :param tokens: The tokens to send to
        :param alert: The alert message
        :param badge: The badge to show
        :param sound: The sound to play
        :param expiry: A timestamp when message will expire
        :param payload: The payload
        :param extra: Extra info

        """
        connection = self.get_connection()
        if connection is None:
            return None

        if not tokens:
            return False

        message = Message(tokens, alert, badge, sound, expiry, payload,
                          **extra)
        srv = APNs(connection)
        res = srv.send(message)
        if res.failed and self.failed_callback:
            for key, reason in res.failed.iterkeys():
                self.failed_callback(key, reason)
        return res
示例#2
0
def _do_push_to_apns_service(user, message, apns_connection):
    # type: (UserProfile, Message, Connection) -> None
    if not apns_connection:
        logging.info("Not delivering APNS message %s to user %s due to missing connection" % (message, user))
        return

    apns_client = APNs(apns_connection)
    ret = apns_client.send(message)
    if not ret:
       logging.warning("APNS: Failed to send push notification for clients %s" % (message.tokens,))
       return

    for token, reason in ret.failed.items():
        code, errmsg = reason
        b64_token = hex_to_b64(token)
        logging.warning("APNS: Failed to deliver APNS notification to %s, reason: %s" % (b64_token, errmsg))
        if code == 8:
            # Invalid Token, remove from our database
            logging.warning("APNS: Removing token from database due to above failure")
            PushDeviceToken.objects.get(user=user, token=b64_token).delete()

    # Check failures not related to devices.
    for code, errmsg in ret.errors:
        logging.warning("APNS: Unknown error when delivering APNS: %s" % (errmsg,))

    if ret.needs_retry():
        logging.warning("APNS: delivery needs a retry, trying again")
        retry_msg = ret.retry()
        ret = apns_client.send(retry_msg)
        for code, errmsg in ret.errors:
            logging.warning("APNS: Unknown error when delivering APNS: %s" % (errmsg,))
示例#3
0
    def push(self, ios_users, device_tokens, alert, extra_kwargs):
        """Send message to ios.

        The method will block until the whole message is sent. The method
        returns :class:`Result` object, which you can examine for possible
        errors and retry attempts.
        """
        pid = os.getpid()
        pname = multiprocessing.current_process().name
        try:
            msg = Message(device_tokens, alert=alert, badge=0, **extra_kwargs)
            apns_service = APNs(self.apns_conn)
            ret_obj = apns_service.send(msg)
            failed_message = ret_obj._failed
            if not failed_message:
                LOG.info("pid(%s) pname(%s) apns pusher send data"
                         " to ios_users(%s) success"
                         % (pid, pname, ios_users))
            else:
                LOG.warn("pid(%s) pname(%s) apns pusher send result"
                         " part failed: %r"
                         %(pid, pname, failed_message))
        except Exception as _ex:
            LOG.error("pid(%s) pname(%s) apns send data exception: %s"
                      % (pid, pname, str(_ex)))
            return False
        return True
示例#4
0
def push(token, message, badge_num, name, item_type):
    con = Session.new_connection(
        ("gateway.push.apple.com",
         2195),
        cert_file="cert.pem",
        passphrase="this is the queue push key")

    message_packet = Message(
        token,
        alert=message,
        badge=badge_num,
        user=name,
        sound="default",
        itemType=item_type)

    srv = APNs(con)
    res = srv.send(message_packet)

    # Check failures. Check codes in APNs reference docs.
    for token, reason in res.failed.items():
        code, errmsg = reason

    if res.needs_retry():
        retry_message = res.retry()
        res = srv.send(retry_message)
示例#5
0
def check_apns_feedback():
    feedback_connection = session.get_connection(settings.APNS_FEEDBACK, cert_file=settings.APNS_CERT_FILE)
    apns_client = APNs(feedback_connection, tail_timeout=20)

    for token, since in apns_client.feedback():
        since_date = timestamp_to_datetime(since)
        logging.info("Found unavailable token %s, unavailable since %s" % (token, since_date))

        PushDeviceToken.objects.filter(token=hex_to_b64(token), last_updates__lt=since_date, type=PushDeviceToken.APNS).delete()
    logging.info("Finished checking feedback for stale tokens")
示例#6
0
    def test_send(self):
        # success, retry + include-failed, don't-retry + include-failed
        backend = DummyBackend(push=(None, 1, 3))
        session = Session(pool=backend)

        msg = Message(["0123456789ABCDEF", "FEDCBA9876543210"], alert="my alert", badge=10, content_available=1, my_extra=15)
        push_con = session.get_connection("push_production", cert_string="certificate")
        srv = APNs(push_con)
        res = srv.send(msg)
        self.assertEqual(len(res.failed), 0)
        self.assertEqual(len(res.errors), 0)
        self.assertFalse(res.needs_retry())

        push_con2 = session.get_connection("push_production", cert_string="certificate")
        srv = APNs(push_con2)
        self.assertEqual(session.pool.push_result_pos, 0)
        session.pool.push_result_pos += 1
        res = srv.send(msg)
        self.assertEqual(len(res.failed), 0)
        self.assertEqual(len(res.errors), 1)
        self.assertTrue(res.needs_retry())

        # indeed, we have used the cache
        self.assertEqual(session.pool.new_connections, 1)

        push_con = session.new_connection("push_production", cert_string="certificate")
        srv = APNs(push_con)
        res = srv.send(msg)
        self.assertEqual(len(res.failed), 0)
        self.assertEqual(len(res.errors), 1)
        self.assertFalse(res.needs_retry())

        # indeed, new connection, we haven't used the cache
        self.assertEqual(session.pool.new_connections, 2)
示例#7
0
def push_to_ios_devices_raw(devices=None, **kwargs):
    conn = Session.new_connection(settings.IOS_PUSH_SERVER,
                                  cert_file=settings.IOS_CERT)
    srv = APNs(conn)
    if devices is None:
        devices = APNSDevice.objects.filter(active=True).values_list(
            "registration_id", flat=True)
    message = Message(devices, **kwargs)
    res = srv.send(message)
    if res.needs_retry():
        push_to_ios_devices_raw.delay(devices=res.retry().tokens, **kwargs)
示例#8
0
 def check_feedback_services_for_tokens(self):
     """
     used only for feedback connection on schedule, remove not available tokens
     """
     services = APNs(self.connection)
     try:
         for token, when in services.feedback():
             last_update = self.get_last_update_of_token(token)
             if last_update and last_update < when:
                 self.remove_token(token)
     except:
         print "Can't connect to APNs, looks like network is down"
示例#9
0
def get_ios_device_feedback():
    conn = Session.new_connection(settings.IOS_FEEDBACK_SERVER,
                                  cert_file=settings.IOS_CERT)
    srv = APNs(conn, tail_timeout=10)
    for token, since in srv.feedback():
        print token
        try:
            obj = APNSDevice.objects.get(registration_id=token)
            obj.active = False
            obj.save()
        except APNSDevice.DoesNotExist:
            pass
def send_push_notifications(tokens, title, message, cert_file, url_args=None):
    url_args = url_args or ["", ""]
    session = Session()
    conn = session.get_connection("push_production", cert_file=cert_file)
    apns = APNs(conn)
    payload = {}
    payload["aps"] = {}
    payload["aps"]["alert"] = {
        "title": title,
        "body": message,
    }
    payload["aps"]["url-args"] = url_args
    message = Message(tokens, payload=payload)
    apns.send(message)
示例#11
0
def remove_tokens():
# feedback needs no persistent connections.
    con = Session.new_connection(("gateway.push.apple.com", 2196), cert_file=os.path.join(os.getcwd(), 'cert.pem'), passphrase="this is the queue push key")

# feedback server might be slow, so allow it to time out in 10 seconds
    srv = APNs(con, tail_timeout=10)

# automatically closes connection for you
    for token, since in srv.feedback():
        user = db.session.query(User).filter(User.device_token == token).one()
        user.device_token = None
        db.session.add(user)

    db.session.commit()
示例#12
0
def check_apns_feedback():
    feedback_connection = session.get_connection(
        settings.APNS_FEEDBACK, cert_file=settings.APNS_CERT_FILE)
    apns_client = APNs(feedback_connection, tail_timeout=20)

    for token, since in apns_client.feedback():
        since_date = timestamp_to_datetime(since)
        logging.info("Found unavailable token %s, unavailable since %s" %
                     (token, since_date))

        PushDeviceToken.objects.filter(token=hex_to_b64(token),
                                       last_updates__lt=since_date,
                                       type=PushDeviceToken.APNS).delete()
    logging.info("Finished checking feedback for stale tokens")
示例#13
0
    def send_ios_push_notifications(self, tokens, message):
        con = self.ios_session.get_connection("push_production",
                                              cert_file=self.config.get('push', 'push_certificate_file'))
        message = Message(tokens, alert=message, badge=1, sound='default')

        # Send the message.
        srv = APNs(con)
        res = srv.send(message)

        # Check failures. Check codes in APNs reference docs.
        for token, reason in res.failed.items():
            code, errmsg = reason
            LOGGER.info("Device push failed: {0}, reason: {1}".format(token, errmsg))

        LOGGER.info("Successfully sended {} to {}.".format(message.alert, tokens))
示例#14
0
 def connect_apns_server(cls, sandbox, p12, secret, timestamp):
     pub_key, priv_key = cls.gen_pem(p12, secret)
     session = Session(read_tail_timeout=1)
     address = 'push_sandbox' if sandbox else 'push_production'
     conn = session.get_connection(address,
                                   cert_string=pub_key,
                                   key_string=priv_key)
     apns = APNs(conn)
     return apns
示例#15
0
    def send_message(self,
                     tokens,
                     alert=None,
                     badge=None,
                     sound=None,
                     content_available=None,
                     expiry=None,
                     payload=None,
                     **extra):
        """
        Send a message. This will not retry but will call the
            failed_callback in case of failure

        .. seealso::

            :py:class:`apnsclient.apns.Message` for a better description of the
                parameters

        :param tokens: The tokens to send to
        :param alert: The alert message
        :param badge: The badge to show
        :param sound: The sound to play
        :param expiry: A timestamp when message will expire
        :param payload: The payload
        :param extra: Extra info

        """
        connection = self.get_connection()
        if connection is None:
            return None

        if not tokens:
            return False

        message = Message(tokens, alert, badge, sound, expiry, payload,
                          content_available, **extra)
        srv = APNs(connection)
        res = srv.send(message)
        if res.failed and self.failed_callback:
            for key, reason in res.failed.iteritems():
                self.failed_callback(key, reason)
        return res
示例#16
0
    def test_send(self):
        # success, retry + include-failed, don't-retry + include-failed
        backend = DummyBackend(push=(None, 1, 3))
        session = Session(pool=backend)

        msg = Message(["0123456789ABCDEF", "FEDCBA9876543210"], alert="my alert", badge=10, content_available=1, my_extra=15)
        push_con = session.get_connection("push_production", cert_string="certificate")
        srv = APNs(push_con)
        res = srv.send(msg)
        self.assertEqual(len(res.failed), 0)
        self.assertEqual(len(res.errors), 0)
        self.assertFalse(res.needs_retry())

        push_con2 = session.get_connection("push_production", cert_string="certificate")
        srv = APNs(push_con2)
        self.assertEqual(session.pool.push_result_pos, 0)
        session.pool.push_result_pos += 1
        res = srv.send(msg)
        self.assertEqual(len(res.failed), 0)
        self.assertEqual(len(res.errors), 1)
        self.assertTrue(res.needs_retry())

        # indeed, we have used the cache
        self.assertEqual(session.pool.new_connections, 1)

        push_con = session.new_connection("push_production", cert_string="certificate")
        srv = APNs(push_con)
        res = srv.send(msg)
        self.assertEqual(len(res.failed), 0)
        self.assertEqual(len(res.errors), 1)
        self.assertFalse(res.needs_retry())

        # indeed, new connection, we haven't used the cache
        self.assertEqual(session.pool.new_connections, 2)
示例#17
0
def _do_push_to_apns_service(user, message, apns_connection):
    # type: (UserProfile, Message, Connection) -> None
    if not apns_connection:
        logging.info(
            "Not delivering APNS message %s to user %s due to missing connection"
            % (message, user))
        return

    apns_client = APNs(apns_connection)
    ret = apns_client.send(message)
    if not ret:
        logging.warning(
            "APNS: Failed to send push notification for clients %s" %
            (message.tokens, ))
        return

    for token, reason in ret.failed.items():
        code, errmsg = reason
        b64_token = hex_to_b64(token)
        logging.warning(
            "APNS: Failed to deliver APNS notification to %s, reason: %s" %
            (b64_token, errmsg))
        if code == 8:
            # Invalid Token, remove from our database
            logging.warning(
                "APNS: Removing token from database due to above failure")
            PushDeviceToken.objects.get(user=user, token=b64_token).delete()

    # Check failures not related to devices.
    for code, errmsg in ret.errors:
        logging.warning("APNS: Unknown error when delivering APNS: %s" %
                        (errmsg, ))

    if ret.needs_retry():
        logging.warning("APNS: delivery needs a retry, trying again")
        retry_msg = ret.retry()
        ret = apns_client.send(retry_msg)
        for code, errmsg in ret.errors:
            logging.warning("APNS: Unknown error when delivering APNS: %s" %
                            (errmsg, ))
示例#18
0
    def send_notification(self, list_tokens, message_title="", message_body="", badge=1):
        """
        push notifications to apns server, used only with push_connection=True
        :param message_body:
        :param message_title:
        :param list_tokens: all tokens to send notifications
        :param badge: number of something new in server
        """
        service = APNs(self.connection)
        try:
            res = service.send(Message(list_tokens, alert={"title": message_title, "body": message_body}, badge=badge))
        except:
            print "Can't connect to APNs, looks like network is down"
        else:
            for token, reason in res.failed.items():
                code, errmsg = reason
                print "Device failed: {0}, reason: {1}".format(token, errmsg)

            for code, errmsg in res.errors:
                print "Error: {}".format(errmsg)

            if res.needs_retry():
                res.retry()
示例#19
0
    def connect_apns(cls, appid):
        logging.debug("connecting apns")
        p12, secret, timestamp = cls.get_p12(appid)
        if not p12:
            return None

        if sandbox:
            pem_file = "/tmp/app_%s_sandbox_%s.pem" % (appid, timestamp)
            address = 'push_sandbox'
        else:
            pem_file = "/tmp/app_%s_%s.pem" % (appid, timestamp)
            address = 'push_production'

        if not os.path.isfile(pem_file):
            pem = cls.gen_pem(p12, secret)
            f = open(pem_file, "wb")
            f.write(pem)
            f.close()

        session = Session(read_tail_timeout=1)

        conn = session.get_connection(address, cert_file=pem_file)
        apns = APNs(conn)
        return apns
示例#20
0
文件: test.py 项目: GMcD/apns-client
 def test_feedback(self):
     backend = DummyBackend(feedback=5)
     session = Session(pool=backend)
     feed_con = session.new_connection("feedback_production", cert_string="certificate")
     srv = APNs(feed_con)
     self.assertEqual(len(list(srv.feedback())), 5)
示例#21
0
文件: app.py 项目: yyjinlong/yPush
class ApnsFeedback(QApplication):
    name = "feedbacker"
    version = "v0.1"

    def init_app(self):
        super(ApnsFeedback, self).init_app()

        # init log
        logging.setup("feedbacker")
        LOG.info("apns feedback service run.")

        # init apns
        self._init_apns()

        # init db
        self.pms = PushMsgService()

    def run(self):
        self.service = APNs(self.apns_conn)
        self._fetch_invalid_tokens()

    def _init_apns(self):
        """Obtain new connection to APNs. This method will not re-use existing
        connection from the pool. The connection will be closed after use.

        Unlike: `get_connection` this method does not cache the connection.
        Use it to fetch feedback from APNs and then close when you are done.
        """
        run_path = os.getcwd()
        cert_file = "%s/%s/%s" %(
            run_path,
            CONF.IOS.cert_child_path,
            CONF.IOS.cert_file_name
        )

        try:
            session = Session()
            self.apns_conn = session.new_connection(
                address=CONF.IOS.feedback_address,
                cert_file=cert_file,
                passphrase=CONF.IOS.cert_passphrase
            )
        except Exception as _ex:
            LOG.error("init feedback non-cached connection exception: %s"
                      % str(_ex))

    def _fetch_invalid_tokens(self):
        """Fetch feedback from APNs.

        Feedback service return all invaild tokens for once run.
        Result sytle:
           ('invalid token', datetime.datetime.now())
        """
        try:
            for token, when in self.service.feedback():
                LOG.info("when(%s) find invalid token: %s" % (when, token))
                # update token not available
                status = self.pms.DEVICE_NOT_AVALIABLE
                self.pms.update_device_available_status(token, status)
        except Exception as _ex:
            LOG.error("connect to apns error: %s" % str(_ex))
示例#22
0
文件: app.py 项目: yyjinlong/yPush
 def run(self):
     self.service = APNs(self.apns_conn)
     self._fetch_invalid_tokens()
示例#23
0
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Author: jinlong.yang
#

from apnsclient import (
    Session,
    APNs
)
from pprint import pprint

session = Session()
conn =session.new_connection("feedback_sandbox", cert_file="apns.pem", passphrase="1234")

service = APNs(conn)
pprint(vars(service))

try:
    # on any IO failure after successfull connection this generator
    # will simply stop iterating. you will pick the rest of the tokens
    # during next feedback session.
    # feedback的接口取到的是上次推送的过程中出现的已卸载应用的设备token,而且获取一次之后就会清空
    for token, when in service.feedback():
        # every time a devices sends you a token, you should store
        # {token: given_token, last_update: datetime.datetime.now()})
        print token
        print when

        # the token wasn't updated after the failure has
        # been reported, so the token is invalid and you should
示例#24
0
 def feedback(self):
     connection = self.get_connection()
     if connection is None:
         return None
     srv = APNs(connection)
     return srv.feedback()
示例#25
0
#

from apnsclient import (
        Session,
        Message,
        APNs
)
from pprint import pprint

# device token and private key's passwd
deviceToken = '097271a3744d951fe233729b649b0d5bcdfbf7e0c8c10e11fa99d02e5cfa87ac';
invalid_deviceToken = '097271a3744d951fe233729b649b0d5bcdfbf7e0c8c10e11fa99d02e5cfa87ed';
passphrase = '1234';

# 使用session对象来创建一个连接池
session = Session()
conn = session.get_connection("push_sandbox", cert_file="apns.pem", passphrase=passphrase)

# 发送推送和得到反馈
tokenList = []
tokenList.append(deviceToken)
#tokenList.append(invalid_deviceToken)
msg = Message(tokenList, alert="use python send", badge=10)

# send message
service = APNs(conn)
res = service.send(msg)

pprint(vars(res))
print res.message.__dict__
示例#26
0
 def test_feedback(self):
     backend = DummyBackend(feedback=5)
     session = Session(pool=backend)
     feed_con = session.new_connection("feedback_production", cert_string="certificate")
     srv = APNs(feed_con)
     self.assertEqual(len(list(srv.feedback())), 5)