o
    l~i8                     @   s.  d dl mZ d dlmZ d dlmZ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mZ d d	lmZ d
ZG dd dejZG dd dejZejejegZdd eD Zdee defddZG dd deZG dd dej j!Z"e#e"Z$G dd dej%Z&G dd deZ'G dd de'Z(dS )    )Sequence)copy)
NamedTupleUnionN)models)gettext_lazy)	messaging)FirebaseErrorInvalidArgumentError)FCM_DJANGO_SETTINGSi  c                   @   s   e Zd ZejddddZejdeddddZej	eddedd	Z
ejed
 ddejeddZejeddddZG dd dZdd ZdS )DeviceIDT)verbose_nameprimary_keyauto_created   Name)
max_lengthr   blanknullz	Is activez/Inactive devices will not be sent notifications)r   default	help_text
USER_MODEL	fcmdevice)r   r   	on_deleterelated_query_namezCreation date)r   auto_now_addr   c                   @   s   e Zd ZdZdS )zDevice.MetaTN)__name__
__module____qualname__abstract r!   r!   X/var/www/newdalilibackend/backend/venv/lib/python3.10/site-packages/fcm_django/models.pyMeta+   s    r#   c                 C   s,   | j pt| dp	dp| jj d| jpd S )N	device_id z for zunknown user)namegetattr	__class__r   userselfr!   r!   r"   __str__.   s
   zDevice.__str__N)r   r   r   r   	AutoFieldid	CharField_r&   BooleanFieldactive
ForeignKeySETTINGSCASCADEr)   DateTimeFielddate_createdr#   r,   r!   r!   r!   r"   r      s4    
r   c                   @   s   e Zd Zdd ZdS )_FCMDeviceManagerc                 C   s
   t | jS N)FCMDeviceQuerySetmodelr*   r!   r!   r"   get_queryset7   s   
z_FCMDeviceManager.get_querysetN)r   r   r   r<   r!   r!   r!   r"   r8   6   s    r8   c                 C   s   g | ]}|j qS r!   )code.0xr!   r!   r"   
<listcomp>B   s    rA   excreturnc                 C   s:   | sdS t | }|tkr| tv S |tko| jdkp|tv S )NFzInvalid registration)typestrfcm_error_list_strr
   causefcm_error_list)rB   exc_typer!   r!   r"   $_validate_exception_for_deactivationE   s   rJ   c                   @   s:   e Zd ZU eejejf ed< ee	 ed< ee	 ed< dS )FirebaseResponseDictresponseregistration_ids_sentdeactivated_registration_idsN)
r   r   r   r   r   BatchResponseTopicManagementResponse__annotations__listrE   r!   r!   r!   r"   rK   P   s   
 rK   c                   @   s  e Zd ZedejdefddZedefddZ				dd
e
dee dee fddZdd	ed fdejd
e
dee dddef
ddZdee deeejejf  dee fddZdee fddZedefddZdd	ed fde
ded
e
dee dddefddZd	S ) r:   messagetokenc                 C   s   || _ t| S r9   )rT   r   )rS   rT   r!   r!   r"   _prepare_messageY   s   z"FCMDeviceQuerySet._prepare_messagerC   c                   C   s   t tg g g dS )NrL   rM   rN   )rK   r   rO   r!   r!   r!   r"   !get_default_send_message_response^   s
   z3FCMDeviceQuerySet.get_default_send_message_responseFNskip_registration_id_lookupadditional_registration_idsc                 C   s4   |rt |ng }|s|| jddjddd |S )a{  
        Uses the current filtering/QuerySet chain to get registration IDs

        :param skip_registration_id_lookup: skips the QuerySet lookup and solely uses
        the list of IDs from additional_registration_ids
        :param additional_registration_ids: specific registration_ids to add to the
        QuerySet lookup
        :returns a list of registration IDs
        Tr2   registration_id)flat)rR   extendfiltervalues_list)r+   rX   rY   registration_idsr!   r!   r"   get_registration_idsf   s   z&FCMDeviceQuerySet.get_registration_idsDEFAULT_FIREBASE_APPappfirebase_admin.Appc           
         s    ||}|s S g }tdt|tD ]!} fdd|||t  D }	|tj|	fd|i|j qt	t
