3
uQh;9                 @   s   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ZddlZddlZddl	Z	ddl
mZ ddlmZ G dd dejZejeZd)dd	Zd
d Zdd Zdd ZddddZ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G d#d$ d$e Z!G d%d& d&ej"Z#d'd( Z$dS )+z6Various helpers not related to the Telegram API itself    N)Path)sha1c               @   s   e Zd ZdZdZdZdS )_EntityTyper         N)__name__
__module____qualname__USERCHATCHANNEL r   r   4/tmp/pip-build-2nz6shyl/telethon/telethon/helpers.pyr      s   r   Tc             C   s   t jtjd| ddS )zEGenerates a random long integer (8 bytes), which is optionally signed   little)signed	byteorder)int
from_bytesosurandom)r   r   r   r   generate_random_long   s    r   c             C   s"   t jj| }|rt j|dd dS )z(Ensures that the parent directory existsT)exist_okN)r   pathdirnamemakedirs)	file_pathparentr   r   r   ensure_parent_dir_exists    s    r   c             C   s   dj dd | D S )N c             s   sP   | ]H}d t |  kodkn  rDdjdd tjd|jdD n|V  qdS )i   i r   c             s   s   | ]}t |V  qd S )N)chr).0yr   r   r   	<genexpr>+   s    z*add_surrogate.<locals>.<genexpr>.<genexpr>z<HHzutf-16leN)ordjoinstructunpackencode)r!   xr   r   r   r#   +   s   z add_surrogate.<locals>.<genexpr>)r%   )textr   r   r   add_surrogate'   s    r+   c             C   s   | j ddjdS )Nzutf-16surrogatepass)r(   decode)r*   r   r   r   del_surrogate0   s    r.   )lengthc            C   sh   |dkrt | }d|  k o&t | k n  ofd| |d    koFdkn  ofd| |   kobdkS   S )zS
    `True` if ``index`` is within a surrogate (before and after it, not at!).
    Nr   u   u   u   )len)r*   indexr/   r   r   r   within_surrogate4   s
     r2   c             C   s   |s| j  S t| }| j } |t|  }| j } t| }xttt|D ]}|| }|jdkrh||= qJ|j|j |kr|j|kr| j|8  _q|j|j | |_d|_n||= qJ|j|j |krqJ|j|kr||= qJ||j |_qJW | S )z
    Strips whitespace from the given surrogated text modifying the provided
    entities, also removing any empty (0-length) entities.

    This assumes that the length of entities is greater or equal to 0, and
    that no entity is out of bounds.
    r   )stripr0   lstriprstripreversedranger/   offset)r*   entitiesZlen_oriZleft_offsetZ	len_finalier   r   r   
strip_textB   s2    

	

r<   c             c   sB   |r| dkp| dk  r| d7 } d}x|| kr<|d7 }|V  q$W dS )z
    Generates an integer sequence starting from 1. If `retries` is
    not a zero or a positive integer value, the sequence will be
    infinite, otherwise it will end at `retries + 1`.
    Nr   r   r   )retriesZforce_retryattemptr   r   r   retry_range   s    	
r?   c                s   t j| r| I d H S | S d S )N)inspectisawaitable)valuer   r   r   _maybe_await   s    

rC   c                s   x|j  D ]\}}|sq
|j  y|I dH  W q
 tjk
rD   Y q
 tk
rV   Y q
 tk
r } z$|jdkr| jd|t|| W Y dd}~X q
 t	k
r   | jd|t|| Y q
X q
W dS )zL
    Helper to cancel one or more tasks gracefully, logging exceptions.
    N"yield from wasn't used with futurez4Unhandled exception from %s after cancelling %s (%s))rD   )
itemscancelasyncioZCancelledErrorRuntimeErrorAssertionErrorargs	exceptiontype	Exception)logZtasksnameZtaskr;   r   r   r   _cancel   s"    
rP   c             C   s8   t | dr| j}n| jj}|j r*td|j| j S )za
    Helps to cut boilerplate on async context
    managers that offer synchronous variants.
    loopz[You must use "async with" if the event loop is running (i.e. you are inside an "async def"))hasattrrQ   _clientZ
