U
    
ڲg                     @   sx   d Z ddlZddlZddlZddlZddlZddlmZ G dd dZG dd dZ	G dd dZ
G d	d
 d
ejZdS )z=Encoding and validation utils for the messaging (FCM) module.    Nc                	   @   s"   e Zd ZdZdddZdd ZdS )Messagea  A message that can be sent via Firebase Cloud Messaging.

    Contains payload information as well as recipient information. In particular, the message must
    contain exactly one of token, topic or condition fields.

    Args:
        data: A dictionary of data fields (optional). All keys and values in the dictionary must be
            strings.
        notification: An instance of ``messaging.Notification`` (optional).
        android: An instance of ``messaging.AndroidConfig`` (optional).
        webpush: An instance of ``messaging.WebpushConfig`` (optional).
        apns: An instance of ``messaging.ApnsConfig`` (optional).
        fcm_options: An instance of ``messaging.FCMOptions`` (optional).
        token: The registration token of the device to which the message should be sent (optional).
        topic: Name of the FCM topic to which the message should be sent (optional). Topic name
            may contain the ``/topics/`` prefix.
        condition: The FCM condition to which the message should be sent (optional).
    Nc
           
      C   s:   || _ || _|| _|| _|| _|| _|| _|| _|	| _d S N)	datanotificationandroidwebpushapnsfcm_optionstokentopic	condition)
selfr   r   r   r   r   r	   r
   r   r    r   E/tmp/pip-unpacked-wheel-p0r7i5ii/firebase_admin/_messaging_encoder.py__init__.   s    zMessage.__init__c                 C   s   t j| tddS )NT)cls	sort_keys)jsondumpsMessageEncoder)r   r   r   r   __str__:   s    zMessage.__str__)	NNNNNNNNN)__name__
__module____qualname____doc__r   r   r   r   r   r   r      s           
r   c                   @   s   e Zd ZdZdddZdS )MulticastMessagea~  A message that can be sent to multiple tokens via Firebase Cloud Messaging.

    Args:
        tokens: A list of registration tokens of targeted devices.
        data: A dictionary of data fields (optional). All keys and values in the dictionary must be
            strings.
        notification: An instance of ``messaging.Notification`` (optional).
        android: An instance of ``messaging.AndroidConfig`` (optional).
        webpush: An instance of ``messaging.WebpushConfig`` (optional).
        apns: An instance of ``messaging.ApnsConfig`` (optional).
        fcm_options: An instance of ``messaging.FCMOptions`` (optional).
    Nc                 C   sN   t d| t|dkr td|| _|| _|| _|| _|| _|| _	|| _
d S )NzMulticastMessage.tokensi  z>MulticastMessage.tokens must not contain more than 500 tokens.)_Validatorscheck_string_listlen
ValueErrortokensr   r   r   r   r   r	   )r   r    r   r   r   r   r   r	   r   r   r   r   K   s    zMulticastMessage.__init__)NNNNNN)r   r   r   r   r   r   r   r   r   r   >   s     r   c                   @   sr   e Zd ZdZedddZedd Zedd Zed	d
 Zedd Z	edd Z
edd Zedd ZdS )r   zA collection of data validation utilities.

    Methods provided in this class raise ``ValueErrors`` if any validations fail.
    Fc                 C   sP   |dkrdS t |ts6|r(td|td||rL|sLtd||S )z&Checks if the given value is a string.Nz{0} must be a non-empty string.z{0} must be a string.)
isinstancestrr   format)r   labelvalue	non_emptyr   r   r   check_string_   s    
z_Validators.check_stringc                 C   s*   |d krd S t |tjs&td||S )Nz{0} must be a number.)r!   numbersNumberr   r#   r   r$   r%   r   r   r   check_numberl   s
    z_Validators.check_numberc                 C   st   |dks|i krdS t |ts,td|dd |D }|rLtd|dd | D }|rptd||S )zSChecks if the given value is a dictionary comprised only of string keys and values.Nz{0} must be a dictionary.c                 S   s   g | ]}t |ts|qS r   r!   r"   .0kr   r   r   
