def remote_server_notify_push(request: HttpRequest, entity: Union[UserProfile, RemoteZulipServer], payload: Dict[str, Any]=REQ(argument_type='body')) -> HttpResponse: validate_entity(entity) server = cast(RemoteZulipServer, entity) user_id = payload['user_id'] gcm_payload = payload['gcm_payload'] apns_payload = payload['apns_payload'] android_devices = list(RemotePushDeviceToken.objects.filter( user_id=user_id, kind=RemotePushDeviceToken.GCM, server=server )) apple_devices = list(RemotePushDeviceToken.objects.filter( user_id=user_id, kind=RemotePushDeviceToken.APNS, server=server )) if android_devices: send_android_push_notification(android_devices, gcm_payload, remote=True) if apple_devices: send_apple_push_notification(user_id, apple_devices, apns_payload, remote=True) return json_success()
def remote_server_notify_push( request: HttpRequest, entity: Union[UserProfile, RemoteZulipServer], payload: Dict[str, Any] = REQ(argument_type="body"), ) -> HttpResponse: server = validate_entity(entity) user_id = payload["user_id"] gcm_payload = payload["gcm_payload"] apns_payload = payload["apns_payload"] gcm_options = payload.get("gcm_options", {}) android_devices = list( RemotePushDeviceToken.objects.filter( user_id=user_id, kind=RemotePushDeviceToken.GCM, server=server, ) ) apple_devices = list( RemotePushDeviceToken.objects.filter( user_id=user_id, kind=RemotePushDeviceToken.APNS, server=server, ) ) send_android_push_notification(android_devices, gcm_payload, gcm_options, remote=True) send_apple_push_notification(user_id, apple_devices, apns_payload, remote=True) return json_success()
def remote_server_notify_push( request: HttpRequest, entity: Union[UserProfile, RemoteZulipServer], payload: Dict[str, Any] = REQ(argument_type='body') ) -> HttpResponse: validate_entity(entity) server = cast(RemoteZulipServer, entity) user_id = payload['user_id'] gcm_payload = payload['gcm_payload'] apns_payload = payload['apns_payload'] android_devices = list( RemotePushDeviceToken.objects.filter(user_id=user_id, kind=RemotePushDeviceToken.GCM, server=server)) apple_devices = list( RemotePushDeviceToken.objects.filter(user_id=user_id, kind=RemotePushDeviceToken.APNS, server=server)) if android_devices: send_android_push_notification(android_devices, gcm_payload, remote=True) if apple_devices: send_apple_push_notification(user_id, apple_devices, apns_payload) return json_success()
def test_pushdevice_different(self, mock_send, mock_info): # type: (mock.MagicMock, mock.MagicMock) -> None res = mock.MagicMock() old_token = apn.hex_to_b64(u'1111') new_token = apn.hex_to_b64(u'2222') res.canonical = {old_token: new_token} res.needs_retry.return_value = False mock_send.return_value = res def get_count(hex_token): # type: (text_type) -> int token = apn.hex_to_b64(hex_token) return PushDeviceToken.objects.filter( token=token, kind=PushDeviceToken.GCM).count() self.assertEqual(get_count(u'1111'), 1) self.assertEqual(get_count(u'2222'), 1) data = self.get_gcm_data() apn.send_android_push_notification(self.user_profile, data) mock_info.assert_called_once_with( "GCM: Got canonical ref %s, dropping %s" % (new_token, old_token)) self.assertEqual(get_count(u'1111'), 0) self.assertEqual(get_count(u'2222'), 1)
def test_pushdevice_not_present(self, mock_send, mock_warning): # type: (mock.MagicMock, mock.MagicMock) -> None res = mock.MagicMock() t1 = apn.hex_to_b64(u'1111') t2 = apn.hex_to_b64(u'3333') res.canonical = {t1: t2} res.needs_retry.return_value = False mock_send.return_value = res def get_count(hex_token): # type: (text_type) -> int token = apn.hex_to_b64(hex_token) return PushDeviceToken.objects.filter( token=token, kind=PushDeviceToken.GCM).count() self.assertEqual(get_count(u'1111'), 1) self.assertEqual(get_count(u'3333'), 0) data = self.get_gcm_data() apn.send_android_push_notification(self.user_profile, data) msg = ("GCM: Got canonical ref %s " "replacing %s but new ID not " "registered! Updating.") mock_warning.assert_called_once_with(msg % (t2, t1)) self.assertEqual(get_count(u'1111'), 0) self.assertEqual(get_count(u'3333'), 1)
def test_gcm_is_none(self, mock_error): # type: (mock.MagicMock) -> None apn.gcm = None apn.send_android_push_notification(self.user_profile, {}) mock_error.assert_called_with("Attempting to send a GCM push " "notification, but no API key was " "configured")
def test_equal(self, mock_send, mock_warning): # type: (mock.MagicMock, mock.MagicMock) -> None res = mock.MagicMock() res.canonical = {1: 1} res.needs_retry.return_value = False mock_send.return_value = res data = self.get_gcm_data() apn.send_android_push_notification(self.user_profile, data) mock_warning.assert_called_once_with("GCM: Got canonical ref but it " "already matches our ID 1!")
def test_failure(self, mock_send, mock_warn): # type: (mock.MagicMock, mock.MagicMock) -> None res = mock.MagicMock() token = apn.hex_to_b64(u'1111') res.failed = {token: 1} res.needs_retry.return_value = True mock_send.return_value = res data = self.get_gcm_data() apn.send_android_push_notification(self.user_profile, data) c1 = call("GCM: Delivery to %s failed: 1" % (token,)) c2 = call("GCM: delivery needs a retry but ignoring") mock_warn.assert_has_calls([c1, c2], any_order=True)
def test_success(self, mock_send, mock_info, mock_warning): # type: (mock.MagicMock, mock.MagicMock, mock.MagicMock) -> None res = mock.MagicMock() res.success = {token: ind for ind, token in enumerate(self.gcm_tokens)} res.needs_retry.return_value = False mock_send.return_value = res data = self.get_gcm_data() apn.send_android_push_notification(self.user_profile, data) self.assertEqual(mock_info.call_count, 2) c1 = call("GCM: Sent 1111 as 0") c2 = call("GCM: Sent 2222 as 1") mock_info.assert_has_calls([c1, c2], any_order=True) mock_warning.assert_not_called()
def remote_server_notify_push( request: HttpRequest, entity: Union[UserProfile, RemoteZulipServer], payload: Dict[str, Any] = REQ(argument_type="body"), ) -> HttpResponse: server = validate_entity(entity) user_id = payload["user_id"] gcm_payload = payload["gcm_payload"] apns_payload = payload["apns_payload"] gcm_options = payload.get("gcm_options", {}) android_devices = list( RemotePushDeviceToken.objects.filter( user_id=user_id, kind=RemotePushDeviceToken.GCM, server=server, )) apple_devices = list( RemotePushDeviceToken.objects.filter( user_id=user_id, kind=RemotePushDeviceToken.APNS, server=server, )) logger.info( "Sending mobile push notifications for remote user %s:%s: %s via FCM devices, %s via APNs devices", server.uuid, user_id, len(android_devices), len(apple_devices), ) send_android_push_notification(user_id, android_devices, gcm_payload, gcm_options, remote=server) send_apple_push_notification(user_id, apple_devices, apns_payload, remote=server) return json_success({ "total_android_devices": len(android_devices), "total_apple_devices": len(apple_devices) })
def test_not_registered(self, mock_send, mock_info): # type: (mock.MagicMock, mock.MagicMock) -> None res = mock.MagicMock() token = apn.hex_to_b64(u'1111') res.not_registered = [token] res.needs_retry.return_value = False mock_send.return_value = res def get_count(hex_token): # type: (text_type) -> int token = apn.hex_to_b64(hex_token) return PushDeviceToken.objects.filter( token=token, kind=PushDeviceToken.GCM).count() self.assertEqual(get_count(u'1111'), 1) data = self.get_gcm_data() apn.send_android_push_notification(self.user_profile, data) mock_info.assert_called_once_with("GCM: Removing %s" % (token,)) self.assertEqual(get_count(u'1111'), 0)
def remote_server_notify_push( request: HttpRequest, entity: Union[UserProfile, RemoteZulipServer], payload: Dict[str, Any] = REQ(argument_type="body"), ) -> HttpResponse: server = validate_entity(entity) user_id = payload["user_id"] gcm_payload = payload["gcm_payload"] apns_payload = payload["apns_payload"] gcm_options = payload.get("gcm_options", {}) android_devices = list( RemotePushDeviceToken.objects.filter( user_id=user_id, kind=RemotePushDeviceToken.GCM, server=server, )) apple_devices = list( RemotePushDeviceToken.objects.filter( user_id=user_id, kind=RemotePushDeviceToken.APNS, server=server, )) logger.info( "Sending mobile push notifications for remote user %s:%s: %s via FCM devices, %s via APNs devices", server.uuid, user_id, len(android_devices), len(apple_devices), ) # Truncate incoming pushes to 200, due to APNs maximum message # sizes; see handle_remove_push_notification for the version of # this for notifications generated natively on the server. We # apply this to remote-server pushes in case they predate that # commit. def truncate_payload(payload: Dict[str, Any]) -> Dict[str, Any]: MAX_MESSAGE_IDS = 200 if payload and payload.get("event") == "remove" and payload.get( "zulip_message_ids"): ids = [int(id) for id in payload["zulip_message_ids"].split(",")] truncated_ids = list(sorted(ids))[-MAX_MESSAGE_IDS:] payload["zulip_message_ids"] = ",".join( str(id) for id in truncated_ids) return payload gcm_payload = truncate_payload(gcm_payload) send_android_push_notification(user_id, android_devices, gcm_payload, gcm_options, remote=server) if isinstance(apns_payload.get("custom"), dict) and isinstance( apns_payload["custom"].get("zulip"), dict): apns_payload["custom"]["zulip"] = truncate_payload( apns_payload["custom"]["zulip"]) send_apple_push_notification(user_id, apple_devices, apns_payload, remote=server) return json_success( request, data={ "total_android_devices": len(android_devices), "total_apple_devices": len(apple_devices), }, )