U
    
ڲgV                  !   @   s  d Z ddlZddlZddlZddlZddlmZ ddlmZ ddl	Z	ddl	m
Z
 ddl	mZ ddl	mZ ddl	mZ dd	l	mZ dd
l	mZ dZddddddddddddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,g!ZejZejZejZejZejZejZejZejZejZejZejZejZejZejZej Z ej!Z!ej"Z"ej#Z#ej$Z$ej%Z%ej&Z&ej'Z'd-d. Z(d=d0d&Z)d>d1d)Z*d?d2d*Z+d@d3d'Z,dAd4d(Z-dBd5d+Z.dCd6d,Z/G d7d dZ0G d8d  d Z1G d9d dZ2G d:d dZ3G d;d< d<Z4dS )Dz Firebase Cloud Messaging module.    N)http)_auth)_http_client)_messaging_encoder)_messaging_utils)_gapic_utils)_utils)
exceptionsZ
_messagingAndroidConfigAndroidFCMOptionsAndroidNotification
APNSConfigAPNSFCMOptionsAPNSPayloadApsApsAlertBatchResponseCriticalSound	ErrorInfo
FCMOptionsLightSettingsMessageMulticastMessageNotificationQuotaExceededErrorSenderIdMismatchErrorSendResponseThirdPartyAuthErrorTopicManagementResponseUnregisteredErrorWebpushConfigWebpushFCMOptionsWebpushNotificationWebpushNotificationActionsendsend_allsend_multicast	send_eachsend_each_for_multicastsubscribe_to_topicunsubscribe_from_topicc                 C   s   t | ttS N)r   Zget_app_service_MESSAGING_ATTRIBUTE_MessagingService)app r/   </tmp/pip-unpacked-wheel-p0r7i5ii/firebase_admin/messaging.py_get_messaging_serviced   s    r1   Fc                 C   s   t || |S )a  Sends the given message via Firebase Cloud Messaging (FCM).

    If the ``dry_run`` mode is enabled, the message will not be actually delivered to the
    recipients. Instead FCM performs all the usual validations, and emulates the send operation.

    Args:
        message: An instance of ``messaging.Message``.
        dry_run: A boolean indicating whether to run the operation in dry run mode (optional).
        app: An App instance (optional).

    Returns:
        string: A message ID string that uniquely identifies the sent message.

    Raises:
        FirebaseError: If an error occurs while sending the message to the FCM service.
        ValueError: If the input arguments are invalid.
    )r1   r$   )messagedry_runr.   r/   r/   r0   r$   g   s    c                 C   s   t || |S )a  Sends each message in the given list via Firebase Cloud Messaging.

    If the ``dry_run`` mode is enabled, the message will not be actually delivered to the
    recipients. Instead FCM performs all the usual validations, and emulates the send operation.

    Args:
        messages: A list of ``messaging.Message`` instances.
        dry_run: A boolean indicating whether to run the operation in dry run mode (optional).
        app: An App instance (optional).

    Returns:
        BatchResponse: A ``messaging.BatchResponse`` instance.

    Raises:
        FirebaseError: If an error occurs while sending the message to the FCM service.
        ValueError: If the input arguments are invalid.
    )r1   r'   messagesr3   r.   r/   r/   r0   r'   {   s    c                    s6   t  tstd fdd jD }t|||S )a  Sends the given mutlicast message to each token via Firebase Cloud Messaging (FCM).

    If the ``dry_run`` mode is enabled, the message will not be actually delivered to the
    recipients. Instead FCM performs all the usual validations, and emulates the send operation.

    Args:
        multicast_message: An instance of ``messaging.MulticastMessage``.
        dry_run: A boolean indicating whether to run the operation in dry run mode (optional).
        app: An App instance (optional).

    Returns:
        BatchResponse: A ``messaging.BatchResponse`` instance.

    Raises:
        FirebaseError: If an error occurs while sending the message to the FCM service.
        ValueError: If the input arguments are invalid.
    @Message must be an instance of messaging.MulticastMessage class.c                    s.   g | ]&}t  j j j j j j|d qS )datanotificationandroidwebpushapnsfcm_optionstokenr   r8   r9   r:   r;   r<   r=   .0r>   multicast_messager/   r0   
