feat(fcm): Enable `fid` and deprecate `token` for Send API (#951) · firebase/firebase-admin-python@44f7246 · GitHub
Skip to content

Commit 44f7246

Browse files
authored
feat(fcm): Enable fid and deprecate token for Send API (#951)
* add fid arg and token deprecate warning to Message class and add unit tests * add fids to MulticastMessage and token deprecate warning and add unit tests * Fix lint formatting error * Position `tokens` first to guarantee backward compatibility for legacy positional arguments and add a unit test for it * Extract multicast-to-message-list conversion logic into a private helper function * Add docstring for the helper function * Add unit tests for the async function, change deprecate message and address other review comments * Fix error messages and MulticastMessage constructor and add mix types of fids and tokens * Add integration tests for fid as argument * Update integration tests error code for invalid fid target
1 parent f493fb0 commit 44f7246

5 files changed

Lines changed: 258 additions & 43 deletions

File tree

firebase_admin/_messaging_encoder.py

Lines changed: 45 additions & 12 deletions

firebase_admin/_messaging_utils.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,8 @@ def __init__(self, message, cause=None, http_response=None):
519519
class UnregisteredError(exceptions.NotFoundError):
520520
"""App instance was unregistered from FCM.
521521
522-
This usually means that the token used is no longer valid and a new one must be used."""
522+
This usually means that the registration token or installation ID (FID) used
523+
is no longer valid and a new one must be used."""
523524

524525
def __init__(self, message, cause=None, http_response=None):
525526
exceptions.NotFoundError.__init__(self, message, cause, http_response)

firebase_admin/messaging.py

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import json
2121
import asyncio
2222
import logging
23+
import warnings
2324
import requests
2425
import httpx
2526

@@ -172,13 +173,45 @@ async def send_each_async(
172173
"""
173174
return await _get_messaging_service(app).send_each_async(messages, dry_run)
174175

176+
def _get_messages_from_multicast(multicast_message: MulticastMessage) -> List[Message]:
177+
"""Extracts individual Message objects from a MulticastMessage."""
178+
if not isinstance(multicast_message, MulticastMessage):
179+
raise ValueError('Message must be an instance of messaging.MulticastMessage class.')
180+
181+
messages = []
182+
if multicast_message.tokens is not None:
183+
with warnings.catch_warnings():
184+
warnings.simplefilter("ignore", DeprecationWarning)
185+
messages.extend([Message(
186+
data=multicast_message.data,
187+
notification=multicast_message.notification,
188+
android=multicast_message.android,
189+
webpush=multicast_message.webpush,
190+
apns=multicast_message.apns,
191+
fcm_options=multicast_message.fcm_options,
192+
token=token
193+
) for token in multicast_message.tokens])
194+
195+
if multicast_message.fids is not None:
196+
messages.extend([Message(
197+
data=multicast_message.data,
198+
notification=multicast_message.notification,
199+
android=multicast_message.android,
200+
webpush=multicast_message.webpush,
201+
apns=multicast_message.apns,
202+
fcm_options=multicast_message.fcm_options,
203+
fid=fid
204+
) for fid in multicast_message.fids])
205+
206+
return messages
207+
175208
async def send_each_for_multicast_async(
176209
multicast_message: MulticastMessage,
177210
dry_run: bool = False,
178211
app: Optional[App] = None
179212
) -> BatchResponse:
180-
"""Sends the given mutlicast message to each token asynchronously via Firebase Cloud Messaging
181-
(FCM).
213+
"""Sends the given multicast message to each token or fid asynchronously via
214+
Firebase Cloud Messaging (FCM).
182215
183216
If the ``dry_run`` mode is enabled, the message will not be actually delivered to the
184217
recipients. Instead, FCM performs all the usual validations and emulates the send operation.
@@ -195,21 +228,11 @@ async def send_each_for_multicast_async(
195228
FirebaseError: If an error occurs while sending the message to the FCM service.
196229
ValueError: If the input arguments are invalid.
197230
"""
198-
if not isinstance(multicast_message, MulticastMessage):
199-
raise ValueError('Message must be an instance of messaging.MulticastMessage class.')
200-
messages = [Message(
201-
data=multicast_message.data,
202-
notification=multicast_message.notification,
203-
android=multicast_message.android,
204-
webpush=multicast_message.webpush,
205-
apns=multicast_message.apns,
206-
fcm_options=multicast_message.fcm_options,
207-
token=token
208-
) for token in multicast_message.tokens]
231+
messages = _get_messages_from_multicast(multicast_message)
209232
return await _get_messaging_service(app).send_each_async(messages, dry_run)
210233

211234
def send_each_for_multicast(multicast_message, dry_run=False, app=None):
212-
"""Sends the given mutlicast message to each token via Firebase Cloud Messaging (FCM).
235+
"""Sends the given multicast message to each token or fid via Firebase Cloud Messaging (FCM).
213236
214237
If the ``dry_run`` mode is enabled, the message will not be actually delivered to the
215238
recipients. Instead, FCM performs all the usual validations and emulates the send operation.
@@ -226,17 +249,7 @@ def send_each_for_multicast(multicast_message, dry_run=False, app=None):
226249
FirebaseError: If an error occurs while sending the message to the FCM service.
227250
ValueError: If the input arguments are invalid.
228251
"""
229-
if not isinstance(multicast_message, MulticastMessage):
230-
raise ValueError('Message must be an instance of messaging.MulticastMessage class.')
231-
messages = [Message(
232-
data=multicast_message.data,
233-
notification=multicast_message.notification,
234-
android=multicast_message.android,
235-
webpush=multicast_message.webpush,
236-
apns=multicast_message.apns,
237-
fcm_options=multicast_message.fcm_options,
238-
token=token
239-
) for token in multicast_message.tokens]
252+
messages = _get_messages_from_multicast(multicast_message)
240253
return _get_messaging_service(app).send_each(messages, dry_run)
241254

242255
def subscribe_to_topic(tokens, topic, app=None):

integration/test_messaging.py

Lines changed: 23 additions & 0 deletions

0 commit comments

Comments
 (0)