U
    h٢                     @   s  d dl Z d dl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 ddl	m
Z
mZmZmZ ddlmZ ddlmZmZmZ zd dlZW n ek
r   dZY nX ejrddlmZ d	Zd
ZdZG dd deZG dd deZG dd deZG dd dZ dS )    N   )AES)utilshelperserrorshints)RequestIter)TLObjecttypes	functions   )TelegramClienti   i   c                   @   s   e Zd ZdddZdS )_CdnRedirectNc                 C   s
   || _ d S N)cdn_redirect)selfr    r   =/tmp/pip-unpacked-wheel-c81u5j2r/telethon/client/downloads.py__init__    s    z_CdnRedirect.__init__)N)__name__
__module____qualname__r   r   r   r   r   r      s   r   c                   @   sJ   e Zd ZdddZdd Zdd Zdd	 Zd
d Zdd Ze	j
Ze	jZdS )_DirectDownloadIterNc
              	      s@  t jj|||d| _| j| _|	| _|	d k	rTt jj|	j||d| _| j	|	I d H | _|| _
|| _|| _d | _|| _d| _|o| jjj|k| _| js| jj| _nz| j|I d H | _W n tjk
r:   | t j I d H }
|
jD ]>}|j| jjjkr| jj|j|j|j | jj   q&q| jj| _d| _Y nX d S )N)offsetlimitF) r   uploadZGetFileRequestrequestclient_client_cdn_redirectZGetCdnFileRequest
file_tokenZ_get_cdn_clienttotal_stride_chunk_size
_last_part	_msg_data
_timed_outsessiondc_id	_exported_sender_borrow_exported_senderr   ZDcIdInvalidErrorhelpZGetConfigRequestZ
dc_options
ip_addressserver_addressZset_dcidportsave)r   filer(   r   stride
chunk_sizerequest_size	file_sizemsg_datar   configoptionr   r   r   _init%   sD      
  
z_DirectDownloadIter._initc                    s\   |   I d H }| j| t|| jjk rFt| j| _|  I d H  n| j j| j	7  _d S r   )
_requestbufferappendlenr   r   leftcloser   r"   )r   curr   r   r   _load_next_chunkK   s    z$_DirectDownloadIter._load_next_chunkc              
      sf  z| j | j| jI d H }d| _t|tjjrH| j	j
