o
    {gt1                     @   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mZ ddlZdad$ddZd%d
dZd&ddZd'ddZd'ddZdd Zdd Zd(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S ))z?
The Utils class contains many functions for project-wide use.
    N)futures)logceilF  @ c              
   C   s   t | dkrt| d | dS t|d;}| D ]/}t|d}||}|r3|| ||}|s'W d   n1 s=w   Y  t| qW d   dS 1 sSw   Y  dS )z
	Combines files.

	:param parts: Source files.
	:type parts: list of strings
	:param dest: Destination file.
	:type dest: string
    :param chunkSize: Fetching chunk size.
	:type chunkSize: int

	   r   wbrbN)lenshutilmoveopenreadwriteosremove)partsdest	chunkSizeoutputpartinputdata r   l/var/www/bot.gig.net.ua/public_html/telegram/P1/HellBot/venv/lib/python3.10/site-packages/pySmartDL/utils.pycombine_files   s   


"r   utf-8c                 C   sH   t j| \}}}}}t j|d}t j|d}t j|||||fS )u  
    Sometimes you get an URL by a user that just isn't a real
    URL because it contains unsafe characters like ' ' and so on.  This
    function can fix some of the problems in a similar way browsers
    handle data entered by the user:

    >>> url_fix(u'http://de.wikipedia.org/wiki/Elf (Begriffsklärung)')
    'http://de.wikipedia.org/wiki/Elf%20%28Begriffskl%C3%A4rung%29'

    :param s: Url address.
    :type s: string
    :param charset: The target charset for the URL if the url was
                    given as unicode string. Default is 'utf-8'.
    :type charset: string
    :rtype: string
                    
    (taken from `werkzeug.utils <http://werkzeug.pocoo.org/docs/utils/>`_)
    z/%z:&%=)urllibparseurlsplitquote
quote_plus
urlunsplit)scharsetschemenetlocpathqsanchorr   r   r   url_fix+   s   r)      c                 C   sL   |d8 }| dk r
d} | dkrd} ddt | |   d|t | |    d S )a:  
    Returns a textual progress bar.
    
    >>> progress_bar(0.6)
    '[##########--------]'
    
    :param progress: Number between 0 and 1 describes the progress.
    :type progress: float
    :param length: The length of the progress bar in chars. Default is 20.
    :type length: int
    :rtype: string
       r   r   [#-])int)progresslengthr   r   r   progress_barC   s   ,r3      c                 C   st   |  dd} t| |d}|sdS ddi}tjj| |d}tjj||d}|  d|jvr/dS t|jd }||kS )	a_  
    Checks if a server allows `Byte serving <https://en.wikipedia.org/wiki/Byte_serving>`_,
    using the Range HTTP request header and the Accept-Ranges and Content-Range HTTP response headers.
    
    :param url: Url address.
    :type url: string
    :param timeout: Timeout in seconds. Default is 15.
    :type timeout: int
    :rtype: bool
     z%20timeoutFRangez	bytes=0-3)headersContent-Length)	replaceget_filesizer   requestRequesturlopencloser9   r0   )urlr7   fullsizer9   requrlObjfilesizer   r   r   is_HTTPRange_supportedW   s   
rF   c                 C   sL   zt jj| |d}t|jd }W |S  tttt jj	t jj
fy%   Y dS w )z
    Fetches file's size of a file over HTTP.
    
    :param url: Url address.
    :type url: string
    :param timeout: Timeout in seconds. Default is 15.
    :type timeout: int
    :returns: Size in bytes.
    :rtype: int
    r6   r:   r   )r   r=   r?   r0   r9   
IndexErrorKeyError	TypeErrorerror	HTTPErrorURLError)rA   r7   rD   	file_sizer   r   r   r<   s   s   r<   c                  C   s   g d} t | S )z
    Returns a random popular user-agent.
    Taken from `here <http://techblog.willshouse.com/2012/01/03/most-common-user-agents/>`_, last updated on 2020/09/19.
    
    :returns: user-agent
    :rtype: string
    )zsMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36zsMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36zrMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36zsMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36zNMozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0zwMozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.2 Safari/605.1.15zNMozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0zxMozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36zyMozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36zyMozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36zLMozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0zRMozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:80.0) Gecko/20100101 Firefox/80.0zrMozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36zMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36 Edg/85.0.564.44zMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36 Edg/85.0.564.51zRMozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:79.0) Gecko/20100101 Firefox/79.0zwMozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Safari/605.1.15zhMozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36zrMozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36zwMozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.2 Safari/605.1.15)randomchoice)lr   r   r   get_random_useragent   s   
rQ   c                 C   s   t tg dg d}| dkr5ttt| dt|d }t| d|  }|| \}}d| }|||S | dkr;dS | dkrAdS d	S )
a2  
    Human-readable formatting for filesizes. Taken from `here <http://stackoverflow.com/questions/1094841/reusable-library-to-get-human-readable-version-of-file-size>`_.
    
    >>> sizeof_human(175799789)
    '167.7 MB'
    
    :param num: Size in bytes.
    :type num: int
    
    :rtype: string
    )BkBMBGBTBPB)r   r   r   r+   r+   r+   r   i   z{:,.%sf} {}r   z0 bytesz1 byteN)listzipminr0   r   r	   floatformat)num	unit_listexponentquotientunitnum_decimalsformat_stringr   r   r   sizeof_human   s   rd   c           	      C   s   t | d d }t | } | dkr|r|dkr|rdS dS g d}|r'g d}ng d}g }tt|d d	d	D ]!}| ||  }|dkrX|||| d|  f | |||  8 } q7|rj|dkrj|||rfd