is_runningrH   run_until_complete
__aenter__)selfrQ   r   r   r   _sync_enter   s    
rW   c             G   s*   t | dr| j}n| jj}|j| j| S )NrQ   )rR   rQ   rS   rT   	__aexit__)rV   rJ   rQ   r   r   r   
_sync_exit   s    
rY   c             C   s   y| j dkrtd	j| W n" tk
r>   td
j| Y nX | jj}d|krVtjS d|krdtjS d|krrtj	S d|krtjS td	j| d S )NV   9    F?L @wy-   ]^ aF   &4) z {} does not have any entity typez2{} is not a TLObject, cannot determine entity typeZUserZChatZChannelZSelf)rZ   r[   r\   r]   r^   r_   r`   ra   )
ZSUBCLASS_OF_ID	TypeErrorformatAttributeError	__class__r   r   r
   r   r   )entityrO   r   r   r   _entity_type   s.           rg   c             C   s   | j dddd} |j dddd}t||  j }t| | j }t|| j }||dd  }|dd | |dd	  }||fS )
z7Generates the key data corresponding to the given nonce   r   T)r       N         )to_bytesr   digest)Zserver_nonceZ	new_nonceZhash1Zhash2Zhash3keyZivr   r   r   generate_key_data_from_nonce  s    rp   c                   s0   e Zd ZdZ fddZdd Zdd Z  ZS )	TotalLista  
    A list with an extra `total` property, which may not match its `len`
    since the total represents the total amount of items *available*
    somewhere else, not the items *in this list*.

    Examples:

        .. code-block:: python

            # Telethon returns these lists in some cases (for example,
            # only when a chunk is returned, but the "total" count
            # is available).
            result = await client.get_messages(chat, limit=10)

            print(result.total)  # large number
            print(len(result))  # 10
            print(result[0])  # latest message

            for x in result:  # show the 10 messages
                print(x.text)

    c                s   t  j|| d| _d S )Nr   )super__init__total)rV   rJ   kwargs)re   r   r   rs   8  s    zTotalList.__init__c             C   s   dj djdd | D | jS )Nz[{}, total={}]z, c             s   s   | ]}t |V  qd S )N)str)r!   r)   r   r   r   r#   >  s    z$TotalList.__str__.<locals>.<genexpr>)rc   r%   rt   )rV   r   r   r   __str__<  s    zTotalList.__str__c             C   s   dj djdd | D | jS )Nz[{}, total={}]z, c             s   s   | ]}t |V  qd S )N)repr)r!   r)   r   r   r   r#   B  s    z%TotalList.__repr__.<locals>.<genexpr>)rc   r%   rt   )rV   r   r   r   __repr__@  s    zTotalList.__repr__)r   r   r	   __doc__rs   rw   ry   __classcell__r   r   )re   r   rq   !  s   rq   c               @   s   e Zd ZdZddddZdd Zdd	 Zed
d Zedd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- ZdS )._FileStreama:  
    Proxy around things that represent a file and need to be used as streams
    which may or not need to be closed.

    This will handle `pathlib.Path`, `str` paths, in-memory `bytes`, and
    anything IO-like (including `aiofiles`).

    It also provides access to the name and file size (also necessary).
    N)	file_sizec            C   s8   t |trt|j }|| _d | _|| _d | _d | _d S )N)	
isinstancer   rv   Zabsolute_file_name_size_stream_close_stream)rV   filer}   r   r   r   rs   O  s    
z_FileStream.__init__c                s  t | jtrDtjj| j| _tjj| j| _t	| jd| _
d| _| S t | jtrtt| j| _tj| j| _
d| _| S tt| jdd stdt| jdd | _| j| _
d| _| jd krtt| jdd rt| jj I d H }nd}|rJt| jj I d H }t| jjdtjI d H  t| jj I d H | _t| jj|tjI d H  n:tjd	 t| jj I d H }t|| _tj|| _
d| _| S )
NrbTreadz,file description should have a `read` methodrO   Fseekabler   zRCould not determine file size beforehand so the entire file will be read in-memory)r~   r   rv   r   r   basenamer   getsizer   openr   r   bytesr0   ioBytesIOcallablegetattrrb   rC   r   tellseekSEEK_ENDSEEK_SET_logwarningr   )rV   r   posdatar   r   r   rU   Y  s@    
z_FileStream.__aenter__c                s$   | j r | jr t| jj I d H  d S )N)r   r   rC   close)rV   exc_typeexc_valexc_tbr   r   r   rX     s    z_FileStream.__aexit__c             C   s   | j S )N)r   )rV   r   r   r   r}     s    z_FileStream.file_sizec             C   s   | j S )N)r   )rV   r   r   r   rO     s    z_FileStream.namec             O   s   | j j||S )N)r   r   )rV   rJ   ru   r   r   r   r     s    z_FileStream.readc             O   s   | j j||S )N)r   readinto)rV   rJ   ru   r   r   r   r     s    z_FileStream.readintoc             O   s   | j j||S )N)r   write)rV   rJ   ru   r   r   r   r     s    z_FileStream.writec             O   s   | j j||S )N)r   fileno)rV   rJ   ru   r   r   r   r     s    z_FileStream.filenoc             O   s   | j j||S )N)r   flush)rV   rJ   ru   r   r   r   r     s    z_FileStream.flushc             O   s   | j j||S )N)r   isatty)rV   rJ   ru   r   r   r   r     s    z_FileStream.isattyc             O   s   | j j||S )N)r   readable)rV   rJ   ru   r   r   r   r     s    z_FileStream.readablec             O   s   | j j||S )N)r   readline)rV   rJ   ru   r   r   r   r     s    z_FileStream.readlinec             O   s   | j j||S )N)r   	readlines)rV   rJ   ru   r   r   r   r     s    z_FileStream.readlinesc             O   s   | j j||S )N)r   r   )rV   rJ   ru   r   r   r   r     s    z_FileStream.seekc             O   s   | j j||S )N)r   r   )rV   rJ   ru   r   r   r   r     s    z_FileStream.seekablec             O   s   | j j||S )N)r   r   )rV   rJ   ru   r   r   r   r     s    z_FileStream.tellc             O   s   | j j||S )N)r   truncate)rV   rJ   ru   r   r   r   r     s    z_FileStream.truncatec             O   s   | j j||S )N)r   writable)rV   rJ   ru   r   r   r   r     s    z_FileStream.writablec             O   s   | j j||S )N)r   
writelines)rV   rJ   ru   r   r   r   r     s    z_FileStream.writelinesc             O   s   d S )Nr   )rV   rJ   ru   r   r   r   r     s    z_FileStream.close)r   r   r	   rz   rs   rU   rX   propertyr}   rO   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r|   E  s,   	
,r|   c               C   s>   t jdkr2ytj S  tk
r.   tj j S X ntj S d S )N      )r   r   )sysversion_inforG   get_running_looprH   Zget_event_loop_policyZget_event_loopr   r   r   r   r     s    
r   )T)T)%rz   rG   r   enumr   r&   r@   logging	functoolsr   Zpathlibr   hashlibr   Enumr   	getLoggerr   r   r   r   r+   r.   r2   r<   r?   rC   rP   rW   rY   rg   rp   listrq   IOBaser|   r   r   r   r   r   <module>   s:   

	J
%	($f