jr@tdt|t|tjjr| j	| j	jtjj| jj|jdI d H  | j | j| jI d H }|jW S |jW S W n tjk
r( } zX| jr| j	jt d  d| _| j	jt d ttI d H  |  I d H  W Y S d }~X Y n: tjk
r } zD| j	jt d | j	 |j!I d H | _d| _"|  I d H  W Y S d }~X Y n tj#tj$fk
r` } z| j%rt| jj&tj'r| jj&j(dkr҂ | j	jt d	 | j%\}}| j	j)||d
I d H }t|j*tj+s |j*j,}|j-| jj&j-kr2 |j.| jj&_.|  I d H  W Y S d }~X Y nX d S )NFzFileCdnRedirect but the GetCdnFileRequest API access for bot users is restricted. Try to change api_id to avoid FileCdnRedirect)r    request_tokenz0Got two timeouts in a row while downloading fileTz1Got timeout while downloading file, retrying oncezFile lives in another DC z4File ref expired during download; refetching message)ids)/r   Z_callr*   r   r&   
isinstancer
   r   FileCdnRedirectr   Z_mb_entity_cacheZself_bot
ValueErrorr   ZCdnFileReuploadNeededr   ZReuploadCdnFileRequestr   r    rC   bytesr   ZTimedOutError_logr   warninginfoasynciosleepTIMED_OUT_SLEEPr;   ZFileMigrateErrorr+   Znew_dcr)   ZFilerefUpgradeNeededErrorZFileReferenceExpiredErrorr%   locationInputDocumentFileLocation
thumb_sizeZget_messagesmediaMessageMediaDocumentdocumentr/   file_reference)r   resulteZchatZmsg_idmsgrU   r   r   r   r;   T   sT    
*$"
z_DirectDownloadIter._requestc                    sV   | j s
d S z>| jr(| j| j I d H  n| j | jj krF| j  I d H  W 5 d | _ X d S r   )r*   r)   r   Z_return_exported_senderZ
disconnectr   r   r   r   r@      s    z_DirectDownloadIter.closec                    s   | S r   r   rZ   r   r   r   
__aenter__   s    z_DirectDownloadIter.__aenter__c                    s   |   I d H  d S r   )r@   )r   argsr   r   r   	__aexit__   s    z_DirectDownloadIter.__aexit__)N)r   r   r   r:   rB   r;   r@   r[   r]   r   Z_sync_enter	__enter__Z
_sync_exit__exit__r   r   r   r   r   $   s    
&	6r   c                   @   s   e Zd Zdd ZdS )_GenericDownloadIterc                    s4  d}| j j| j j }| j j}| j  j|8  _d}|st|| | jk r|  I d H }| j  j| j j7  _||7 }t|| j jk }q0|| j _t|}t|t|| jD ]0}| j	
|||| j   | j  j| j7  _q|rt| j	| _|  I d H  d S t| j	d | jkr0| j	  | _| j  j| j8  _d S )N    F)r   r   r   r>   r#   r;   
memoryviewranger"   r<   r=   r?   r@   poptobytesr$   )r   databadbeforedonerA   Zmemir   r   r   rB      s,    z%_GenericDownloadIter._load_next_chunkN)r   r   r   rB   r   r   r   r   r`      s   r`   c                   @   s  e Zd Zd4dddddeeje ddd	Zd5ddd
dddddejejee	f  dddZ
d6ddddddddddeedee	e	eje	 d
ddZd7ddddddddddddeedee	e	eejjeje	 dddZddddedddddeeeeeeed	ddZddddeddddd	ddeeeeeeeeejjd d!d"Zed#d$ Zdd%d&d'Zdd%d(d)Zed*d+ Zd,d- Zed.d/ Zed0d1 Zed8d2d3ZdS )9DownloadMethodsNT)download_bigr   zhints.EntityLikezhints.FileLike)r   entityr2   rm   returnc             
      s  d}d}t |tr|j|kr,| |I dH }|r4dnd}g }|j|krL|}nVt|dst|dsddS | j|j|d|ddI dH S d	D ]}	|t||	d q|j	}t |t
jt
jfr|j}
t
jtj|d
d|j|d}ndS | j|dd|d}z*| j|||
dI dH }|tkr|n|W S  tjk
r   | |I dH }t|}|tjjkr| tj|I dH }| j|jj|dd|dI dH  Y S Y dS Y nX dS )a  
        Downloads the profile photo from the given user, chat or channel.

        Arguments
            entity (`entity`):
                From who the photo will be downloaded.

                .. note::

                    This method expects the full entity (which has the data
                    to download the photo), not an input variant.

                    It's possible that sometimes you can't fetch the entity
                    from its input (since you can get errors like
                    ``ChannelPrivateError``) but you already have it through
                    another call, like getting a forwarded message from it.

            file (`str` | `file`, optional):
                The output file path, directory, or stream-like object.
                If the path exists and is a file, it will be overwritten.
                If file is the type `bytes`, it will be downloaded in-memory
                and returned as a bytestring (i.e. ``file=bytes``, without
                parentheses or quotes).

            download_big (`bool`, optional):
                Whether to use the big version of the available photos.

        Returns
            `None` if no photo was provided, or if it was Empty. On success
            the file path is returned since it may differ from the one given.

        Example
            .. code-block:: python

                # Download your own profile photo
                path = await client.download_profile_photo('me')
                print(path)
        )iwy-l   ]^ iaFl   &4) )l   9 l   F?L i@Nrb   r   photo
chat_photo)datethumbprogress_callback)username
first_nametitleF)Z
check_hash)Zpeerphoto_idbigZprofile_photo.jpgpossible_names)r(   )rr   rt   rs   ) rF   r	   ZSUBCLASS_OF_IDZ
get_entityhasattr_download_photorq   r=   getattrrp   r
   ZUserProfilePhotoZ	ChatPhotor(   ZInputPeerPhotoFileLocationr   Zget_input_peerrx   _get_proper_filenamedownload_filerI   r   ZLocationInvalidErrorZget_input_entityr   Z_entity_typeZ_EntityTypeZCHANNELr   ZchannelsZGetFullChannelRequestZ	full_chat)r   rn   r2   rm   ZENTITIESZINPUTSrs   r|   rp   attrr(   locrW   Zietyfullr   r   r   download_profile_photo   sf    .


     
  z&DownloadMethods.download_profile_photo)rs   rt   zhints.MessageLikez&typing.Union[int, types.TypePhotoSize]zhints.ProgressCallback)r   messager2   rs   rt   ro   c                   sP  d}t |tjr4|j}|j}|jr.|j|jfnd}ntj }|}t |t	rVt
|}t |tjrvt |jtjrv|j}t |tjrt |jtjr|jjp|jj}t |tjtjfr| |||||I dH S t |tjtjfr| ||||||I dH S t |tjr|dkr| ||S t |tjtjfrL|dkrL| |||I dH S dS )av  
        Downloads the given media from a message object.

        Note that if the download is too slow, you should consider installing
        ``cryptg`` (through ``pip install cryptg``) so that decrypting the
        received data is done in C instead of Python (much faster).

        See also `Message.download_media() <telethon.tl.custom.message.Message.download_media>`.

        Arguments
            message (`Message <telethon.tl.custom.message.Message>` | :tl:`Media`):
                The media or message containing the media that will be downloaded.

            file (`str` | `file`, optional):
                The output file path, directory, or stream-like object.
                If the path exists and is a file, it will be overwritten.
                If file is the type `bytes`, it will be downloaded in-memory
                and returned as a bytestring (i.e. ``file=bytes``, without
                parentheses or quotes).

            progress_callback (`callable`, optional):
                A callback function accepting two parameters:
                ``(received bytes, total)``.

            thumb (`int` | :tl:`PhotoSize`, optional):
                Which thumbnail size from the document or photo to download,
                instead of downloading the document or photo itself.

                If it's specified but the file does not have a thumbnail,
                this method will return `None`.

                The parameter should be an integer index between ``0`` and
                ``len(sizes)``. ``0`` will download the smallest thumbnail,
                and ``len(sizes) - 1`` will download the largest thumbnail.
                You can also use negative indices, which work the same as
                they do in Python's `list`.

                You can also pass the :tl:`PhotoSize` instance to use.
                Alternatively, the thumb size type `str` may be used.

                In short, use ``thumb=0`` if you want the smallest thumbnail
                and ``thumb=-1`` if you want the largest thumbnail.

                .. note::
                    The largest thumbnail may be a video instead of a photo,
                    as they are available since layer 116 and are bigger than
                    any of the photos.

        Returns
            `None` if no media was provided, or if it was Empty. On success
            the file path is returned since it may differ from the one given.

        Example
            .. code-block:: python

                path = await client.download_media(message)
                await client.download_media(message, filename)
                # or
                path = await message.download_media()
                await message.download_media(filename)

                # Downloading to memory
                blob = await client.download_media(message, bytes)

                # Printing download progress
                def callback(current, total):
                    print('Downloaded', current, 'out of', total,
                          'bytes: {:.2%}'.format(current / total))

                await client.download_media(message, progress_callback=callback)
        N)rF   r
   Messagerr   rS   Z
input_chatr/   datetimenowstrr   Zresolve_bot_file_idZMessageServiceactionZMessageActionChatEditPhotorp   ZMessageMediaWebPageZwebpageZWebPagerU   MessageMediaPhotoPhotor~   rT   Document_download_documentZMessageMediaContact_download_contactZWebDocumentZWebDocumentNoProxy_download_web_document)r   r   r2   rs   rt   r7   rr   rS   r   r   r   download_mediaI  sZ    Q


    
     
   zDownloadMethods.download_mediapart_size_kbr6   rt   r(   keyivzhints.OutFileLike)
r   input_locationr2   r   r6   rt   r(   r   r   ro   c          	   
      s    | j ||||||||dI dH S )a  
        Low-level method to download files from their input location.

        .. note::

            Generally, you should instead use `download_media`.
            This method is intended to be a bit more low-level.

        Arguments
            input_location (:tl:`InputFileLocation`):
                The file location from which the file will be downloaded.
                See `telethon.utils.get_input_location` source for a complete
                list of supported types.

            file (`str` | `file`, optional):
                The output file path, directory, or stream-like object.
                If the path exists and is a file, it will be overwritten.

                If the file path is `None` or `bytes`, then the result
                will be saved in memory and returned as `bytes`.

            part_size_kb (`int`, optional):
                Chunk size when downloading files. The larger, the less
                requests will be made (up to 512KB maximum).

            file_size (`int`, optional):
                The file size that is about to be downloaded, if known.
                Only used if ``progress_callback`` is specified.

            progress_callback (`callable`, optional):
                A callback function accepting two parameters:
                ``(downloaded bytes, total)``. Note that the
                ``total`` is the provided ``file_size``.

            dc_id (`int`, optional):
                The data center the library should connect to in order
                to download the file. You shouldn't worry about this.

            key ('bytes', optional):
                In case of an encrypted upload (secret chats) a key is supplied

            iv ('bytes', optional):
                In case of an encrypted upload (secret chats) an iv is supplied


        Example
            .. code-block:: python

                # Download a file and print its header
                data = await client.download_file(input_file, bytes)
                print(data[:16])
        r   N)_download_file)	r   r   r2   r   r6   rt   r(   r   r   r   r   r   r     s    ?zDownloadMethods.download_file)r   r6   rt   r(   r   r   r7   r   )r   r   r2   r   r6   rt   r(   r   r   r7   r   ro   c                   s  |s|sd}n
t |}t|d }|t dkr8tdt|tjrPt|	 }|d kp^|t
k}|rnt }n$t|trt| t|d}n|}z*z| j||||	|
d2 zf3 d H W }|r|rt|||}||}t|r|I d H  |r|| |}t|r|I d H  q6 tt|dd r0|  |rD| W W ~S W nt tk
r } zT| jt d|j j! | j"||||||j j!|j j#|j j$|	|j d	
I d H  W Y W S d }~X Y nX W 5 t|ts|r|  X d S )
N@   i   r   z/The part size must be evenly divisible by 4096.wb)r5   r(   r7   r   flushz%FileCdnRedirect to CDN data center %s)
r   r2   r   r6   rt   r(   r   r   r7   r   )%r   Zget_appropriated_part_sizeintMIN_CHUNK_SIZErH   rF   pathlibPathr   absoluterI   ioBytesIOr   ensure_parent_dir_existsopenr@   _iter_downloadr   Zdecrypt_igewriteinspectisawaitabletellcallabler   r   getvaluer   rJ   r   rL   r   r(   r   Zencryption_keyZencryption_iv)r   r   r2   r   r6   rt   r(   r   r   r7   r   Z	part_sizeZ	in_memoryfchunkrrX   r   r   r   r     sn    



    



*zDownloadMethods._download_filer   r   r3   r   r4   r5   r6   r(   	r   r2   r   r3   r   r4   r5   r6   r(   c          	   
   C   s   | j ||||||||dS )a  
        Iterates over a file download, yielding chunks of the file.

        This method can be used to stream files in a more convenient
        way, since it offers more control (pausing, resuming, etc.)

        .. note::

            Using a value for `offset` or `stride` which is not a multiple
            of the minimum allowed `request_size`, or if `chunk_size` is
            different from `request_size`, the library will need to do a
            bit more work to fetch the data in the way you intend it to.

            You normally shouldn't worry about this.

        Arguments
            file (`hints.FileLike`):
                The file of which contents you want to iterate over.

            offset (`int`, optional):
                The offset in bytes into the file from where the
                download should start. For example, if a file is
                1024KB long and you just want the last 512KB, you
                would use ``offset=512 * 1024``.

            stride (`int`, optional):
                The stride of each chunk (how much the offset should
                advance between reading each chunk). This parameter
                should only be used for more advanced use cases.

                It must be bigger than or equal to the `chunk_size`.

            limit (`int`, optional):
                The limit for how many *chunks* will be yielded at most.

            chunk_size (`int`, optional):
                The maximum size of the chunks that will be yielded.
                Note that the last chunk may be less than this value.
                By default, it equals to `request_size`.

            request_size (`int`, optional):
                How many bytes will be requested to Telegram when more
                data is required. By default, as many bytes as possible
                are requested. If you would like to request data in
                smaller sizes, adjust this parameter.

                Note that values outside the valid range will be clamped,
                and the final value will also be a multiple of the minimum
                allowed size.

            file_size (`int`, optional):
                If the file size is known beforehand, you should set
                this parameter to said value. Depending on the type of
                the input file passed, this may be set automatically.

            dc_id (`int`, optional):
                The data center the library should connect to in order
                to download the file. You shouldn't worry about this.

        Yields

            `bytes` objects representing the chunks of the file if the
            right conditions are met, or `memoryview` objects instead.

        Example
            .. code-block:: python

                # Streaming `media` to an output file
                # After the iteration ends, the sender is cleaned up
                with open('photo.jpg', 'wb') as fd:
                    async for chunk in client.iter_download(media):
                        fd.write(chunk)

                # Fetching only the header of a file (32 bytes)
                # You should manually close the iterator in this case.
                #
                # "stream" is a common name for asynchronous generators,
                # and iter_download will yield `bytes` (chunks of the file).
                stream = client.iter_download(media, request_size=32)
                header = await stream.__anext__()  # "manual" version of `async for`
                await stream.close()
                assert len(header) == 32
        r   )r   r   r   r   r   iter_downloadX  s    _zDownloadMethods.iter_download)	r   r3   r   r4   r5   r6   r(   r7   r   )r   r2   r   r3   r   r4   r5   r6   r(   r7   r   c       	         C   s&  t |}|jd k	r|j}|d kr(|j}|j}|d kr:|}|d krZ|d k	rZ|| d | }|d krh|}n||k rxtd||t 8 }|tk rt}n|tkrt}||kr|t dkr|t dkr|d ks|| dkrt}| j	t
 d||| nt}| j	t
 d||| || |||||||||	|
dS )Nr   zstride must be >= chunk_sizer   z>Starting direct file download in chunks of %d at %d, stride %dz@Starting indirect file download in chunks of %d at %d, stride %d)	r2   r(   r   r3   r4   r5   r6   r7   r   )r   Z_get_file_infor(   sizerP   rH   r   MAX_CHUNK_SIZEr   rJ   r   rL   r`   )r   r2   r   r3   r   r4   r5   r6   r(   r7   r   rL   clsr   r   r   r     sj    




    zDownloadMethods._iter_downloadc                    s   | sd S dd }t t| |d} ttt| D ]}t| | tjr0| | q0 d kr`| d S t t	rr|   S t t
rt fdd| D d S t tjtjtjtjfr S d S d S )Nc                 S   s~   t | tjrdt| jfS t | tjr4dt| jfS t | tjrJd| jfS t | tjrddt	| j
fS t | tjrzd| jfS dS )Nr   r   )r   r   )rF   r
   PhotoStrippedSizer>   rI   PhotoCachedSize	PhotoSizer   PhotoSizeProgressivemaxsizes	VideoSizers   r   r   r   sort_thumbs  s    

z/DownloadMethods._get_thumb.<locals>.sort_thumbs)r   rb   c                 3   s   | ]}|j  kr|V  qd S r   )type).0tr   r   r   	<genexpr>-  s     
 z-DownloadMethods._get_thumb.<locals>.<genexpr>)listsortedreversedrd   r>   rF   r
   ZPhotoPathSizere   r   r   nextr   r   r   r   )thumbsrs   r   rk   r   r   r   
_get_thumb  s&    

 zDownloadMethods._get_thumbrZ   c              	   C   sx   t |tjrt|j}n|j}|tkr,|S t |trLt| t	|d}n|}z|| W 5 t |trr|
  X |S )Nr   )rF   r
   r   r   Zstripped_photo_to_jpgrI   r   r   r   r   r@   r   )r   r   r2   rg   r   r   r   r   _download_cached_photo_size4  s    



z+DownloadMethods._download_cached_photo_sizec           	         s   t |tjr|j}t |tjs"dS | |j|jp2g  |}|rJt |tjrNdS t |tj	rn| j
|dd|d}n| j
|dd|d}t |tjtjfr| ||S t |tjrt|j}n|j}| jtj|j|j|j|jd|||dI dH }|tkr|S |S )	z3Specialized version of .download_media() for photosNvideoz.mp4rr   rp   rz   r/   access_hashrV   rR   )r6   rt   )rF   r
   r   rp   r   r   r   Zvideo_sizesPhotoSizeEmptyr   r   r   r   r   r   r   r   r   ZInputPhotoFileLocationr/   r   rV   r   rI   )	r   rp   r2   rr   rs   rt   r   r6   rW   r   r   r   r~   J  s6    zDownloadMethods._download_photoc                 C   s   d}g }| D ]}t |tjr,|d|j qt |tjrd}|jr`|jr`|d	|j|j q|jrt||j q|jr||j q|j
rd}q||fS )z9Gets kind and possible names for :tl:`DocumentAttribute`.rU   r   audioz{} - {}voice)rF   r
   ZDocumentAttributeFilenameinsert	file_nameZDocumentAttributeAudioZ	performerrw   r=   formatr   )
attributeskindr|   r   r   r   r   _get_kind_and_namesq  s&     z#DownloadMethods._get_kind_and_namesc                    s   t |tjr|j}t |tjs"dS |dkrZ| |j\}}| j||t	|||d}d}	nR| j|dd|d}| 
|j|}	|	rt |	tjrdS t |	tjtjfr| |	|S | jtj|j|j|j|	r|	jndd||	r|	jn|j||dI dH }
|tkr|
S |S )	z7Specialized version of .download_media() for documents.N)rr   r|   rp   rz   r   rD   r   )r6   rt   r7   )rF   r
   rT   rU   r   r   r   r   r   get_extensionr   r   r   r   r   r   r   rQ   r/   r   rV   r   r   rI   )r   rU   r2   rr   rs   rt   r7   r   r|   r   rW   r   r   r   r     sB       z"DownloadMethods._download_documentc                 C   s   |j }|j}|j}|dd}|p$ddd}dj|||dd}| j|dd|||gd}|tkrh|S t|d	rv|nt	|d
}z|| W 5 ||kr|
  X |S )zw
        Specialized version of .download_media() for contacts.
        Will make use of the vCard 4.0 format.
        ;rD   z[BEGIN:VCARD
VERSION:4.0
N:{f};{l};;;
FN:{f} {l}
TEL;TYPE=cell;VALUE=uri:tel:+{p}
END:VCARD
)r   lpzutf-8contactz.vcardr{   r   r   )rv   	last_namephone_numberreplacer   encoder   rI   r}   r   r@   r   )r   Z
mm_contactr2   rv   r   r   rW   r   r   r   r   r     s6      	  
z!DownloadMethods._download_contactc           
         s   t std| |j\}}| j||t||d}|tkrFt	 }nt
|drV|}n
t|d}zpt  4 I dH P}||j4 I dH *}|jdI dH }	|	sq||	 qW 5 Q I dH R X W 5 Q I dH R X W 5 ||kr|  X |tkr| S |S )zM
        Specialized version of .download_media() for web documents.
        z]Cannot download web documents without the aiohttp dependency install it (pip install aiohttp)r{   r   r   Ni   )aiohttprH   r   r   r   r   r   rI   r   r   r}   r   r@   ZClientSessiongeturlcontentreadr   r   )
r   Zwebr2   rt   r   r|   r   r'   responser   r   r   r   r     s4      


0
z&DownloadMethods._download_web_documentc           
   	   C   sf  t | tjrt|  } | dk	r.t | ts.| S | dkr<d} ntj| rL| S tj| s\| sz"|dkrjdnt	dd |D }W n t
k
r   d}Y nX |s|stj }d||j|j|j|j|j|j}tj| |} tj| \}}tj|\}}|s|}tj||| }tj|s(|S d}	tj|d||	|}tj|sV|S |	d7 }	q,dS )a  Gets a proper filename for 'file', if this is a path.

           'kind' should be the kind of the output file (photo, document...)
           'extension' should be the extension to be added to the file if
                       the filename doesn't have any yet
           'date' should be when this file was originally sent, if known
           'possible_names' should be an ordered list of possible names

           If no modification is made to the path, any existing file
           will be overwritten.
           If any modification is made to the path, this method will
           ensure that no existing file will be overwritten.
        NrD   c                 s   s   | ]}|r|V  qd S r   r   )r   xr   r   r   r     s     z7DownloadMethods._get_proper_filename.<locals>.<genexpr>z#{}_{}-{:02}-{:02}_{:02}-{:02}-{:02}r   z	{} ({}){})rF   r   r   r   r   ospathisfileisdirr   StopIterationr   r   r   yearmonthdayhourminutesecondjoinsplitsplitext)
r2   r   	extensionrr   r|   name	directoryextrW   rk   r   r   r   r     sP    

    z$DownloadMethods._get_proper_filename)N)N)N)N)NN) r   r   r   booltypingOptionalr   r   UnionrI   r   floatr   r   tupler
   r   rG   r   r   r   r   staticmethodr   r   r~   r   r   classmethodr   r   r   r   r   r   r   rl      s     u  |  M PnF
+'
'
&
'   rl   )!r   r   r   r   r   r   rM   Zcryptor   rD   r   r   r   r   Zrequestiterr   tlr	   r
   r   r   ImportErrorTYPE_CHECKINGZtelegramclientr   r   r   rO   	Exceptionr   r   r`   rl   r   r   r   r   <module>   s.   
|3