<listcomp>{   s     
 z1_Validators.check_string_dict.<locals>.<listcomp>z%{0} must not contain non-string keys.c                 S   s   g | ]}t |ts|qS r   r,   )r.   vr   r   r   r0   ~   s     
 '{0} must not contain non-string values.)r!   dictr   r#   valuesr   r$   r%   Znon_strr   r   r   check_string_dictt   s    
z_Validators.check_string_dictc                 C   sP   |dks|g krdS t |ts,td|dd |D }|rLtd||S )z>Checks if the given value is a list comprised only of strings.Nz{0} must be a list of strings.c                 S   s   g | ]}t |ts|qS r   r,   r-   r   r   r   r0      s     
 z1_Validators.check_string_list.<locals>.<listcomp>r2   r!   listr   r#   r5   r   r   r   r      s    
z_Validators.check_string_listc                 C   sP   |dks|g krdS t |ts,td|dd |D }|rLtd||S )z>Checks if the given value is a list comprised only of numbers.Nz{0} must be a list of numbers.c                 S   s   g | ]}t |tjs|qS r   )r!   r(   r)   r-   r   r   r   r0      s      z1_Validators.check_number_list.<locals>.<listcomp>z'{0} must not contain non-number values.r7   )r   r$   r%   Z
non_numberr   r   r   check_number_list   s    
z_Validators.check_number_listc                 C   s2   t ||}|dk	r.td|s.td||S )z5Checks if the given value is a valid analytics label.Nz^[a-zA-Z0-9-_.~%]{1,50}$zMalformed {}.)r   r'   rematchr   r#   r*   r   r   r   check_analytics_label   s    z!_Validators.check_analytics_labelc                 C   s(   |dkrdS t |ts$td||S )z%Checks if the given value is boolean.Nz{0} must be a boolean.)r!   boolr   r#   r*   r   r   r   check_boolean   s
    
z_Validators.check_booleanc                 C   s*   |dkrdS t |tjs&td||S )z(Checks if the given value is a datetime.Nz{0} must be a datetime.)r!   datetimer   r#   r*   r   r   r   check_datetime   s
    z_Validators.check_datetimeN)F)r   r   r   r   classmethodr'   r+   r6   r   r9   r<   r>   r@   r   r   r   r   r   Y   s"   





r   c                   @   s  e Zd ZdZedd Zedd Zedd Zedd	 Zed
d Z	edd Z
edd Zedd Zedd Zedd Zedd Zedd Zedd Zedd Zedd Zed d! Zed"d# Zed$d% Zed&d' Zd(d) Zed*d+ Zd,S )-r   zTA custom ``JSONEncoder`` implementation for serializing Message instances into JSON.c                 C   s   dd |  D S )Nc                 S   s$   i | ]\}}|d g i fkr||qS r   r   )r.   r/   r1   r   r   r   
<dictcomp>   s       z5MessageEncoder.remove_null_values.<locals>.<dictcomp>)items)r   Z
dict_valuer   r   r   remove_null_values   s    z!MessageEncoder.remove_null_valuesc                 C   s   |dkrdS t |tjs tdtd|jtd|j| 	|j
tjd|jddtd|j| |j| |jtd	|jd
}| |}|d}|r|dkrtd|S )z0Encodes an ``AndroidConfig`` instance into JSON.Nz;Message.android must be an instance of AndroidConfig class.zAndroidConfig.collapse_keyzAndroidConfig.datazAndroidConfig.priorityTr&   z%AndroidConfig.restricted_package_namezAndroidConfig.direct_boot_ok)collapse_keyr   r   priorityrestricted_package_namettlr	   direct_boot_okrG   )highnormalz2AndroidConfig.priority must be "high" or "normal".)r!   _messaging_utilsZAndroidConfigr   r   r'   rF   r6   r   encode_android_notificationr   rG   rH   
encode_ttlrI   encode_android_fcm_optionsr	   r>   rJ   rD   get)r   r   resultrG   r   r   r   encode_android   sD      
   

 