<listcomp>   s   z+send_each_for_multicast.<locals>.<listcomp>)
isinstancer   
ValueErrortokensr1   r'   rC   r3   r.   r5   r/   rB   r0   r(      s    

	c                 C   s   t dt t|| |S )a  Sends the given list of messages via Firebase Cloud Messaging as a single batch.

    If the ``dry_run`` mode is enabled, the message will not be actually delivered to the
    recipients. Instead FCM performs all the usual validations, and emulates the send operation.

    Args:
        messages: A list of ``messaging.Message`` instances.
        dry_run: A boolean indicating whether to run the operation in dry run mode (optional).
        app: An App instance (optional).

    Returns:
        BatchResponse: A ``messaging.BatchResponse`` instance.

    Raises:
        FirebaseError: If an error occurs while sending the message to the FCM service.
        ValueError: If the input arguments are invalid.

    send_all() is deprecated. Use send_each() instead.
    z2send_all() is deprecated. Use send_each() instead.)warningswarnDeprecationWarningr1   r%   r4   r/   r/   r0   r%      s    c                    sB   t dt t tstd fdd jD }t|||S )a'  Sends the given mutlicast message to all tokens via Firebase Cloud Messaging (FCM).

    If the ``dry_run`` mode is enabled, the message will not be actually delivered to the
    recipients. Instead FCM performs all the usual validations, and emulates the send operation.

    Args:
        multicast_message: An instance of ``messaging.MulticastMessage``.
        dry_run: A boolean indicating whether to run the operation in dry run mode (optional).
        app: An App instance (optional).

    Returns:
        BatchResponse: A ``messaging.BatchResponse`` instance.

    Raises:
        FirebaseError: If an error occurs while sending the message to the FCM service.
        ValueError: If the input arguments are invalid.

    send_multicast() is deprecated. Use send_each_for_multicast() instead.
    zFsend_multicast() is deprecated. Use send_each_for_multicast() instead.r6   c                    s.   g | ]&}t  j j j j j j|d qS r7   r?   r@   rB   r/   r0   rD      s   z"send_multicast.<locals>.<listcomp>)	rI   rJ   rK   rE   r   rF   rG   r1   r%   rH   r/   rB   r0   r&      s    

	c                 C   s   t || |dS )a4  Subscribes a list of registration tokens to an FCM topic.

    Args:
        tokens: A non-empty list of device registration tokens. List may not have more than 1000
            elements.
        topic: Name of the topic to subscribe to. May contain the ``/topics/`` prefix.
        app: An App instance (optional).

    Returns:
        TopicManagementResponse: A ``TopicManagementResponse`` instance.

    Raises:
        FirebaseError: If an error occurs while communicating with instance ID service.
        ValueError: If the input arguments are invalid.
    ziid/v1:batchAddr1   make_topic_management_requestrG   topicr.   r/   r/   r0   r)      s
      c                 C   s   t || |dS )a<  Unsubscribes a list of registration tokens from an FCM topic.

    Args:
        tokens: A non-empty list of device registration tokens. List may not have more than 1000
            elements.
        topic: Name of the topic to unsubscribe from. May contain the ``/topics/`` prefix.
        app: An App instance (optional).

    Returns:
        TopicManagementResponse: A ``TopicManagementResponse`` instance.

    Raises:
        FirebaseError: If an error occurs while communicating with instance ID service.
        ValueError: If the input arguments are invalid.
    ziid/v1:batchRemoverL   rN   r/   r/   r0   r*      s
      c                   @   s0   e Zd ZdZdd Zedd Zedd ZdS )	r   zBAn error encountered when performing a topic management operation.c                 C   s   || _ || _d S r+   )_index_reason)selfindexreasonr/   r/   r0   __init__  s    zErrorInfo.__init__c                 C   s   | j S )zBIndex of the registration token to which this error is related to.)rP   rR   r/   r/   r0   rS     s    zErrorInfo.indexc                 C   s   | j S )z*String describing the nature of the error.)rQ   rV   r/   r/   r0   rT     s    zErrorInfo.reasonN)__name__