ndf |rvddd |D S ddd |D S )az  
    Human-readable formatting for timing. Based on code from `here <http://stackoverflow.com/questions/6574329/how-can-i-produce-a-human-readable-difference-when-subtracting-two-unix-timestam>`_.
    
    >>> time_human(175799789)
    '6 years, 2 weeks, 4 days, 17 hours, 16 minutes, 29 seconds'
    >>> time_human(589, fmt_short=True)
    '9m49s'
    
    :param duration: Duration in seconds.
    :type duration: int/float
    :param fmt_short: Format as a short string (`47s` instead of `47 seconds`)
    :type fmt_short: bool
    :param show_ms: Specify milliseconds in the string.
    :type show_ms: bool
    :rtype: string
    r   i  r   0sz	0 seconds)r   <   i  iQ i:	 i $ i )ssmmhhddwwyy))secondseconds)minuteminutes)hourhours)daydays)weekweeks)monthmonths)yearyearsmsmilliseconds c                 S      g | ]}d | qS )z%s%sr   .0xr   r   r   
<listcomp>       ztime_human.<locals>.<listcomp>z, c                 S   r   )z%s %sr   r   r   r   r   r      r   )r0   ranger	   appendjoin)	duration	fmt_shortshow_msr|   	INTERVALSNAMESresultiar   r   r   
time_human   s(   

r   c                 C   s   t | }d}t|d(}||}|r*|| ||}|sW d   | S W d   | S 1 s7w   Y  | S )ah  
    Calculates a file's hash.

    .. WARNING::
        The hashing algorithm must be supported on your system, as documented at `hashlib documentation page <http://docs.python.org/3/library/hashlib.html>`_.
    
    :param algorithm: Hashing algorithm.
    :type algorithm: string
    :param path: The file path
    :type path: string
    :rtype: string
    i   r   N)hashlibnewr   r   update	hexdigest)	algorithmr&   hashAlgblock_szfr   r   r   r   get_file_hash   s   





r   c           	      C   s   | sdgS t | | |k r!|dkr!|d8 }t | | |k r!|dksg }d}t | | }t|D ]}|}|| }|| d krA| d }|||f ||d 7 }q/|S )a+  
    Calculates the byte chunks to download.
    
    :param filesize: filesize in bytes.
    :type filesize: int
    :param threads: Number of trheads
    :type threads: int
    :param minChunkFile: Minimum chunk size
    :type minChunkFile: int
    :rtype: Array of (startByte,endByte) tuples
    )r   r   r   r   )r   r   r   )	rE   threadsminChunkFileargsposchunkr   	startByteendByter   r   r   calc_chunk_size  s    r   c                  C   sP   t d} ts&| t j t  }|t j |t d | | da| S )zg
    Creates a debugging logger that prints to console.
    
    :rtype: `logging.Logger` instance
    	pySmartDLzA[%(levelname)s||%(thread)d@{%(pathname)s:%(lineno)d}] %(message)sT)	logging	getLoggerDEFAULT_LOGGER_CREATEDsetLevelDEBUGStreamHandlersetFormatter	Formatter
addHandler)t_logconsoler   r   r   create_debugging_logger+  s   

r   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	DummyLoggerzk
    A dummy logger. You can call `debug()`, `warning()`, etc on this object, and nothing will happen.
    c                 C      d S Nr   selfr   r   r   __init__C     zDummyLogger.__init__c                 O   r   r   r   )r   r   kargsr   r   r   
dummy_funcF  r   zDummyLogger.dummy_funcc                 C   s   | dr
t|S | jS )N__)
startswithobject__getattr__r   )r   namer   r   r   r   I  s   

zDummyLogger.__getattr__N)__name__
__module____qualname____doc__r   r   r   r   r   r   r   r   ?  s
    r   c                       s@   e Zd ZdZdd Z fddZdd Zdd	 Zd
d Z  Z	S )ManagedThreadPoolExecutorzF
	Managed Thread Pool Executor. A subclass of ThreadPoolExecutor.
    c                 C   s   t j| | g | _d S r   )r   ThreadPoolExecutorr   _futures)r   max_workersr   r   r   r   R  s   
z"ManagedThreadPoolExecutor.__init__c                    s*   t  j|g|R i |}| j| |S r   )supersubmitr   r   )r   fnr   kwargsfuture	__class__r   r   r   V  s   z ManagedThreadPoolExecutor.submitc                 C   s   t dd | jD S )Nc                 S   s   g | ]}|  qS r   )doner   r   r   r   r   \  r   z2ManagedThreadPoolExecutor.done.<locals>.<listcomp>)allr   r   r   r   r   r   [  s   zManagedThreadPoolExecutor.donec                 C   s*   g }| j D ]}| r||  q|S )zY
        Return all the exceptions raised.

        :rtype: List of `Exception` instances)r   	exceptionr   )r   rP   r   r   r   r   get_exceptions^  s   
z(ManagedThreadPoolExecutor.get_exceptionsc                 C   s$   | j D ]}| r|   S qdS )z
        Returns only the first exception. Returns None if no exception was raised.

        :rtype: `Exception` instance
        N)r   r   )r   r   r   r   r   get_exceptioni  s
   
z'ManagedThreadPoolExecutor.get_exception)
r   r   r   r   r   r   r   r   r   __classcell__r   r   r   r   r   N  s    r   )r   )r   )r*   )r4   )FF)!r   r   sysurllib.requestr   urllib.parseurllib.errorrN   r   rer   
concurrentr   mathr   r   r
   r   r   r)   r3   rF   r<   rQ   rd   r   r   r   r   r   r   r   r   r   r   r   r   <module>   s2   




 
3