zMessageEncoder.encode_androidc                 C   s@   |dkrdS t |tjs tddtd|ji}| |}|S )z4Encodes an ``AndroidFCMOptions`` instance into JSON.NzIAndroidConfig.fcm_options must be an instance of AndroidFCMOptions class.analytics_labelz!AndroidFCMOptions.analytics_label)r!   rM   ZAndroidFCMOptionsr   r   r<   rT   rD   r   r	   rR   r   r   r   rP      s      
z)MessageEncoder.encode_android_fcm_optionsc                 C   s   |dkrdS t |tjr$tj|d}t |tjs8td| }|dk rPtdtt	|}t|| d }|rd
|t|dS d	
|S )
z<Encodes an ``AndroidConfig`` ``TTL`` duration into a string.N)secondszUAndroidConfig.ttl must be a duration in seconds or an instance of datetime.timedelta.r   z'AndroidConfig.ttl must not be negative.    eA{0}.{1}s	   {0}s)r!   r(   r)   r?   	timedeltar   total_secondsintmathfloorr#   r"   zfill)r   rI   r\   rV   nanosr   r   r   rO      s    zMessageEncoder.encode_ttlc                 C   s   |dkrdS t |tjr$tj|d}t |tjs>td|| }|dk r\td|tt	
|}t|| d }|rd|t|dS d	|S )
z1Encodes a duration in milliseconds into a string.N)ZmillisecondszL{0} must be a duration in milliseconds or an instance of datetime.timedelta.r   z{0} must not be negative.rW   rX   rY   rZ   )r!   r(   r)   r?   r[   r   r#   r\   r]   r^   r_   r"   r`   )r   r$   msecr\   rV   ra   r   r   r   encode_milliseconds   s     z"MessageEncoder.encode_millisecondsc                 C   s~  |dkrdS t |tjs tdtd|jtd|jtd|j	td|j
tjd|jdd	td
|jtd|jtd|jtd|jtd|jtd|jtd|jtd|jtd|j|jtd|j|jtjd|jdd	td|j|j|j|j| |j tjd|j!dd	t"d|j#d}| $|}|%d}|rdt&'d|sdtd|%dr|%dstd|%dr|%d std!|%d"}|r|j(dk	r|)t*j+j,}|-d#|d"< |%d$}|r|d%krtd&d'|.  |d$< |%d(}|r<|d)kr0td*|. |d(< |%d+}|rzg }|D ]}	| /d|	}
|0|
 qT||d+< |S ),z6Encodes an ``AndroidNotification`` instance into JSON.NzLAndroidConfig.notification must be an instance of AndroidNotification class.zAndroidNotification.bodyz!AndroidNotification.body_loc_argsz AndroidNotification.body_loc_keyz AndroidNotification.click_actionzAndroidNotification.colorTrE   zAndroidNotification.iconzAndroidNotification.soundzAndroidNotification.tagzAndroidNotification.titlez"AndroidNotification.title_loc_argsz!AndroidNotification.title_loc_keyzAndroidNotification.channel_idimagezAndroidNotification.tickerz#AndroidNotification.event_timestampzAndroidNotification.priorityz*AndroidNotification.vibrate_timings_milliszAndroidNotification.visibilityz&AndroidNotification.notification_count)bodybody_loc_argsbody_loc_keyclick_actioncoloriconsoundtagtitletitle_loc_argstitle_loc_key
