+32
-7
@@ -20,6 +20,15 @@ class NotificationPriority(Enum):
|
|||||||
Delayed = '5'
|
Delayed = '5'
|
||||||
|
|
||||||
|
|
||||||
|
class NotificationType(Enum):
|
||||||
|
Alert = 'alert'
|
||||||
|
Background = 'background'
|
||||||
|
VoIP = 'voip'
|
||||||
|
Complication = 'complication'
|
||||||
|
FileProvider = 'fileprovider'
|
||||||
|
MDM = 'mdm'
|
||||||
|
|
||||||
|
|
||||||
RequestStream = collections.namedtuple('RequestStream', ['stream_id', 'token'])
|
RequestStream = collections.namedtuple('RequestStream', ['stream_id', 'token'])
|
||||||
Notification = collections.namedtuple('Notification', ['token', 'payload'])
|
Notification = collections.namedtuple('Notification', ['token', 'payload'])
|
||||||
|
|
||||||
@@ -92,16 +101,32 @@ class APNsClient(object):
|
|||||||
|
|
||||||
def send_notification_async(self, token_hex: str, notification: Payload, topic: Optional[str] = None,
|
def send_notification_async(self, token_hex: str, notification: Payload, topic: Optional[str] = None,
|
||||||
priority: NotificationPriority = NotificationPriority.Immediate,
|
priority: NotificationPriority = NotificationPriority.Immediate,
|
||||||
expiration: Optional[int] = None, collapse_id: Optional[str] = None) -> int:
|
expiration: Optional[int] = None, collapse_id: Optional[str] = None,
|
||||||
|
push_type: Optional[NotificationType] = None) -> int:
|
||||||
json_str = json.dumps(notification.dict(), cls=self.__json_encoder, ensure_ascii=False, separators=(',', ':'))
|
json_str = json.dumps(notification.dict(), cls=self.__json_encoder, ensure_ascii=False, separators=(',', ':'))
|
||||||
json_payload = json_str.encode('utf-8')
|
json_payload = json_str.encode('utf-8')
|
||||||
|
|
||||||
headers = {
|
headers = {}
|
||||||
'apns-push-type': notification.push_type
|
|
||||||
}
|
|
||||||
|
|
||||||
|
inferred_push_type = None # type: Optional[str]
|
||||||
if topic is not None:
|
if topic is not None:
|
||||||
headers['apns-topic'] = topic
|
headers['apns-topic'] = topic
|
||||||
|
if topic.endswith('.voip'):
|
||||||
|
inferred_push_type = NotificationType.VoIP.value
|
||||||
|
elif topic.endswith('.complication'):
|
||||||
|
inferred_push_type = NotificationType.Complication.value
|
||||||
|
elif topic.endswith('.pushkit.fileprovider'):
|
||||||
|
inferred_push_type = NotificationType.FileProvider.value
|
||||||
|
elif any([notification.alert, notification.badge, notification.sound]):
|
||||||
|
inferred_push_type = NotificationType.Alert.value
|
||||||
|
else:
|
||||||
|
inferred_push_type = NotificationType.Background.value
|
||||||
|
|
||||||
|
if push_type:
|
||||||
|
inferred_push_type = push_type.value
|
||||||
|
|
||||||
|
if inferred_push_type:
|
||||||
|
headers['apns-push-type'] = inferred_push_type
|
||||||
|
|
||||||
if priority != DEFAULT_APNS_PRIORITY:
|
if priority != DEFAULT_APNS_PRIORITY:
|
||||||
headers['apns-priority'] = priority.value
|
headers['apns-priority'] = priority.value
|
||||||
@@ -138,8 +163,8 @@ class APNsClient(object):
|
|||||||
|
|
||||||
def send_notification_batch(self, notifications: Iterable[Notification], topic: Optional[str] = None,
|
def send_notification_batch(self, notifications: Iterable[Notification], topic: Optional[str] = None,
|
||||||
priority: NotificationPriority = NotificationPriority.Immediate,
|
priority: NotificationPriority = NotificationPriority.Immediate,
|
||||||
expiration: Optional[int] = None, collapse_id: Optional[str] = None
|
expiration: Optional[int] = None, collapse_id: Optional[str] = None,
|
||||||
) -> Dict[str, Union[str, Tuple[str, str]]]:
|
push_type: Optional[NotificationType] = None) -> Dict[str, Union[str, Tuple[str, str]]]:
|
||||||
"""
|
"""
|
||||||
Send a notification to a list of tokens in batch. Instead of sending a synchronous request
|
Send a notification to a list of tokens in batch. Instead of sending a synchronous request
|
||||||
for each token, send multiple requests concurrently. This is done on the same connection,
|
for each token, send multiple requests concurrently. This is done on the same connection,
|
||||||
@@ -171,7 +196,7 @@ class APNsClient(object):
|
|||||||
if next_notification is not None and len(open_streams) < self.__max_concurrent_streams:
|
if next_notification is not None and len(open_streams) < self.__max_concurrent_streams:
|
||||||
logger.info('Sending to token %s', next_notification.token)
|
logger.info('Sending to token %s', next_notification.token)
|
||||||
stream_id = self.send_notification_async(next_notification.token, next_notification.payload, topic,
|
stream_id = self.send_notification_async(next_notification.token, next_notification.payload, topic,
|
||||||
priority, expiration, collapse_id)
|
priority, expiration, collapse_id, push_type)
|
||||||
open_streams.append(RequestStream(stream_id, next_notification.token))
|
open_streams.append(RequestStream(stream_id, next_notification.token))
|
||||||
|
|
||||||
next_notification = next(notification_iterator, None)
|
next_notification = next(notification_iterator, None)
|
||||||
|
|||||||
@@ -77,10 +77,6 @@ class Payload(object):
|
|||||||
self.mutable_content = mutable_content
|
self.mutable_content = mutable_content
|
||||||
self.thread_id = thread_id
|
self.thread_id = thread_id
|
||||||
|
|
||||||
self.push_type = 'background'
|
|
||||||
if self.alert or self.badge is not None or self.sound is not None:
|
|
||||||
self.push_type = 'alert'
|
|
||||||
|
|
||||||
def dict(self) -> Dict[str, Any]:
|
def dict(self) -> Dict[str, Any]:
|
||||||
result = {
|
result = {
|
||||||
'aps': {}
|
'aps': {}
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ def test_payload():
|
|||||||
},
|
},
|
||||||
'extra': 'something'
|
'extra': 'something'
|
||||||
}
|
}
|
||||||
assert payload.push_type == 'alert'
|
|
||||||
|
|
||||||
|
|
||||||
def test_payload_with_payload_alert(payload_alert):
|
def test_payload_with_payload_alert(payload_alert):
|
||||||
@@ -81,21 +80,3 @@ def test_payload_with_payload_alert(payload_alert):
|
|||||||
},
|
},
|
||||||
'extra': 'something'
|
'extra': 'something'
|
||||||
}
|
}
|
||||||
assert payload.push_type == 'alert'
|
|
||||||
|
|
||||||
|
|
||||||
def test_payload_with_background_push_type():
|
|
||||||
payload = Payload(
|
|
||||||
content_available=True, mutable_content=True,
|
|
||||||
category='my_category', url_args='args', custom={'extra': 'something'}, thread_id='42')
|
|
||||||
assert payload.dict() == {
|
|
||||||
'aps': {
|
|
||||||
'content-available': 1,
|
|
||||||
'mutable-content': 1,
|
|
||||||
'thread-id': '42',
|
|
||||||
'category': 'my_category',
|
|
||||||
'url-args': 'args',
|
|
||||||
},
|
|
||||||
'extra': 'something'
|
|
||||||
}
|
|
||||||
assert payload.push_type == 'background'
|
|
||||||
|
|||||||
Reference in New Issue
Block a user