Maintain two APNS connections and send correct notifications to each

Now we have 2 different Zulip apps out there, and they are signed with
two certs: Zulip and Dropbox. The Dropbox-signed apps are going to need
to be sent APNS notifications from the appropriate APNS connection

(imported from commit 6db50c5811847db4f08e5c997c7bbb4b46cfc462)
This commit is contained in:
Leo Franchi
2015-02-09 23:08:47 -08:00
parent 1c22b48bb1
commit d865732e0d
4 changed files with 45 additions and 21 deletions

View File

@@ -18,6 +18,13 @@ connection = None
if settings.APNS_CERT_FILE is not None and os.path.exists(settings.APNS_CERT_FILE):
connection = session.get_connection(settings.APNS_SANDBOX, cert_file=settings.APNS_CERT_FILE)
# We maintain an additional APNS connection for pushing to Zulip apps that have been signed
# by the Dropbox certs (and have an app id of com.dropbox.zulip)
dbx_session = Session()
dbx_connection = None
if settings.DBX_APNS_CERT_FILE is not None and os.path.exists(settings.DBX_APNS_CERT_FILE):
dbx_connection = session.get_connection(settings.APNS_SANDBOX, cert_file=settings.DBX_APNS_CERT_FILE)
def num_push_devices_for_user(user_profile, kind = None):
if kind is None:
return PushDeviceToken.objects.filter(user=user_profile).count()
@@ -31,25 +38,11 @@ def b64_to_hex(data):
def hex_to_b64(data):
return base64.b64encode(binascii.unhexlify(data))
# Send a push notification to the desired clients
# extra_data is a dict that will be passed to the
# mobile app
@statsd_increment("apple_push_notification")
def send_apple_push_notification(user, alert, **extra_data):
if not connection:
logging.error("Attempting to send push notification, but no connection was found. This may be because we could not find the APNS Certificate file.")
return
b64_tokens = [device.token for device in PushDeviceToken.objects.filter(user=user, kind=PushDeviceToken.APNS)]
tokens = [b64_to_hex(token) for token in b64_tokens]
logging.info("APNS: Sending apple push notification to devices: %s" % (b64_tokens,))
message = Message(tokens, alert=alert, **extra_data)
apns_client = APNs(connection)
def _do_push_to_apns_service(user, message, apns_connection):
apns_client = APNs(apns_connection)
ret = apns_client.send(message)
if not ret:
logging.warning("APNS: Failed to send push notification for clients %s" % (b64_tokens,))
logging.warning("APNS: Failed to send push notification for clients %s" % (message.tokens,))
return
for token, reason in ret.failed.items():
@@ -73,6 +66,28 @@ def send_apple_push_notification(user, alert, **extra_data):
logging.warning("APNS: Unknown error when delivering APNS: %s" % (errmsg,))
# Send a push notification to the desired clients
# extra_data is a dict that will be passed to the
# mobile app
@statsd_increment("apple_push_notification")
def send_apple_push_notification(user, alert, **extra_data):
if not connection and not dbx_connection:
logging.error("Attempting to send push notification, but no connection was found. This may be because we could not find the APNS Certificate file.")
return
devices = PushDeviceToken.objects.filter(user=user, kind=PushDeviceToken.APNS)
# Plain b64 token kept for debugging purposes
tokens = [(b64_to_hex(device.token), device.ios_app_id, device.token) for device in devices]
logging.info("APNS: Sending apple push notification to devices: %s" % (tokens,))
zulip_message = Message([token[0] for token in tokens if token[1] in (settings.ZULIP_IOS_APP_ID, None)],
alert=alert, **extra_data)
dbx_message = Message([token[0] for token in tokens if token[1] in (settings.DBX_IOS_APP_ID,)],
alert=alert, **extra_data)
_do_push_to_apns_service(user, zulip_message, connection)
_do_push_to_apns_service(user, dbx_message, dbx_connection)
# NOTE: This is used by the check_apns_tokens manage.py command. Do not call it otherwise, as the
# feedback() call can take up to 15s
def check_apns_feedback():