channel_idrd   tickersticky
event_time
local_onlynotification_priorityvibrate_timingsdefault_vibrate_timingsdefault_sounddefault_light_settingslight_settings
visibilitynotification_countri   ^#[0-9a-fA-F]{6}$z6AndroidNotification.color must be in the form #RRGGBB.rf   rg   zKAndroidNotification.body_loc_key is required when specifying body_loc_args.rn   ro   zMAndroidNotification.title_loc_key is required when specifying title_loc_args.rs   z%Y-%m-%dT%H:%M:%S.%fZru   )minlowdefaultrK   maxzNAndroidNotification.priority must be "default", "min", "low", "high" or "max".Z	PRIORITY_r{   )privatepublicsecretzGAndroidNotification.visibility must be "private", "public" or "secret".rv   )1r!   rM   ZAndroidNotificationr   r   r'   re   r   rf   rg   rh   ri   rj   rk   rl   rm   rn   ro   rp   rd   rq   rr   r@   Zevent_timestamprt   rG   r9   vibrate_timings_millisrw   rx   ry   encode_light_settingsrz   r{   r+   r|   rD   rQ   r:   r;   tzinfo
astimezoner?   timezoneutcstrftimeupperrc   append)r   r   rR   ri   rs   rG   r{   r   Zvibrate_timing_stringsrb   Zformated_stringr   r   r   rN     s                      
   .







 z*MessageEncoder.encode_android_notificationc                    s  |dkrdS t |tjs tdtjd|jdd| d|j| d|j	d}| 
|}|d	}|sntd
|d}|std|d  stdtd std stdt dkrΈ d   fdddD }|d |d |d |d d|d< |S )z/Encodes a ``LightSettings`` instance into JSON.NzNAndroidNotification.light_settings must be an instance of LightSettings class.zLightSettings.colorTrE   z&LightSettings.light_on_duration_millisz'LightSettings.light_off_duration_millis)ri   light_on_durationlight_off_durationr   z3LightSettings.light_on_duration_millis is required.r   z4LightSettings.light_off_duration_millis is required.ri   z LightSettings.color is required.r}   z^#[0-9a-fA-F]{8}$z=LightSettings.color must be in the form #RRGGBB or #RRGGBBAA.   ZFFc                    s&   g | ]}t  ||d   dd qS )      g     o@)r]   )r.   iri   r   r   r0     s     z8MessageEncoder.encode_light_settings.<locals>.<listcomp>)         r   r   r   r   r   )ZredZgreenZbluealpha)r!   rM   ZLightSettingsr   r   r'   ri   rc   Zlight_on_duration_millisZlight_off_duration_millisrD   rQ   r:   r;   r   )r   rz   rR   r   r   Zrgbar   r   r   r   p  s\       	



 
z$MessageEncoder.encode_light_settingsc                 C   s\   |dkrdS t |tjs tdtd|jtd|j| |j	| 
|jd}| |S )z/Encodes a ``WebpushConfig`` instance into JSON.Nz;Message.webpush must be an instance of WebpushConfig class.zWebpushConfig.datazWebpushConfig.headers)r   headersr   r	   )r!   rM   ZWebpushConfigr   r   r6   r   r   encode_webpush_notificationr   encode_webpush_fcm_optionsr	   rD   )r   r   rR   r   r   r   encode_webpush  s       

zMessageEncoder.encode_webpushc                 C   s,  |dkrdS t |tjs td| |jtd|jtd|j	|j
td|jtd|jtd|jtd|j|j|j|jtd	|jtd
|jtd|j|jd}|d}|r|dkrtd|jdk	r"t |jtstd|j D ](\}}||krtd||||< q| |S )z5Encodes a ``WebpushNotification`` instance into JSON.NzLWebpushConfig.notification must be an instance of WebpushNotification class.zWebpushNotification.badgezWebpushNotification.bodyzWebpushNotification.directionzWebpushNotification.iconzWebpushNotification.imagezWebpushNotification.languagezWebpushNotification.tagz$WebpushNotification.timestamp_milliszWebpushNotification.title)actionsbadgere   r   dirrj   rd   langrenotifyZrequireInteractionsilentrl   	timestamprm   vibrater   )autoZltrrtlz=WebpushNotification.direction must be "auto", "ltr" or "rtl".z/WebpushNotification.custom_data must be a dict.z7Multiple specifications for {0} in WebpushNotification.)r!   rM   ZWebpushNotificationr   #encode_webpush_notification_actionsr   r   r'   r   re   r   	directionrj   rd   languager   Zrequire_interactionr   rl   r+   Ztimestamp_millisrm   r   rQ   custom_datar3   rC   r#   rD   )r   r   rR   r   keyr%   r   r   r   r     sx    
         


