@@ -36,19 +36,21 @@ class Message(object):
3636        android: An instance of ``messaging.AndroidConfig`` (optional). 
3737        webpush: An instance of ``messaging.WebpushConfig`` (optional). 
3838        apns: An instance of ``messaging.ApnsConfig`` (optional). 
39+         fcm_options: An instance of ``messaging.FcmOptions`` (optional). 
3940        token: The registration token of the device to which the message should be sent (optional). 
4041        topic: Name of the FCM topic to which the message should be sent (optional). Topic name 
4142            may contain the ``/topics/`` prefix. 
4243        condition: The FCM condition to which the message should be sent (optional). 
4344    """ 
4445
4546    def  __init__ (self , data = None , notification = None , android = None , webpush = None , apns = None ,
46-                  token = None , topic = None , condition = None ):
47+                  fcm_options = None ,  token = None , topic = None , condition = None ):
4748        self .data  =  data 
4849        self .notification  =  notification 
4950        self .android  =  android 
5051        self .webpush  =  webpush 
5152        self .apns  =  apns 
53+         self .fcm_options  =  fcm_options 
5254        self .token  =  token 
5355        self .topic  =  topic 
5456        self .condition  =  condition 
@@ -65,8 +67,10 @@ class MulticastMessage(object):
6567        android: An instance of ``messaging.AndroidConfig`` (optional). 
6668        webpush: An instance of ``messaging.WebpushConfig`` (optional). 
6769        apns: An instance of ``messaging.ApnsConfig`` (optional). 
70+         fcm_options: An instance of ``messaging.FcmOptions`` (optional). 
6871    """ 
69-     def  __init__ (self , tokens , data = None , notification = None , android = None , webpush = None , apns = None ):
72+     def  __init__ (self , tokens , data = None , notification = None , android = None , webpush = None , apns = None ,
73+                  fcm_options = None ):
7074        _Validators .check_string_list ('MulticastMessage.tokens' , tokens )
7175        if  len (tokens ) >  100 :
7276            raise  ValueError ('MulticastMessage.tokens must not contain more than 100 tokens.' )
@@ -76,6 +80,7 @@ def __init__(self, tokens, data=None, notification=None, android=None, webpush=N
7680        self .android  =  android 
7781        self .webpush  =  webpush 
7882        self .apns  =  apns 
83+         self .fcm_options  =  fcm_options 
7984
8085
8186class  Notification (object ):
@@ -107,16 +112,18 @@ class AndroidConfig(object):
107112        data: A dictionary of data fields (optional). All keys and values in the dictionary must be 
108113            strings. When specified, overrides any data fields set via ``Message.data``. 
109114        notification: A ``messaging.AndroidNotification`` to be included in the message (optional). 
115+         fcm_options: A ``messaging.AndroidFcmOptions`` to be included in the message (optional). 
110116    """ 
111117
112118    def  __init__ (self , collapse_key = None , priority = None , ttl = None , restricted_package_name = None ,
113-                  data = None , notification = None ):
119+                  data = None , notification = None ,  fcm_options = None ):
114120        self .collapse_key  =  collapse_key 
115121        self .priority  =  priority 
116122        self .ttl  =  ttl 
117123        self .restricted_package_name  =  restricted_package_name 
118124        self .data  =  data 
119125        self .notification  =  notification 
126+         self .fcm_options  =  fcm_options 
120127
121128
122129class  AndroidNotification (object ):
@@ -165,6 +172,18 @@ def __init__(self, title=None, body=None, icon=None, color=None, sound=None, tag
165172        self .channel_id  =  channel_id 
166173
167174
175+ class  AndroidFcmOptions (object ):
176+     """Options for features provided by the FCM SDK for Android. 
177+ 
178+     Args: 
179+         analytics_label: contains additional options for features provided by the FCM Android SDK 
180+             (optional). 
181+     """ 
182+ 
183+     def  __init__ (self , analytics_label = None ):
184+         self .analytics_label  =  analytics_label 
185+ 
186+ 
168187class  WebpushConfig (object ):
169188    """Webpush-specific options that can be included in a message. 
170189
@@ -279,14 +298,17 @@ class APNSConfig(object):
279298    Args: 
280299        headers: A dictionary of headers (optional). 
281300        payload: A ``messaging.APNSPayload`` to be included in the message (optional). 
301+         fcm_options: A ``messaging.APNSFcmOptions`` instance to be included in the message 
302+             (optional). 
282303
283304    .. _APNS Documentation: https://developer.apple.com/library/content/documentation\  
284305
285306    """ 
286307
287-     def  __init__ (self , headers = None , payload = None ):
308+     def  __init__ (self , headers = None , payload = None ,  fcm_options = None ):
288309        self .headers  =  headers 
289310        self .payload  =  payload 
311+         self .fcm_options  =  fcm_options 
290312
291313
292314class  APNSPayload (object ):
@@ -387,6 +409,29 @@ def __init__(self, title=None, subtitle=None, body=None, loc_key=None, loc_args=
387409        self .launch_image  =  launch_image 
388410
389411
412+ class  APNSFcmOptions (object ):
413+     """Options for features provided by the FCM SDK for iOS. 
414+ 
415+     Args: 
416+         analytics_label: contains additional options for features provided by the FCM iOS SDK 
417+             (optional). 
418+     """ 
419+ 
420+     def  __init__ (self , analytics_label = None ):
421+         self .analytics_label  =  analytics_label 
422+ 
423+ 
424+ class  FcmOptions (object ):
425+     """Options for features provided by SDK. 
426+ 
427+     Args: 
428+         analytics_label: contains additional options to use across all platforms (optional). 
429+     """ 
430+ 
431+     def  __init__ (self , analytics_label = None ):
432+         self .analytics_label  =  analytics_label 
433+ 
434+ 
390435class  _Validators (object ):
391436    """A collection of data validation utilities. 
392437
@@ -442,6 +487,14 @@ def check_string_list(cls, label, value):
442487            raise  ValueError ('{0} must not contain non-string values.' .format (label ))
443488        return  value 
444489
490+     @classmethod  
491+     def  check_analytics_label (cls , label , value ):
492+         """Checks if the given value is a valid analytics label.""" 
493+         value  =  _Validators .check_string (label , value )
494+         if  value  is  not None  and  not  re .match (r'^[a-zA-Z0-9-_.~%]{1,50}$' , value ):
495+             raise  ValueError ('Malformed {}.' .format (label ))
496+         return  value 
497+ 
445498
446499class  MessageEncoder (json .JSONEncoder ):
447500    """A custom JSONEncoder implementation for serializing Message instances into JSON.""" 
@@ -468,13 +521,29 @@ def encode_android(cls, android):
468521            'restricted_package_name' : _Validators .check_string (
469522                'AndroidConfig.restricted_package_name' , android .restricted_package_name ),
470523            'ttl' : cls .encode_ttl (android .ttl ),
524+             'fcm_options' : cls .encode_android_fcm_options (android .fcm_options ),
471525        }
472526        result  =  cls .remove_null_values (result )
473527        priority  =  result .get ('priority' )
474528        if  priority  and  priority  not  in 'high' , 'normal' ):
475529            raise  ValueError ('AndroidConfig.priority must be "high" or "normal".' )
476530        return  result 
477531
532+     @classmethod  
533+     def  encode_android_fcm_options (cls , fcm_options ):
534+         """Encodes a AndroidFcmOptions instance into a json.""" 
535+         if  fcm_options  is  None :
536+             return  None 
537+         if  not  isinstance (fcm_options , AndroidFcmOptions ):
538+             raise  ValueError ('AndroidConfig.fcm_options must be an instance of ' 
539+                              'AndroidFcmOptions class.' )
540+         result  =  {
541+             'analytics_label' : _Validators .check_analytics_label (
542+                 'AndroidFcmOptions.analytics_label' , fcm_options .analytics_label ),
543+         }
544+         result  =  cls .remove_null_values (result )
545+         return  result 
546+ 
478547    @classmethod  
479548    def  encode_ttl (cls , ttl ):
480549        """Encodes a AndroidConfig TTL duration into a string.""" 
@@ -553,7 +622,7 @@ def encode_webpush(cls, webpush):
553622            'headers' : _Validators .check_string_dict (
554623                'WebpushConfig.headers' , webpush .headers ),
555624            'notification' : cls .encode_webpush_notification (webpush .notification ),
556-             'fcmOptions ' : cls .encode_webpush_fcm_options (webpush .fcm_options ),
625+             'fcm_options ' : cls .encode_webpush_fcm_options (webpush .fcm_options ),
557626        }
558627        return  cls .remove_null_values (result )
559628
@@ -653,6 +722,7 @@ def encode_apns(cls, apns):
653722            'headers' : _Validators .check_string_dict (
654723                'APNSConfig.headers' , apns .headers ),
655724            'payload' : cls .encode_apns_payload (apns .payload ),
725+             'fcm_options' : cls .encode_apns_fcm_options (apns .fcm_options ),
656726        }
657727        return  cls .remove_null_values (result )
658728
@@ -670,6 +740,20 @@ def encode_apns_payload(cls, payload):
670740            result [key ] =  value 
671741        return  cls .remove_null_values (result )
672742
743+     @classmethod  
744+     def  encode_apns_fcm_options (cls , fcm_options ):
745+         """Encodes an APNSFcmOptions instance into JSON.""" 
746+         if  fcm_options  is  None :
747+             return  None 
748+         if  not  isinstance (fcm_options , APNSFcmOptions ):
749+             raise  ValueError ('APNSConfig.fcm_options must be an instance of APNSFcmOptions class.' )
750+         result  =  {
751+             'analytics_label' : _Validators .check_analytics_label (
752+                 'APNSFcmOptions.analytics_label' , fcm_options .analytics_label ),
753+         }
754+         result  =  cls .remove_null_values (result )
755+         return  result 
756+ 
673757    @classmethod  
674758    def  encode_aps (cls , aps ):
675759        """Encodes an Aps instance into JSON.""" 
@@ -790,10 +874,25 @@ def default(self, obj): # pylint: disable=method-hidden
790874            'token' : _Validators .check_string ('Message.token' , obj .token , non_empty = True ),
791875            'topic' : _Validators .check_string ('Message.topic' , obj .topic , non_empty = True ),
792876            'webpush' : MessageEncoder .encode_webpush (obj .webpush ),
877+             'fcm_options' : MessageEncoder .encode_fcm_options (obj .fcm_options ),
793878        }
794879        result ['topic' ] =  MessageEncoder .sanitize_topic_name (result .get ('topic' ))
795880        result  =  MessageEncoder .remove_null_values (result )
796881        target_count  =  sum ([t  in  result  for  t  in  ['token' , 'topic' , 'condition' ]])
797882        if  target_count  !=  1 :
798883            raise  ValueError ('Exactly one of token, topic or condition must be specified.' )
799884        return  result 
885+ 
886+     @classmethod  
887+     def  encode_fcm_options (cls , fcm_options ):
888+         """Encodes an FcmOptions instance into JSON.""" 
889+         if  fcm_options  is  None :
890+             return  None 
891+         if  not  isinstance (fcm_options , FcmOptions ):
892+             raise  ValueError ('Message.fcm_options must be an instance of FcmOptions class.' )
893+         result  =  {
894+             'analytics_label' : _Validators .check_analytics_label (
895+                 'FcmOptions.analytics_label' , fcm_options .analytics_label ),
896+         }
897+         result  =  cls .remove_null_values (result )
898+         return  result 
0 commit comments