Skip to content

Commit

Permalink
Add FCM v1 API (#702)
Browse files Browse the repository at this point in the history
* Add FCM v1 API

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Add Unit Tests for GCMDeviceAdmin and fix FCM v1 tests

* fixes admin test for python 3.6

---------

Co-authored-by: Tim Jahn <tim@smartfactory.ch>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored and 50-Course committed Oct 3, 2024
1 parent fa1d501 commit 645eabe
Show file tree
Hide file tree
Showing 14 changed files with 45 additions and 43 deletions.
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ You can install the library directly from pypi using pip:

.. code-block:: shell
$ pip install django-push-notifications[WP,APNS_ASYNC]
$ pip install django-push-notifications[WP,APNS,FCM]
Edit your settings.py file:
Expand Down
2 changes: 1 addition & 1 deletion docs/FCM.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Initialize the firebase admin in your ``settings.py`` file.
.. code-block:: python
# Import the firebase service
import firebase_admin
from firebase_admin import auth
# Initialize the default app
default_app = firebase_admin.initialize_app()
Expand Down
2 changes: 1 addition & 1 deletion push_notifications/conf/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from django.utils.module_loading import import_string

from ..settings import PUSH_NOTIFICATIONS_SETTINGS as SETTINGS # noqa: I001
from .app import AppConfig # noqa: F401
from .appmodel import AppModelConfig # noqa: F401
from .legacy import LegacyConfig # noqa: F401
from ..settings import PUSH_NOTIFICATIONS_SETTINGS as SETTINGS # noqa: I001


manager = None
Expand Down
1 change: 0 additions & 1 deletion push_notifications/conf/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
PLATFORMS = [
"APNS",
"FCM",
"GCM",
"WNS",
"WP",
]
Expand Down
2 changes: 1 addition & 1 deletion push_notifications/gcm.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ def send_message(
messages = [
_prepare_message(message, token) for token in chunk
]
responses = messaging.send_each(messages, dry_run=dry_run, app=app).responses
responses = messaging.send_all(messages, dry_run=dry_run, app=app).responses
ret.extend(responses)
_deactivate_devices_with_error_results(registration_ids, ret)
return messaging.BatchResponse(ret)
Expand Down
4 changes: 2 additions & 2 deletions push_notifications/models.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from firebase_admin import messaging

from .fields import HexIntegerField
from .gcm import dict_to_fcm_message
from .settings import PUSH_NOTIFICATIONS_SETTINGS as SETTINGS


Expand Down Expand Up @@ -58,7 +60,6 @@ def get_queryset(self):
class GCMDeviceQuerySet(models.query.QuerySet):
def send_message(self, message, **kwargs):
if self.exists():
from .gcm import dict_to_fcm_message, messaging
from .gcm import send_message as fcm_send_message

if not isinstance(message, messaging.Message):
Expand Down Expand Up @@ -107,7 +108,6 @@ class Meta:
verbose_name = _("FCM device")

def send_message(self, message, **kwargs):
from .gcm import dict_to_fcm_message, messaging
from .gcm import send_message as fcm_send_message

# GCM is not supported.
Expand Down
7 changes: 6 additions & 1 deletion push_notifications/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

# FCM
PUSH_NOTIFICATIONS_SETTINGS.setdefault("FIREBASE_APP", None)
PUSH_NOTIFICATIONS_SETTINGS.setdefault("FCM_MAX_RECIPIENTS", 500)
PUSH_NOTIFICATIONS_SETTINGS.setdefault("FCM_MAX_RECIPIENTS", 1000)

# APNS
if settings.DEBUG:
Expand All @@ -27,6 +27,11 @@
)

# WP (WebPush)

PUSH_NOTIFICATIONS_SETTINGS.setdefault(
"FCM_POST_URL", "https://fcm.googleapis.com/fcm/send"
)

PUSH_NOTIFICATIONS_SETTINGS.setdefault("WP_POST_URL", {
"CHROME": PUSH_NOTIFICATIONS_SETTINGS["FCM_POST_URL"],
"OPERA": PUSH_NOTIFICATIONS_SETTINGS["FCM_POST_URL"],
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ APNS =

WP = pywebpush>=1.3.0

FCM = firebase-admin>=6.2
FCM = firebase-admin>=5,<6
APNS_ASYNC = aioapns>=3.1


Expand Down
3 changes: 1 addition & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#!/usr/bin/env python
from pathlib import Path

from setuptools import setup
from pathlib import Path


this_directory = Path(__file__).parent
long_description = (this_directory / "README.rst").read_text()
Expand Down
6 changes: 3 additions & 3 deletions tests/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def test_send_bulk_messages_action(self):
admin.message_user = mock.Mock()

with mock.patch(
"firebase_admin.messaging.send_each", return_value=responses.FCM_SUCCESS
"firebase_admin.messaging.send_all", return_value=responses.FCM_SUCCESS
) as p:
admin.send_messages(request, queryset, bulk=True)

Expand Down Expand Up @@ -61,7 +61,7 @@ def test_send_single_message_action(self):
admin.message_user = mock.Mock()

with mock.patch(
"firebase_admin.messaging.send_each", return_value=responses.FCM_SUCCESS
"firebase_admin.messaging.send_all", return_value=responses.FCM_SUCCESS
) as p:
admin.send_messages(request, queryset, bulk=False)

Expand Down Expand Up @@ -102,7 +102,7 @@ def test_send_bulk_messages_action_fail(self):
)

with mock.patch(
"firebase_admin.messaging.send_each", return_value=response
"firebase_admin.messaging.send_all", return_value=response
) as p:
admin.send_messages(request, queryset, bulk=True)

Expand Down
4 changes: 2 additions & 2 deletions tests/test_gcm_push_payload.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
class GCMPushPayloadTest(TestCase):

def test_fcm_push_payload(self):
with mock.patch("firebase_admin.messaging.send_each", return_value=FCM_SUCCESS) as p:
with mock.patch("firebase_admin.messaging.send_all", return_value=FCM_SUCCESS) as p:
message = dict_to_fcm_message({"message": "Hello world"})

send_message("abc", message)
Expand All @@ -37,7 +37,7 @@ def test_fcm_push_payload(self):
self.assertEqual(message.android.notification.body, "Hello world")

def test_fcm_push_payload_many(self):
with mock.patch("firebase_admin.messaging.send_each", return_value=FCM_SUCCESS) as p:
with mock.patch("firebase_admin.messaging.send_all", return_value=FCM_SUCCESS) as p:
message = dict_to_fcm_message({"message": "Hello world"})

send_message(["abc", "123"], message)
Expand Down
1 change: 0 additions & 1 deletion tests/test_legacy_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from django.test import TestCase

from push_notifications.conf import get_manager
from push_notifications.conf.legacy import LegacyConfig
from push_notifications.exceptions import WebPushError
from push_notifications.webpush import webpush_send_message

Expand Down
50 changes: 25 additions & 25 deletions tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def test_can_create_save_device(self):
def test_fcm_send_message(self):
device = GCMDevice.objects.create(registration_id="abc", cloud_message_type="FCM")
with mock.patch(
"firebase_admin.messaging.send_each", return_value=responses.FCM_SUCCESS
"firebase_admin.messaging.send_all", return_value=responses.FCM_SUCCESS
) as p:
device.send_message("Hello world")

Expand All @@ -65,7 +65,7 @@ def test_fcm_send_message(self):
def test_fcm_send_message_with_fcm_message(self):
device = GCMDevice.objects.create(registration_id="abc", cloud_message_type="FCM")
with mock.patch(
"firebase_admin.messaging.send_each", return_value=responses.FCM_SUCCESS
"firebase_admin.messaging.send_all", return_value=responses.FCM_SUCCESS
) as p:
message_to_send = messaging.Message(
notification=messaging.Notification(
Expand Down Expand Up @@ -99,7 +99,7 @@ def test_fcm_send_message_with_fcm_message(self):
def test_fcm_send_message_extra_data(self):
device = GCMDevice.objects.create(registration_id="abc", cloud_message_type="FCM")
with mock.patch(
"firebase_admin.messaging.send_each", return_value=responses.FCM_SUCCESS
"firebase_admin.messaging.send_all", return_value=responses.FCM_SUCCESS
) as p:
device.send_message("Hello world", extra={"foo": "bar"})

Expand All @@ -125,7 +125,7 @@ def test_fcm_send_message_extra_data(self):
def test_fcm_send_message_extra_options(self):
device = GCMDevice.objects.create(registration_id="abc", cloud_message_type="FCM")
with mock.patch(
"firebase_admin.messaging.send_each", return_value=responses.FCM_SUCCESS
"firebase_admin.messaging.send_all", return_value=responses.FCM_SUCCESS
) as p:
device.send_message("Hello world", collapse_key="test_key", foo="bar")

Expand All @@ -152,7 +152,7 @@ def test_fcm_send_message_extra_options(self):
def test_fcm_send_message_extra_notification(self):
device = GCMDevice.objects.create(registration_id="abc", cloud_message_type="FCM")
with mock.patch(
"firebase_admin.messaging.send_each", return_value=responses.FCM_SUCCESS
"firebase_admin.messaging.send_all", return_value=responses.FCM_SUCCESS
) as p:
device.send_message("Hello world", extra={"icon": "test_icon"}, title="test")

Expand Down Expand Up @@ -180,7 +180,7 @@ def test_fcm_send_message_extra_notification(self):
def test_fcm_send_message_extra_options_and_notification_and_data(self):
device = GCMDevice.objects.create(registration_id="abc", cloud_message_type="FCM")
with mock.patch(
"firebase_admin.messaging.send_each", return_value=responses.FCM_SUCCESS
"firebase_admin.messaging.send_all", return_value=responses.FCM_SUCCESS
) as p:
device.send_message(
"Hello world",
Expand Down Expand Up @@ -215,7 +215,7 @@ def test_fcm_send_message_to_multiple_devices(self):
self._create_fcm_devices(["abc", "abc1"])

with mock.patch(
"firebase_admin.messaging.send_each", return_value=responses.FCM_SUCCESS_MULTIPLE
"firebase_admin.messaging.send_all", return_value=responses.FCM_SUCCESS_MULTIPLE
) as p:
GCMDevice.objects.all().send_message("Hello world")

Expand Down Expand Up @@ -245,7 +245,7 @@ def test_fcm_send_message_to_multiple_devices_fcm_message(self):
self._create_fcm_devices(["abc", "abc1"])

with mock.patch(
"firebase_admin.messaging.send_each", return_value=responses.FCM_SUCCESS_MULTIPLE
"firebase_admin.messaging.send_all", return_value=responses.FCM_SUCCESS_MULTIPLE
) as p:
message_to_send = messaging.Message(
notification=messaging.Notification(
Expand Down Expand Up @@ -283,7 +283,7 @@ def test_gcm_send_message_does_not_send(self):
device = GCMDevice.objects.create(registration_id="abc", cloud_message_type="GCM")

with mock.patch(
"firebase_admin.messaging.send_each", return_value=responses.FCM_SUCCESS_MULTIPLE
"firebase_admin.messaging.send_all", return_value=responses.FCM_SUCCESS_MULTIPLE
) as p:
message_to_send = messaging.Message(
notification=messaging.Notification(
Expand All @@ -299,7 +299,7 @@ def test_gcm_send_multiple_message_does_not_send(self):
self._create_devices(["abc", "abc1"])

with mock.patch(
"firebase_admin.messaging.send_each", return_value=responses.FCM_SUCCESS_MULTIPLE
"firebase_admin.messaging.send_all", return_value=responses.FCM_SUCCESS_MULTIPLE
) as p:
message_to_send = messaging.Message(
notification=messaging.Notification(
Expand All @@ -318,7 +318,7 @@ def test_fcm_send_message_active_devices(self):
GCMDevice.objects.create(registration_id="xyz", active=False, cloud_message_type="FCM")

with mock.patch(
"firebase_admin.messaging.send_each", return_value=responses.FCM_SUCCESS_MULTIPLE
"firebase_admin.messaging.send_all", return_value=responses.FCM_SUCCESS_MULTIPLE
) as p:
GCMDevice.objects.all().send_message("Hello world")

Expand All @@ -344,7 +344,7 @@ def test_fcm_send_message_collapse_to_multiple_devices(self):
self._create_fcm_devices(["abc", "abc1"])

with mock.patch(
"firebase_admin.messaging.send_each", return_value=responses.FCM_SUCCESS_MULTIPLE
"firebase_admin.messaging.send_all", return_value=responses.FCM_SUCCESS_MULTIPLE
) as p:
GCMDevice.objects.all().send_message("Hello world", collapse_key="test_key")

Expand Down Expand Up @@ -386,7 +386,7 @@ def test_fcm_send_message_to_single_device_with_error(self):
[SendResponse(resp={"name": "..."}, exception=error)]
)
with mock.patch(
"firebase_admin.messaging.send_each", return_value=return_value
"firebase_admin.messaging.send_all", return_value=return_value
):
device = GCMDevice.objects.get(registration_id=devices[index])
device.send_message("Hello World!")
Expand All @@ -399,7 +399,7 @@ def test_fcm_send_message_to_single_device_with_error_mismatch(self):
[SendResponse(resp={"name": "..."}, exception=OSError())]
)
with mock.patch(
"firebase_admin.messaging.send_each",
"firebase_admin.messaging.send_all",
return_value=return_value
):
# these errors are not device specific, device is not deactivated
Expand All @@ -417,7 +417,7 @@ def test_fcm_send_message_to_multiple_devices_with_error(self):
SendResponse(resp={"name": "..."}, exception=InvalidArgumentError("Invalid registration")),
])
with mock.patch(
"firebase_admin.messaging.send_each", return_value=return_value
"firebase_admin.messaging.send_all", return_value=return_value
):
GCMDevice.objects.all().send_message("Hello World")
self.assertFalse(GCMDevice.objects.get(registration_id="abc").active)
Expand All @@ -436,7 +436,7 @@ def test_fcm_send_message_to_multiple_devices_with_error_b(self):
])

with mock.patch(
"firebase_admin.messaging.send_each", return_value=return_value
"firebase_admin.messaging.send_all", return_value=return_value
):
GCMDevice.objects.all().send_message("Hello World")
self.assertTrue(GCMDevice.objects.get(registration_id="abc").active)
Expand All @@ -448,7 +448,7 @@ def test_fcm_send_message_with_no_reg_ids(self):
self._create_fcm_devices(["abc", "abc1"])

with mock.patch(
"firebase_admin.messaging.send_each",
"firebase_admin.messaging.send_all",
return_value=responses.FCM_SUCCESS_MULTIPLE
) as p:
GCMDevice.objects.filter(registration_id="xyz").send_message("Hello World")
Expand All @@ -459,17 +459,17 @@ def test_fcm_send_message_with_no_reg_ids(self):
return_value=responses.FCM_SUCCESS_MULTIPLE
) as p:
reg_ids = [obj.registration_id for obj in GCMDevice.objects.all()]
<<<<<<< HEAD
message = dict_to_fcm_message({"message": "Hello World"})
send_bulk_message(reg_ids, message)
p.assert_called_once()
=======
send_bulk_message(reg_ids, {"message": "Hello World"}, "FCM")
p.assert_called_once_with(
["abc", "abc1"], {"message": "Hello World"}, cloud_type="FCM",
application_id=None
)
>>>>>>> 34d6c54 ([pre-commit.ci] pre-commit autoupdate (#669))
with mock.patch(
"firebase_admin.messaging.send_all",
return_value=responses.FCM_SUCCESS_MULTIPLE
) as p:
reg_ids = [obj.registration_id for obj in GCMDevice.objects.all()]
message = dict_to_fcm_message({"message": "Hello World"})
send_bulk_message(reg_ids, message)
p.assert_called_once()

def test_can_save_wsn_device(self):
device = GCMDevice.objects.create(registration_id="a valid registration id")
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ deps =
pytest-django
pywebpush
djangorestframework
firebase-admin>=6.2
firebase-admin>=5,<6
dj22: Django>=2.2,<3.0
dj32: Django>=3.2,<3.3
dj40: Django>=4.0,<4.0.5
Expand Down

0 comments on commit 645eabe

Please sign in to comment.