z*MessageEncoder.encode_webpush_notificationc                 C   s~   |dkrdS t |tstdg }|D ]R}t |tjs>tdtd|jtd|jtd|j	d}|
| | q&|S )z;Encodes a list of ``WebpushNotificationActions`` into JSON.NzYWebpushConfig.notification.actions must be a list of WebpushNotificationAction instances.z WebpushNotificationAction.actionzWebpushNotificationAction.titlezWebpushNotificationAction.icon)actionrm   rj   )r!   r8   r   rM   ZWebpushNotificationActionr   r'   r   rm   rj   r   rD   )r   r   resultsr   rR   r   r   r   r     s.    
   z2MessageEncoder.encode_webpush_notification_actionsc                 C   sP   |dkrdS dt d|ji}| |}|d}|dk	rL|dsLtd|S )z3Encodes a ``WebpushFCMOptions`` instance into JSON.NlinkzWebpushConfig.fcm_options.linkzhttps://z+WebpushFCMOptions.link must be a HTTPS URL.)r   r'   r   rD   rQ   
startswithr   )r   optionsrR   r   r   r   r   r     s     

z)MessageEncoder.encode_webpush_fcm_optionsc                 C   sP   |dkrdS t |tjs tdtd|j| |j| 	|j
d}| |S )z-Encodes an ``APNSConfig`` instance into JSON.Nz5Message.apns must be an instance of APNSConfig class.zAPNSConfig.headers)r   payloadr	   )r!   rM   Z
APNSConfigr   r   r6   r   encode_apns_payloadr   encode_apns_fcm_optionsr	   rD   )r   r   rR   r   r   r   encode_apns  s     

zMessageEncoder.encode_apnsc                 C   sV   |dkrdS t |tjs tdd| |ji}|j D ]\}}|||< q:| |S )z.Encodes an ``APNSPayload`` instance into JSON.Nz<APNSConfig.payload must be an instance of APNSPayload class.aps)	r!   rM   ZAPNSPayloadr   
encode_apsr   r   rC   rD   )r   r   rR   r   r%   r   r   r   r     s     

z"MessageEncoder.encode_apns_payloadc                 C   sL   |dkrdS t |tjs tdtd|jtd|jd}| 	|}|S )z1Encodes an ``APNSFCMOptions`` instance into JSON.NzCAPNSConfig.fcm_options must be an instance of APNSFCMOptions class.zAPNSFCMOptions.analytics_labelzAPNSFCMOptions.image)rT   rd   )
r!   rM   ZAPNSFCMOptionsr   r   r<   rT   r'   rd   rD   rU   r   r   r   r     s     
z&MessageEncoder.encode_apns_fcm_optionsc                 C   s   t |tjstd| |jtd|j| 	|j
td|jtd|jd}|jdkrdd|d< |jdkrvd|d	< |jd
k	rt |jtstd|j D ]2\}}td| ||krtd||||< q| |S )z&Encodes an ``Aps`` instance into JSON.z1APNSPayload.aps must be an instance of Aps class.z	Aps.badgezAps.categoryzAps.thread_id)alertr   rk   categoryz	thread-idTr   zcontent-availablezmutable-contentNzAps.custom_data must be a dict.zAps.custom_data keyz'Multiple specifications for {0} in Aps.)r!   rM   ZApsr   encode_aps_alertr   r   r+   r   encode_aps_soundrk   r'   r   Z	thread_idZcontent_availableZmutable_contentr   r3   rC   r#   rD   )r   r   rR   r   valr   r   r   r   +  s*    





zMessageEncoder.encode_apsc                 C   s   |dkrdS |rt |tr|S t |tjs2tdtjd|jddtd|j	d}|j
rbd|d	< |d
 srtd|d }|dk	r|dk s|dkrtd| |S )z.Encodes an APNs sound configuration into JSON.NzKAps.sound must be a non-empty string or an instance of CriticalSound class.zCriticalSound.nameTrE   zCriticalSound.volume)namevolumer   criticalr   z-CriticalSond.name must be a non-empty string.r   r   z3CriticalSound.volume must be in the interval [0,1].)r!   r"   rM   ZCriticalSoundr   r   r'   r   r+   r   r   rD   )r   rk   rR   r   r   r   r   r   E  s&    zMessageEncoder.encode_aps_soundc                 C   s,  |dkrdS t |tr|S t |tjs.tdtd|jtd|jtd|j	td|j
