a
    a*jG                     @  s   d dl mZ d dlZd dlZd dlmZmZ d dlmZm	Z	 d dl
mZmZmZmZmZmZmZ ddlmZ dd	lmZmZmZ G d
d deeeeZedde	dddG dd deZdS )    )annotationsN)ABCabstractmethod)versionaddedversionchanged)MongoClientMongoCollectionMongoDatabaseOptionalTypeUnioncast   )get_dependency   )MovingWindowSupportSlidingWindowCounterSupportStoragec                	      sr  e Zd ZdZdgZdBdddddd	d
d fddZeddddZeddddZeddddZ	eddddZ
edd	ddddZedddd Zd
dd!d"Zd#dd$d%Zdd
d&d'd(Zdd)d&d*d+Zdd,d&d-d.ZdCdd,dd,d,d0d1d2Zddd3d4Zdd,d,d5d6d7d8ZdDdd,d,d,dd9d:d;Zdd,d<d=d>d?ZdEdd,d,d,dd9d@dAZ  ZS )FMongoDBStorageBasezV
    Rate limit storage with MongoDB as backend.

    Depends on :pypi:`pymongo`.
    pymongolimitscounterswindowsFstrboolUnion[int, str, bool]None)uridatabase_namecounter_collection_namewindow_collection_namewrap_exceptionsoptionsreturnc                   s\   t  j|fd|i| || _||d| _| jd j| _td\| _}|| _	|| _
d| _dS )ai  
        :param uri: uri of the form ``mongodb://[user:password]@host:port?...``,
         This uri is passed directly to :class:`~pymongo.mongo_client.MongoClient`
        :param database_name: The database to use for storing the rate limit
         collections.
        :param counter_collection_name: The collection name to use for individual counters
         used in fixed window strategies
        :param window_collection_name: The collection name to use for sliding & moving window
         storage
        :param wrap_exceptions: Whether to wrap storage exceptions in
         :exc:`limits.errors.StorageError` before raising it.
        :param options: all remaining keyword arguments are passed to the
         constructor of :class:`~pymongo.mongo_client.MongoClient`
        :raise ConfigurationError: when the :pypi:`pymongo` library is not available
        r!   )r   r   r   zpymongo.errorsN)super__init___database_name_collection_mappingdependenciesmodulelibr   
lib_errors_storage_uri_storage_options_storage)selfr   r   r   r    r!   r"   _	__class__ R/var/www/html/assistant/venv/lib/python3.9/site-packages/limits/storage/mongodb.pyr%   "   s    zMongoDBStorageBase.__init__r   )r#   c                 C  s0   | j d u r*| j| jfi | j| _ |   | j S N)r.   _init_mongo_clientr,   r-   (_MongoDBStorageBase__initialize_databaser/   r3   r3   r4   storageG   s    
zMongoDBStorageBase.storager	   c                 C  s   | j | j S r5   )r9   r&   r8   r3   r3   r4   	_databaseP   s    zMongoDBStorageBase._databaser   c                 C  s   | j | jd  S )Nr   r:   r'   r8   r3   r3   r4   r   T   s    zMongoDBStorageBase.countersc                 C  s   | j | jd  S )Nr   r;   r8   r3   r3   r4   r   X   s    zMongoDBStorageBase.windowsOptional[str]r   r"   r#   c                 K  s
   t  d S r5   )NotImplementedErrorr/   r   r"   r3   r3   r4   r6   \   s    z%MongoDBStorageBase._init_mongo_clientz3Union[Type[Exception], tuple[Type[Exception], ...]]c                 C  s   | j jS r5   )r+   ZPyMongoErrorr8   r3   r3   r4   base_exceptionsb   s    z"MongoDBStorageBase.base_exceptionsc                 C  s$   | j jddd | jjddd d S )NexpireAtr   )ZexpireAfterSeconds)r   Zcreate_indexr   r8   r3   r3   r4   Z__initialize_databaseh   s    z(MongoDBStorageBase.__initialize_databasezOptional[int]c                 C  s4   | j i | ji  }| j   | j  t|S )z^
        Delete all rate limit keys in the rate limit collections (counters, windows)
        )r   Zcount_documentsr   Zdropint)r/   Znum_keysr3   r3   r4   resetl   s    

zMongoDBStorageBase.reset)keyr#   c                 C  s$   | j d|i | jd|i dS )z>
        :param key: the key to clear rate limits for
        _idN)r   Zfind_one_and_deleter   )r/   rD   r3   r3   r4   clearv   s    zMongoDBStorageBase.clearfloatc                 C  s6   | j d|i}|r|d ntj jtjjd S )z;
        :param key: the key to get the expiry for
        rE   rA   tzinfo)r   find_onedatetimenowreplacetimezoneutc	timestampr/   rD   counterr3   r3   r4   
get_expiry}   s
    zMongoDBStorageBase.get_expiryrB   c                 C  s8   | j j|dtjtjjiddgd}|r4|d p6dS )zB
        :param key: the key to get the counter value for
        $gte)rE   rA   count)
projectionr   )r   rJ   rK   rL   rN   rO   rQ   r3   r3   r4   get   s    zMongoDBStorageBase.getr   )rD   expiryelastic_expiryamountr#   c              
   C  s   t j t jjt j|d }t| jjd|idddddgi|dd	|gid
