def _apns_send(app_id, token, alert, badge=None, sound=None, category=None, content_available=False,
action_loc_key=None, loc_key=None, loc_args=[], extra={}, identifier=0,
expiration=None, priority=10, socket=None):
data = {}
aps_data = {}
if action_loc_key or loc_key or loc_args:
alert = {"body": alert} if alert else {}
if action_loc_key:
alert["action-loc-key"] = action_loc_key
if loc_key:
alert["loc-key"] = loc_key
if loc_args:
alert["loc-args"] = loc_args
if alert is not None:
aps_data["alert"] = alert
if badge is not None:
aps_data["badge"] = badge
if sound is not None:
aps_data["sound"] = sound
if category is not None:
aps_data["category"] = category
if content_available:
aps_data["content-available"] = 1
data["aps"] = aps_data
data.update(extra)
# convert to json, avoiding unnecessary whitespace with separators (keys sorted for tests)
json_data = json.dumps(data, separators=(",", ":"), sort_keys=True).encode("utf-8")
max_size = SETTINGS["APNS_MAX_NOTIFICATION_SIZE"]
if len(json_data) > max_size:
raise APNSDataOverflow("Notification body cannot exceed %i bytes" % (max_size))
# if expiration isn't specified use 1 month from now
expiration_time = expiration if expiration is not None else int(time.time()) + 2592000
frame = _apns_pack_frame(token, json_data, identifier, expiration_time, priority)
if socket:
socket.write(frame)
else:
with closing(_apns_create_socket_to_push(app_id)) as socket:
socket.write(frame)
_apns_check_errors(socket)