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")
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 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"
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")
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()
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)
def feedback(self): connection = self.get_connection() if connection is None: return None srv = APNs(connection) return srv.feedback()
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 # stop sending messages to it. except Exception as _ex: print "connect to APNs failed, err: %s" %str(_ex)
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))