diff --git a/push_notifications/apns_async.py b/push_notifications/apns_async.py index d15168e7..736b02e1 100644 --- a/push_notifications/apns_async.py +++ b/push_notifications/apns_async.py @@ -223,6 +223,7 @@ def apns_send_message( priority: int = None, collapse_id: str = None, mutable_content: bool = False, + category: str = None, err_func: ErrFunc = None, ): """ @@ -242,6 +243,10 @@ def apns_send_message( :param mutable_content: If True, enables the "mutable-content" flag in the payload. This allows the app's Notification Service Extension to modify the notification before it is displayed. + :param category: The category identifier for actionable notifications. + This should match a category identifier defined in the app's + Notification Content Extension or UNNotificationCategory configuration. + It allows the app to display custom actions with the notification. """ results = apns_send_bulk_message( registration_ids=[registration_id], @@ -258,6 +263,7 @@ def apns_send_message( priority=priority, collapse_id=collapse_id, mutable_content=mutable_content, + category = category, err_func=err_func, ) @@ -283,6 +289,7 @@ def apns_send_bulk_message( priority: int = None, collapse_id: str = None, mutable_content: bool = False, + category: str = None, err_func: ErrFunc = None, ): """ @@ -300,6 +307,10 @@ def apns_send_bulk_message( :param mutable_content: If True, enables the "mutable-content" flag in the payload. This allows the app's Notification Service Extension to modify the notification before it is displayed. + :param category: The category identifier for actionable notifications. + This should match a category identifier defined in the app's + Notification Content Extension or UNNotificationCategory configuration. + It allows the app to display custom actions with the notification. """ try: topic = get_manager().get_apns_topic(application_id) @@ -321,6 +332,7 @@ def apns_send_bulk_message( priority=priority, collapse_id=collapse_id, mutable_content=mutable_content, + category=category, err_func=err_func, )) @@ -366,6 +378,7 @@ async def _send_bulk_request( priority: int = None, collapse_id: str = None, mutable_content: bool = False, + category: str = None, err_func: ErrFunc = None, ): client = _create_client( @@ -375,6 +388,8 @@ async def _send_bulk_request( aps_kwargs = {} if mutable_content: aps_kwargs["mutable-content"] = mutable_content + if category: + aps_kwargs["category"] = category requests = [_create_notification_request_from_args( registration_id, diff --git a/tests/test_apns_async_push_payload.py b/tests/test_apns_async_push_payload.py index b961de12..a311d9b2 100644 --- a/tests/test_apns_async_push_payload.py +++ b/tests/test_apns_async_push_payload.py @@ -200,6 +200,25 @@ def test_push_payload_with_mutable_content(self, mock_apns): self.assertTrue("mutable-content" in req.message["aps"]) self.assertEqual(req.message["aps"]["mutable-content"], 1) # APNs expects 1 for True + @mock.patch("push_notifications.apns_async.APNs", autospec=True) + def test_push_payload_with_category(self, mock_apns): + apns_send_message( + "123", + "Hello world", + category="MESSAGE_CATEGORY", + creds=TokenCredentials(key="aaa", key_id="bbb", team_id="ccc"), + sound="chime", + extra={"custom_data": 12345}, + expiration=int(time.time()) + 3, + ) + + args, kwargs = mock_apns.return_value.send_notification.call_args + req = args[0] + + # Assertions + self.assertTrue("category" in req.message["aps"]) + self.assertEqual(req.message["aps"]["category"], "MESSAGE_CATEGORY") # Verify correct category value + # def test_bad_priority(self): # with mock.patch("apns2.credentials.init_context"): # with mock.patch("apns2.client.APNsClient.connect"):