@@ -38,19 +38,21 @@ class Message(object):
38
38
android: An instance of ``messaging.AndroidConfig`` (optional).
39
39
webpush: An instance of ``messaging.WebpushConfig`` (optional).
40
40
apns: An instance of ``messaging.ApnsConfig`` (optional).
41
+ fcm_options: An instance of ``messaging.FcmOptions`` (optional).
41
42
token: The registration token of the device to which the message should be sent (optional).
42
43
topic: Name of the FCM topic to which the message should be sent (optional). Topic name
43
44
may contain the ``/topics/`` prefix.
44
45
condition: The FCM condition to which the message should be sent (optional).
45
46
"""
46
47
47
48
def __init__ (self , data = None , notification = None , android = None , webpush = None , apns = None ,
48
- token = None , topic = None , condition = None ):
49
+ fcm_options = None , token = None , topic = None , condition = None ):
49
50
self .data = data
50
51
self .notification = notification
51
52
self .android = android
52
53
self .webpush = webpush
53
54
self .apns = apns
55
+ self .fcm_options = fcm_options
54
56
self .token = token
55
57
self .topic = topic
56
58
self .condition = condition
@@ -67,8 +69,10 @@ class MulticastMessage(object):
67
69
android: An instance of ``messaging.AndroidConfig`` (optional).
68
70
webpush: An instance of ``messaging.WebpushConfig`` (optional).
69
71
apns: An instance of ``messaging.ApnsConfig`` (optional).
72
+ fcm_options: An instance of ``messaging.FcmOptions`` (optional).
70
73
"""
71
- def __init__ (self , tokens , data = None , notification = None , android = None , webpush = None , apns = None ):
74
+ def __init__ (self , tokens , data = None , notification = None , android = None , webpush = None , apns = None ,
75
+ fcm_options = None ):
72
76
_Validators .check_string_list ('MulticastMessage.tokens' , tokens )
73
77
if len (tokens ) > 100 :
74
78
raise ValueError ('MulticastMessage.tokens must not contain more than 100 tokens.' )
@@ -78,6 +82,7 @@ def __init__(self, tokens, data=None, notification=None, android=None, webpush=N
78
82
self .android = android
79
83
self .webpush = webpush
80
84
self .apns = apns
85
+ self .fcm_options = fcm_options
81
86
82
87
83
88
class Notification (object ):
@@ -109,16 +114,18 @@ class AndroidConfig(object):
109
114
data: A dictionary of data fields (optional). All keys and values in the dictionary must be
110
115
strings. When specified, overrides any data fields set via ``Message.data``.
111
116
notification: A ``messaging.AndroidNotification`` to be included in the message (optional).
117
+ fcm_options: A ``messaging.AndroidFcmOptions`` to be included in the message (optional).
112
118
"""
113
119
114
120
def __init__ (self , collapse_key = None , priority = None , ttl = None , restricted_package_name = None ,
115
- data = None , notification = None ):
121
+ data = None , notification = None , fcm_options = None ):
116
122
self .collapse_key = collapse_key
117
123
self .priority = priority
118
124
self .ttl = ttl
119
125
self .restricted_package_name = restricted_package_name
120
126
self .data = data
121
127
self .notification = notification
128
+ self .fcm_options = fcm_options
122
129
123
130
124
131
class AndroidNotification (object ):
@@ -167,6 +174,18 @@ def __init__(self, title=None, body=None, icon=None, color=None, sound=None, tag
167
174
self .channel_id = channel_id
168
175
169
176
177
+ class AndroidFcmOptions (object ):
178
+ """Options for features provided by the FCM SDK for Android.
179
+
180
+ Args:
181
+ analytics_label: contains additional options for features provided by the FCM Android SDK
182
+ (optional).
183
+ """
184
+
185
+ def __init__ (self , analytics_label = None ):
186
+ self .analytics_label = analytics_label
187
+
188
+
170
189
class WebpushConfig (object ):
171
190
"""Webpush-specific options that can be included in a message.
172
191
@@ -281,14 +300,17 @@ class APNSConfig(object):
281
300
Args:
282
301
headers: A dictionary of headers (optional).
283
302
payload: A ``messaging.APNSPayload`` to be included in the message (optional).
303
+ fcm_options: A ``messaging.APNSFcmOptions`` instance to be included in the message
304
+ (optional).
284
305
285
306
.. _APNS Documentation: https://developer.apple.com/library/content/documentation\
286
307
/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingwithAPNs.html
287
308
"""
288
309
289
- def __init__ (self , headers = None , payload = None ):
310
+ def __init__ (self , headers = None , payload = None , fcm_options = None ):
290
311
self .headers = headers
291
312
self .payload = payload
313
+ self .fcm_options = fcm_options
292
314
293
315
294
316
class APNSPayload (object ):
@@ -389,6 +411,29 @@ def __init__(self, title=None, subtitle=None, body=None, loc_key=None, loc_args=
389
411
self .launch_image = launch_image
390
412
391
413
414
+ class APNSFcmOptions (object ):
415
+ """Options for features provided by the FCM SDK for iOS.
416
+
417
+ Args:
418
+ analytics_label: contains additional options for features provided by the FCM iOS SDK
419
+ (optional).
420
+ """
421
+
422
+ def __init__ (self , analytics_label = None ):
423
+ self .analytics_label = analytics_label
424
+
425
+
426
+ class FcmOptions (object ):
427
+ """Options for features provided by SDK.
428
+
429
+ Args:
430
+ analytics_label: contains additional options to use across all platforms (optional).
431
+ """
432
+
433
+ def __init__ (self , analytics_label = None ):
434
+ self .analytics_label = analytics_label
435
+
436
+
392
437
class _Validators (object ):
393
438
"""A collection of data validation utilities.
394
439
@@ -444,6 +489,14 @@ def check_string_list(cls, label, value):
444
489
raise ValueError ('{0} must not contain non-string values.' .format (label ))
445
490
return value
446
491
492
+ @classmethod
493
+ def check_analytics_label (cls , label , value ):
494
+ """Checks if the given value is a valid analytics label."""
495
+ value = _Validators .check_string (label , value )
496
+ if value is not None and not re .match (r'^[a-zA-Z0-9-_.~%]{1,50}$' , value ):
497
+ raise ValueError ('Malformed {}.' .format (label ))
498
+ return value
499
+
447
500
448
501
class MessageEncoder (json .JSONEncoder ):
449
502
"""A custom JSONEncoder implementation for serializing Message instances into JSON."""
@@ -470,13 +523,29 @@ def encode_android(cls, android):
470
523
'restricted_package_name' : _Validators .check_string (
471
524
'AndroidConfig.restricted_package_name' , android .restricted_package_name ),
472
525
'ttl' : cls .encode_ttl (android .ttl ),
526
+ 'fcm_options' : cls .encode_android_fcm_options (android .fcm_options ),
473
527
}
474
528
result = cls .remove_null_values (result )
475
529
priority = result .get ('priority' )
476
530
if priority and priority not in ('high' , 'normal' ):
477
531
raise ValueError ('AndroidConfig.priority must be "high" or "normal".' )
478
532
return result
479
533
534
+ @classmethod
535
+ def encode_android_fcm_options (cls , fcm_options ):
536
+ """Encodes a AndroidFcmOptions instance into a json."""
537
+ if fcm_options is None :
538
+ return None
539
+ if not isinstance (fcm_options , AndroidFcmOptions ):
540
+ raise ValueError ('AndroidConfig.fcm_options must be an instance of '
541
+ 'AndroidFcmOptions class.' )
542
+ result = {
543
+ 'analytics_label' : _Validators .check_analytics_label (
544
+ 'AndroidFcmOptions.analytics_label' , fcm_options .analytics_label ),
545
+ }
546
+ result = cls .remove_null_values (result )
547
+ return result
548
+
480
549
@classmethod
481
550
def encode_ttl (cls , ttl ):
482
551
"""Encodes a AndroidConfig TTL duration into a string."""
@@ -555,7 +624,7 @@ def encode_webpush(cls, webpush):
555
624
'headers' : _Validators .check_string_dict (
556
625
'WebpushConfig.headers' , webpush .headers ),
557
626
'notification' : cls .encode_webpush_notification (webpush .notification ),
558
- 'fcmOptions ' : cls .encode_webpush_fcm_options (webpush .fcm_options ),
627
+ 'fcm_options ' : cls .encode_webpush_fcm_options (webpush .fcm_options ),
559
628
}
560
629
return cls .remove_null_values (result )
561
630
@@ -655,6 +724,7 @@ def encode_apns(cls, apns):
655
724
'headers' : _Validators .check_string_dict (
656
725
'APNSConfig.headers' , apns .headers ),
657
726
'payload' : cls .encode_apns_payload (apns .payload ),
727
+ 'fcm_options' : cls .encode_apns_fcm_options (apns .fcm_options ),
658
728
}
659
729
return cls .remove_null_values (result )
660
730
@@ -672,6 +742,20 @@ def encode_apns_payload(cls, payload):
672
742
result [key ] = value
673
743
return cls .remove_null_values (result )
674
744
745
+ @classmethod
746
+ def encode_apns_fcm_options (cls , fcm_options ):
747
+ """Encodes an APNSFcmOptions instance into JSON."""
748
+ if fcm_options is None :
749
+ return None
750
+ if not isinstance (fcm_options , APNSFcmOptions ):
751
+ raise ValueError ('APNSConfig.fcm_options must be an instance of APNSFcmOptions class.' )
752
+ result = {
753
+ 'analytics_label' : _Validators .check_analytics_label (
754
+ 'APNSFcmOptions.analytics_label' , fcm_options .analytics_label ),
755
+ }
756
+ result = cls .remove_null_values (result )
757
+ return result
758
+
675
759
@classmethod
676
760
def encode_aps (cls , aps ):
677
761
"""Encodes an Aps instance into JSON."""
@@ -792,6 +876,7 @@ def default(self, obj): # pylint: disable=method-hidden
792
876
'token' : _Validators .check_string ('Message.token' , obj .token , non_empty = True ),
793
877
'topic' : _Validators .check_string ('Message.topic' , obj .topic , non_empty = True ),
794
878
'webpush' : MessageEncoder .encode_webpush (obj .webpush ),
879
+ 'fcm_options' : MessageEncoder .encode_fcm_options (obj .fcm_options ),
795
880
}
796
881
result ['topic' ] = MessageEncoder .sanitize_topic_name (result .get ('topic' ))
797
882
result = MessageEncoder .remove_null_values (result )
@@ -800,6 +885,20 @@ def default(self, obj): # pylint: disable=method-hidden
800
885
raise ValueError ('Exactly one of token, topic or condition must be specified.' )
801
886
return result
802
887
888
+ @classmethod
889
+ def encode_fcm_options (cls , fcm_options ):
890
+ """Encodes an FcmOptions instance into JSON."""
891
+ if fcm_options is None :
892
+ return None
893
+ if not isinstance (fcm_options , FcmOptions ):
894
+ raise ValueError ('Message.fcm_options must be an instance of FcmOptions class.' )
895
+ result = {
896
+ 'analytics_label' : _Validators .check_analytics_label (
897
+ 'FcmOptions.analytics_label' , fcm_options .analytics_label ),
898
+ }
899
+ result = cls .remove_null_values (result )
900
+ return result
901
+
803
902
804
903
class ThirdPartyAuthError (exceptions .UnauthenticatedError ):
805
904
"""APNs certificate or web push auth key was invalid or missing."""
0 commit comments