td|jtd|jtd	|jtd
|jtd|jd	}|dr|dstd|dr|dstd|jdk	r"t |jtstd|j D ]\}}td| |||< q| |S )z+Encodes an ``ApsAlert`` instance into JSON.Nz<Aps.alert must be a string or an instance of ApsAlert class.zApsAlert.titlezApsAlert.subtitlezApsAlert.bodyzApsAlert.title_loc_keyzApsAlert.title_loc_argszApsAlert.loc_keyzApsAlert.loc_argszApsAlert.action_loc_keyzApsAlert.launch_image)	rm   subtitlere   title-loc-keytitle-loc-argsloc-keyloc-argszaction-loc-keyzlaunch-imager   r   z6ApsAlert.loc_key is required when specifying loc_args.r   r   zBApsAlert.title_loc_key is required when specifying title_loc_args.z$ApsAlert.custom_data must be a dict.zApsAlert.custom_data key)r!   r"   rM   ZApsAlertr   r   r'   rm   r   re   ro   r   rn   Zloc_keyZloc_argsZaction_loc_keyZlaunch_imagerQ   r   r3   rC   rD   )r   r   rR   r   r   r   r   r   r   \  sb    
      zMessageEncoder.encode_aps_alertc                 C   sT   |dkrdS t |tjs tdtd|jtd|jtd|jd}| 	|S )z.Encodes a ``Notification`` instance into JSON.Nz?Message.notification must be an instance of Notification class.zNotification.bodyzNotification.titlezNotification.image)re   rm   rd   )
r!   rM   ZNotificationr   r   r'   re   rm   rd   rD   )r   r   rR   r   r   r   encode_notification  s    z"MessageEncoder.encode_notificationc                 C   s>   |sdS d}| |r&|t|d }td|s:td|S )z<Removes the /topics/ prefix from the topic name, if present.Nz/topics/z^[a-zA-Z0-9-_\.~%]+$zMalformed topic name.)r   r   r:   r;   r   )r   r   prefixr   r   r   sanitize_topic_name  s    
z"MessageEncoder.sanitize_topic_namec                    s   t |tstj| |S t|jt|j	t
jd|jddt
d|jt|jt
jd|jddt
jd|jddt|jt|jd	 t d d< t  t fd	d
dD }|dkrtd S )NzMessage.conditionTrE   zMessage.datazMessage.tokenzMessage.topic)	r   r   r   r   r   r
   r   r   r	   r   c                    s   g | ]}| kqS r   r   )r.   trR   r   r   r0     s     z*MessageEncoder.default.<locals>.<listcomp>)r
   r   r   r   z;Exactly one of token, topic or condition must be specified.)r!   r   r   JSONEncoderr   r   rS   r   r   r   r   r'   r   r6   r   r   r   r
   r   r   r   encode_fcm_optionsr	   r   rQ   rD   sumr   )r   oZtarget_countr   r   r   r     s,    


  



zMessageEncoder.defaultc                 C   s@   |dkrdS t |tjs tddtd|ji}| |}|S )z-Encodes an ``FCMOptions`` instance into JSON.Nz<Message.fcm_options must be an instance of FCMOptions class.rT   zFCMOptions.analytics_label)r!   rM   Z
FCMOptionsr   r   r<   rT   rD   rU   r   r   r   r     s      
z!MessageEncoder.encode_fcm_optionsN)r   r   r   r   rA   rD   rS   rP   rO   rc   rN   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r      sT   





a
(

.







)

r   )r   r?   r   r^   r(   r:   Zfirebase_admin._messaging_utilsrM   r   r   r   r   r   r   r   r   r   <module>   s   $]