__module____qualname____doc__rU   propertyrS   rT   r/   r/   r/   r0   r     s   
c                   @   s<   e Zd ZdZdd Zedd Zedd Zedd	 Zd
S )r   z8The response received from a topic management operation.c                 C   s   t |trd|kr td|d| _d| _g | _t|d D ]D\}}d|krt|  jd7  _| jt	||d  q>|  jd7  _q>d S )Nresultsz*Unexpected topic management response: {0}.r   error   )
rE   dictrF   format_success_count_failure_count_errors	enumerateappendr   )rR   resprS   resultr/   r/   r0   rU   $  s    z TopicManagementResponse.__init__c                 C   s   | j S )zCNumber of tokens that were successfully subscribed or unsubscribed.ra   rV   r/   r/   r0   success_count1  s    z%TopicManagementResponse.success_countc                 C   s   | j S )zLNumber of tokens that could not be subscribed or unsubscribed due to errors.)rb   rV   r/   r/   r0   failure_count6  s    z%TopicManagementResponse.failure_countc                 C   s   | j S )z;A list of ``messaging.ErrorInfo`` objects (possibly empty).)rc   rV   r/   r/   r0   errors;  s    zTopicManagementResponse.errorsN)	rW   rX   rY   rZ   rU   r[   ri   rj   rk   r/   r/   r/   r0   r   !  s   

c                   @   s<   e Zd ZdZdd Zedd Zedd Zedd	 Zd
S )r   z:The response received from a batch request to the FCM API.c                 C   s   || _ tdd |D | _d S )Nc                 S   s   g | ]}|j r|qS r/   )successrA   rf   r/   r/   r0   rD   F  s      z*BatchResponse.__init__.<locals>.<listcomp>)
_responseslenra   )rR   	responsesr/   r/   r0   rU   D  s    zBatchResponse.__init__c                 C   s   | j S )z>A list of ``messaging.SendResponse`` objects (possibly empty).)rn   rV   r/   r/   r0   rp   H  s    zBatchResponse.responsesc                 C   s   | j S r+   rh   rV   r/   r/   r0   ri   M  s    zBatchResponse.success_countc                 C   s   t | j| j S r+   )ro   rp   ri   rV   r/   r/   r0   rj   Q  s    zBatchResponse.failure_countN)	rW   rX   rY   rZ   rU   r[   rp   ri   rj   r/   r/   r/   r0   r   A  s   

c                   @   s<   e Zd ZdZdd Zedd Zedd Zedd	 Zd
S )r   zHThe response received from an individual batched request to the FCM API.c                 C   s"   || _ d | _|r|dd | _d S )Nname)
_exception_message_idget)rR   rf   	exceptionr/   r/   r0   rU   Y  s    zSendResponse.__init__c                 C   s   | j S )z9A message ID string that uniquely identifies the message.)rs   rV   r/   r/   r0   
message_id_  s    zSendResponse.message_idc                 C   s   | j dk	o| j S )z3A boolean indicating if the request was successful.N)rs   rr   rV   r/   r/   r0   rl   d  s    zSendResponse.successc                 C   s   | j S )zTA ``FirebaseError`` if an error occurs while sending the message to the FCM service.)rr   rV   r/   r/   r0   ru   i  s    zSendResponse.exceptionN)	rW   rX   rY   rZ   rU   r[   rv   rl   ru   r/   r/   r/   r0   r   V  s   

c                   @   s   e Zd ZdZdZdZdZddiZe	 Z
eeeeedZdd	 Zed
d Zd&ddZd'ddZd(ddZdd Zdd Zdd Zdd Zdd Zdd Zedd  Zed!d" Zed#d$ Zd%S ))r-   zKService class that implements Firebase Cloud Messaging (FCM) functionality.z8https://fcm.googleapis.com/v1/projects/{0}/messages:sendz https://fcm.googleapis.com/batchzhttps://iid.googleapis.comZaccess_token_authtrue)ZAPNS_AUTH_ERRORZQUOTA_EXCEEDEDZSENDER_ID_MISMATCHZTHIRD_PARTY_AUTH_ERRORZUNREGISTEREDc                 C   sn   |j }|stdtj|| _ddtjd| _|j	
dtj}|j | _tj| j|d| _tj| _d S )NzProject ID is required to access Cloud Messaging service. Either set the projectId option, or use service account credentials. Alternatively, set the GOOGLE_CLOUD_PROJECT environment variable.2zfire-admin-python/{0})zX-GOOG-API-FORMAT-VERSIONzX-FIREBASE-CLIENTZhttpTimeout)
credentialtimeout)
project_idrF   r-   FCM_URLr`   _fcm_urlfirebase_admin__version___fcm_headersoptionsrt   r   ZDEFAULT_TIMEOUT_SECONDSry   get_credential_credentialZJsonHttpClient_clientr   Zauthorized_http_build_transport)rR   r.   r{   rz   r/   r/   r0   rU     s    
z_MessagingService.__init__c                 C   s   t |tstd| j|S )Nz7Message must be an instance of messaging.Message class.)rE   r   rF   JSON_ENCODERdefault)clsr2   r/   r/   r0   encode_message  s    
z _MessagingService.encode_messageFc              
   C   sf   |  ||}z| jjd| j| j|d}W n0 tjjk
rX } z| |W 5 d}~X Y n
X |d S dS )z2Sends the given message to FCM via the FCM v1 API.posturlheadersjsonNrq   )	_message_datar   bodyr}   r   requestsr	   RequestException_handle_fcm_error)rR   r2   r3   r8   rf   r]   r/   r/   r0   r$     s    
z_MessagingService.sendc              
      s   t |tstdt|dkr&tdfdd} fdd|D }zJtjjt|d.}d	d |||D }t|W  5 Q R  W S Q R X W n6 t	k
r } zt
jd
||dW 5 d}~X Y nX dS )z3Sends the given messages to FCM via the FCM v1 API.7messages must be a list of messaging.Message instances.  1messages must not contain more than 500 elements.c              
      sj   z j jd j j| d}W n< tjjk
rX } ztd  |d W Y S d }~X Y nX t|d dS d S )Nr   r   )rf   ru   )ru   )	r   r   r}   r   r   r	   r   r   r   )r8   rf   ru   rV   r/   r0   	send_data  s    
(z._MessagingService.send_each.<locals>.send_datac                    s   g | ]} | qS r/   )r   )rA   r2   r3   rR   r/   r0   rD     s     z/_MessagingService.send_each.<locals>.<listcomp>)max_workersc                 S   s   g | ]}|qS r/   r/   rm   r/   r/   r0   rD     s     z4Unknown error while making remote service calls: {0})r2   causeN)rE   listrF   ro   
concurrentZfuturesZThreadPoolExecutormapr   	Exceptionr	   ZUnknownErrorr`   )rR   r5   r3   r   Zmessage_dataexecutorrp   r]   r/   r   r0   r'     s    
 z_MessagingService.send_eachc           
   
      s   t |tstdt|dkr&tdg   fdd}tj|tjd}j	}|D ]<}t