iddddgi||r`|ndd
idigddg| jj	j
dd S )z
        increments the counter for a given rate limit key

        :param key: the key to increment
        :param expiry: amount in seconds for the key to expire in
        :param amount: the number to increment by
        secondsrE   $set$condz$ltz	$expireAt$$NOW$addz$countifZthenelse)rU   rA   TrU   )upsertrV   return_document)rK   rL   rN   rO   	timedeltarB   r   find_one_and_updater*   ReturnDocumentAFTER)r/   rD   rX   rY   rZ   Z
expirationr3   r3   r4   incr   s:    




zMongoDBStorageBase.incrc                 C  s$   z| j   W dS    Y dS 0 dS )zm
        Check if storage is healthy by calling :meth:`pymongo.mongo_client.MongoClient.server_info`
        TFN)r9   Zserver_infor8   r3   r3   r4   check   s
    
zMongoDBStorageBase.checkztuple[float, int])rD   limitrX   r#   c                 C  s   t   }t| jdd|iiddddddd	|| gid
iiiddiddddiddidig}|r||d d |d d fS |dfS )z
        returns the starting point and the number of entries in the moving
        window

        :param key: rate limit key
        :param expiry: expiry of entry
        :return: (start of window, number of acquired entries)
        z$matchrE   z$projectentriesz$filterz$entriesentryrT   z$$entry)inputasZcondz$unwindz$groupz$_idz$minz$sumr   )rE   minrU   r   rq   rU   )timelistr   Z	aggregate)r/   rD   rl   rX   rP   resultr3   r3   r4   get_moving_window   s6    	
z$MongoDBStorageBase.get_moving_window)rD   rl   rX   rZ   r#   c                 C  s   ||krdS t   }znd|g| d|didtjtjjtj|d id}| jjd|d	||  d
d|| iii|dd W dS  | jj	j
y   Y dS 0 dS )z
        :param key: rate limit key to acquire an entry in
        :param limit: amount of entries allowed
        :param expiry: expiry of the entry
        :param amount: the number of entries to acquire
        Frm   r   )z$eachz	$positionz$slicerA   r[   )z$pushr]   rE   zentries.z$notrT   T)rd   N)rr   rK   rL   rN   rO   rf   r   Z
update_oner*   errorsZDuplicateKeyError)r/   rD   rl   rX   rZ   rP   Zupdatesr3   r3   r4   acquire_entry   s6    
	z MongoDBStorageBase.acquire_entryztuple[int, float, int, float])rD   rX   r#   c              
   C  s"  |d }| j jd|iddddddgi|gid	d
dgid	ddgididddddgi|gidd	d
dgididddddgi|gidd|giddidig| jjjg dd }r|dr|d jtjj	d
 nt }td|t  }td|d r|| nd}|d ||d |fS dS )N  rE   r]   r^   $lte	$subtract
$expiresAtr_   $ifNull$currentCountr   $previousCountra   r`   )previousCountcurrentCount	expiresAt)r   r   r   )re   rV   r   rH   r   r   )r           r   r   )r   rg   r*   rh   ri   rW   rM   rK   rN   rO   rP   rr   max)r/   rD   rX   	expiry_msrt   Z
expires_atZcurrent_ttlZprev_ttlr3   r3   r4   get_sliding_window$  sj    





,3z%MongoDBStorageBase.get_sliding_windowc                 C  sl  |d }| j jd|iddddddd	gi|gid
ddgid
ddgidiiidddddd	gi|gidd
ddgididdddd	gi|giddddgidd|gidd	d| gididdididdddddddddddd	|gigigi|gigidgiiiidddddd|gi|gidd|giddiiiddddd|gi|giiiddgig| jjjdd}tt|d S )Nrx   rE   r]   r   r^   ry   rz   r{   r_   r|   r}   r   r~   ra   z$gtr`   r   )r   r   ZcurWeightedCountz$floorz	$multiplyz$dividez$maxr   z$curWeightedCountZ	_acquiredz$unsetT)re   rd   )r   rg   r*   rh   ri   r   r   )r/   rD   rl   rX   rZ   r   rt   r3   r3   r4   acquire_sliding_window_entryi  s    







#&

qvz/MongoDBStorageBase.acquire_sliding_window_entry)r   r   r   F)Fr   )r   )r   )__name__
__module____qualname____doc__ZDEPENDENCIESr%   propertyr9   r:   r   r   r   r6   r@   r7   rC   rF   rS   rW   rj   rk   ru   rw   r   r   __classcell__r3   r3   r1   r4   r      s@        %
 -*,F r   z2.1)versionz3.14.0zEAdded option to select custom collection names for windows & counters)r   reasonc                   @  s&   e Zd ZddgZddddddZd	S )
MongoDBStorageZmongodbzmongodb+srvr<   r   r   r=   c                 K  s   t t| jj|fi |S r5   )r   r   r*   r?   r3   r3   r4   r6     s    z!MongoDBStorage._init_mongo_clientN)r   r   r   ZSTORAGE_SCHEMEr6   r3   r3   r3   r4   r     s   r   )
__future__r   rK   rr   abcr   r   Zdeprecated.sphinxr   r   Zlimits.typingr   r   r	   r
   r   r   r   utilr   baser   r   r   r   r   r3   r3   r3   r4   <module>   s&   $

   R