||||dS )a7  
        Send notification of single message for all active devices in
        queryset and deactivate if DELETE_INACTIVE_DEVICES setting is set to True.
        Bulk sends using firebase.messaging.send_each. For every 500 messages, we send a
        single HTTP request to Firebase (the 500 is set by the firebase-sdk).

        :param message: firebase.messaging.Message. If `message` includes a token/id, it
        will be overridden.
        :param skip_registration_id_lookup: skips the QuerySet lookup and solely uses
        the list of IDs from additional_registration_ids
        :param additional_registration_ids: specific registration_ids to add to the
        :param app: firebase_admin.App. Specify a specific app to use
        QuerySet lookup
        :param more_send_message_kwargs: Parameters for firebase.messaging.send_each()
        - dry_run: bool. Whether to actually send the notification to the device
        If there are any new parameters, you can still specify them here.

        :raises FirebaseError
        :returns FirebaseResponseDict
        r   c                    s   g | ]}  |qS r!   )rU   )r?   rT   rS   r+   r!   r"   rA      s    
z2FCMDeviceQuerySet.send_message.<locals>.<listcomp>rc   rV   )ra   rW   rangelenMAX_MESSAGES_PER_BATCHr]   r   	send_each	responsesrK   rO   %deactivate_devices_with_error_results)
r+   rS   rX   rY   rc   more_send_message_kwargsr`   rj   imessagesr!   re   r"   send_message}   s8   zFCMDeviceQuerySet.send_messager`   resultsc                    sb   |sg S t |d tjrdd t| D }n	 fdd|D }| j|djdd | | |S )Nr   c                 S   s   g | ]\}}t |jr|qS r!   )rJ   	exception)r?   itemrT   r!   r!   r"   rA      s    zKFCMDeviceQuerySet.deactivate_devices_with_error_results.<locals>.<listcomp>c                    s    g | ]}t |jr |j qS r!   )rJ   reasonindexr>   r`   r!   r"   rA      s    registration_id__inFrZ   )
isinstancer   SendResponsezipr^   update%_delete_inactive_devices_if_requested)r+   r`   rp   deactivated_idsr!   ru   r"   rk      s   

z7FCMDeviceQuerySet.deactivate_devices_with_error_resultsc                 C   s    t d r| j|d  d S d S )NDELETE_INACTIVE_DEVICESrv   )r4   r^   delete)r+   r`   r!   r!   r"   r|      s   z7FCMDeviceQuerySet._delete_inactive_devices_if_requestedc                   C   s   t tdg ig g dS )Nrp   rV   )rK   r   rP   r!   r!   r!   r"   get_default_topic_response   s
   z,FCMDeviceQuerySet.get_default_topic_responseshould_subscribetopicc           	      K   sR   |  ||}|s|  S |rtjntj||fd|i|}t||| ||jdS )a  
        Subscribes or Unsubscribes filtered and/or given tokens/registration_ids
        to given topic.

        :param should_subscribe: whether to have these users subscribe (True) or
        unsubscribe to a topic (False).
        :param topic: Name of the topic to subscribe to. May contain the ``/topics/``
        prefix.
        :param skip_registration_id_lookup: skips the QuerySet lookup and solely uses
        the list of IDs from additional_registration_ids
        :param additional_registration_ids: specific registration_ids to add to the
        :param app: firebase_admin.App. Specify a specific app to use
        QuerySet lookup
        :param more_subscribe_kwargs: Parameters for
        ``firebase.messaging.subscribe_to_topic()``
        If there are any new parameters, you can still specify them here.

        :raises FirebaseError
        :returns FirebaseResponseDict
        rc   rV   )ra   r   r   subscribe_to_topicunsubscribe_from_topicrK   rk   errors)	r+   r   r   rX   rY   rc   more_subscribe_kwargsr`   rL   r!   r!   r"   handle_topic_subscription   s,   z+FCMDeviceQuerySet.handle_topic_subscription)FN)r   r   r   staticmethodr   MessagerE   rU   rK   rW   boolr   rR   ra   r4   ro   r   ry   	ErrorInfork   r|   r   r   r!   r!   r!   r"   r:   X   sl    	

5
r:   c                   @   s   e Zd ZdZdZdZdS )
DeviceType)iosr   )androidr   )webr   N)r   r   r   IOSANDROIDWEBr!   r!   r!   r"   r   	  s    r   c                
   @   s   e Zd ZU ejeddddedddZejeded  dZ	eje
jd	d
Ze Zded< G dd dZed fdejdddejfddZed fdededddefddZe	d dee fddZeed fdejdedddejfddZdS )!AbstractFCMDevicez	Device IDTzUnique device identifierr   )r   r   r   db_indexr   r   zRegistration tokenMYSQL_COMPATIBILITY)r   unique
   )choicesr   r:   objectsc                   @   s*   e Zd ZdZedZejddgdgZdS )zAbstractFCMDevice.MetaT
FCM devicer[   r)   fieldsN)	r   r   r   r    r0   r   r   Indexindexesr!   r!   r!   r"   r#     s
    r#   rb   rS   rc   rd   rC   c              
   K   sh   | j s	tddS | j|_ztdtj|fd|i|idW S  ty3 } z| | j|  d}~ww )a  
        Send single message. The message's token should be blank (and will be
        overridden if not). Responds with message ID string.

        :param message: firebase.messaging.Message. If `message` includes a token/id, it
        will be overridden.
        :param app: firebase_admin.App. Specify a specific app to use
        :param more_send_message_kwargs: Parameters for firebase.messaging.send_each()
        - dry_run: bool. Whether to actually send the notification to the device
        If there are any new parameters, you can still specify them here.

        :raises FirebaseError
        :returns messaging.SendResponse or FirebaseError if the device was
        deactivated due to an error.
        Nr&   rc   )r2   r   ry   r[   rT   sendr	   $deactivate_devices_with_error_result)r+   rS   rc   rl   er!   r!   r"   ro   &  s    zAbstractFCMDevice.send_messager   r   c                 K   sH   | j g}|r	tjntj||fd|i|}t||t| j||jdS )an  
        Subscribes or Unsubscribes based on instance's registration_id

        :param should_subscribe: whether to have these users subscribe (True) or
        unsubscribe to a topic (False).
        :param topic: Name of the topic to subscribe to. May contain the ``/topics/``
        prefix.
        :param app: firebase_admin.App. Specify a specific app to use
        :param more_subscribe_kwargs: Parameters for
        ``firebase.messaging.subscribe_to_topic()``
        If there are any new parameters, you can still specify them here.

        :raises FirebaseError
        :returns FirebaseResponseDict
        rc   rV   )	r[   r   r   r   rK   rD   r   rk   r   )r+   r   r   rc   r   _r_idsrL   r!   r!   r"   r   J  s$   z+AbstractFCMDevice.handle_topic_subscriptionNc                 C   s   | j |gtd|i|gS )Nr&   )r   rk   r   ry   )clsr[   firebase_excr&   r!   r!   r"   r   n  s   z6AbstractFCMDevice.deactivate_devices_with_error_result
topic_namec                 K   s(   || _ tdtj| fd|i|id S )Nr&   rc   )r   r   ry   r   )rS   r   rc   rl   r!   r!   r"   send_topic_messagev  s
   z$AbstractFCMDevice.send_topic_messager9   )r   r   r   r   r/   r0   r$   	TextFieldr4   r[   r   r   rD   FCMDeviceManagerr   rQ   r#   r   r   ry   ro   r   rE   rK   r   classmethodrR   r   r   r   r!   r!   r!   r"   r     sd   
 

(
$r   c                   @   s   e Zd ZG dd dZdS )	FCMDevicec                   @   sF   e Zd ZedZedZed sejddgdgZ	dZ
eddZd	S )
zFCMDevice.Metar   zFCM devicesr   r[   r)   r   
fcm_djangor   N)r   r   r   r0   r   verbose_name_pluralr4   r   r   r   	app_labelswapperswappable_setting	swappabler!   r!   r!   r"   r#     s    r#   N)r   r   r   r#   r!   r!   r!   r"   r     s    r   ))collections.abcr   r   typingr   r   r   	django.dbr   django.utils.translationr   r0   firebase_adminr   firebase_admin.exceptionsr	   r
   fcm_django.settingsr   r4   rh   Modelr   Managerr8   UnregisteredErrorSenderIdMismatchErrorrH   rF   r   rJ   rK   queryQuerySetr:   from_querysetr   TextChoicesr   r   r   r!   r!   r!   r"   <module>   s2    $ 
/v