||}tj|jjd|jd}|| qXz|  W n, tk
r }	 z|	W 5 d	}	~	X Y n
X t S d	S )
z2Sends the given messages to FCM via the batch API.r   r   r   c                    s*   d }|r |}t||} | d S r+   )_handle_batch_errorr   re   )_responser]   ru   Zsend_responserp   rR   r/   r0   batch_callback  s
    

z2_MessagingService.send_all.<locals>.batch_callback)callbackZ	batch_uriPOST)r   Zpostprocurimethodr   r   N)rE   r   rF   ro   r   ZBatchHttpRequestr-   FCM_BATCH_URLr   r   r   dumpsr   ZHttpRequest	_postprocr}   r   addexecuter   r   r   )
rR   r5   r3   r   batch	transportr2   r   reqr]   r/   r   r0   r%     s6    
 z_MessagingService.send_allc           	   
   C   s   t |tr|g}t |tr|s&tddd |D }|r@tdt |trN|sVtd|dsjd|}||d}d	tj|}z| jj	d
||tj
d}W n0 tjjk
r } z| |W 5 d}~X Y n
X t|S dS )z;Invokes the IID service for topic management functionality.z7Tokens must be a string or a non-empty list of strings.c                 S   s   g | ]}t |tr|s|qS r/   )rE   str)rA   tr/   r/   r0   rD     s     
  zC_MessagingService.make_topic_management_request.<locals>.<listcomp>z!Tokens must be non-empty strings.z!Topic must be a non-empty string.z/topics/z/topics/{0})toZregistration_tokensz{0}/{1}r   )r   r   r   N)rE   r   r   rF   
startswithr`   r-   IID_URLr   r   IID_HEADERSr   r	   r   _handle_iid_errorr   )	rR   rG   rO   Z	operationZinvalid_strr8   r   rf   r]   r/   r/   r0   rM     s2    



z/_MessagingService.make_topic_management_requestc                 C   s   dt |i}|rd|d< |S )Nr2   TZvalidate_only)r-   r   )rR   r2   r3   r8   r/   r/   r0   r     s    z_MessagingService._message_datac                 C   s   t | S )z'Handle response from batch API request.)r   loadsdecode)rR   r   r   r/   r/   r0   r     s    z_MessagingService._postprocc                 C   s   t |tjS )z)Handles errors received from the FCM API.)r   Z#handle_platform_error_from_requestsr-   _build_fcm_error_requestsrR   r]   r/   r/   r0   r     s     z#_MessagingService._handle_fcm_errorc                 C   s   |j dkrt|i }z|j  }t|tr2|}W n tk
rH   Y nX |d}d}|rhd|}nd|j j	|j j
 }t||S )z1Handles errors received from the Instance ID API.Nr]   z(Error while calling the IID service: {0}z4Unexpected HTTP response with status: {0}; body: {1})r   r   Zhandle_requests_errorr   rE   r_   rF   rt   r`   status_codecontentr   )rR   r]   r8   Zparsed_bodycodemsgr/   r/   r0   r     s$    




 
z#_MessagingService._handle_iid_errorc                 C   s   t |tjS )zMHandles errors received from the googleapiclient while making batch requests.)r   Z*handle_platform_error_from_googleapiclientr-    _build_fcm_error_googleapiclientr   r/   r/   r0   r   0  s     z%_MessagingService._handle_batch_errorc                 C   s"   |  |}|r||||jdS dS zfParses an error response from the FCM API and creates a FCM-specific exception if
        appropriate.)r   http_responseN)_build_fcm_errorr   )r   r]   r2   
error_dictexc_typer/   r/   r0   r   5  s    
z+_MessagingService._build_fcm_error_requestsc                 C   s    |  |}|r||||dS dS r   )r   )r   r]   r2   r   r   r   r/   r/   r0   r   <  s    
z2_MessagingService._build_fcm_error_googleapiclientc                 C   sF   |sd S d }| dg D ] }| ddkr| d} q:qtj |S )Ndetailsz@typez3type.googleapis.com/google.firebase.fcm.v1.FcmErrorZ	errorCode)rt   r-   FCM_ERROR_TYPES)r   r   Zfcm_codeZdetailr/   r/   r0   r   C  s    
z"_MessagingService._build_fcm_errorN)F)F)F)rW   rX   rY   rZ   r|   r   r   r   r   ZMessageEncoderr   r   r   r   r   r   rU   classmethodr   r$   r'   r%   rM   r   r   r   r   r   r   r   r   r/   r/   r/   r0   r-   o  s<   



&

r-   )FN)FN)FN)FN)FN)N)N)5rZ   concurrent.futuresr   r   rI   r   Zgoogleapiclientr   r   r~   r   r   r   r   r   r	   r,   __all__r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r   r   r   r   r1   r$   r'   r(   r%   r&   r)   r*   r   r   r   r   r-   r/   r/   r/   r0   <module>   s   &




#

 