U
    dhdR                     @   sv   d dl mZmZ d dlT d dl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 edZG d	d
 d
eZdS )    )urlparse	parse_qsl)*N)HTTPAdapter)Retry)
Confluence)ApiNotFoundErrorzatlassian.rest_clientc                	       s  e Zd ZdZddejde ddf fdd	Zdd Z	d	d
 Z
dd Zdd Z fddZdMddZdN fdd	ZdOddZdd Zdd Zd d! Z fd"d#Z fd$d%ZdPeeeeed'd(d)ZdQeeed*d+d,ZdRed-d.d/ZdSd0d1ZdTd2d3ZdUd4d5ZdVd6d7Z  fd8d9Z!d:d; Z" fd<d=Z#d>d? Z$dWeeeed@dAdBZ%dXeeeeeeedEdFdGZ&dHdI Z'edJdKdLZ(  Z)S )YConfluenceApiuK    Подключение по API к учетной записи Confluence NTFc	           
   
      s   | dr|nd| }|ds*|d7 }|r4|}nd }t j|f|||||||d|	 |   tjj| _dt|j	 | _
d | _|   d S )Nhttphttps:///)usernamepasswordtimeout
verify_sslsessioncloudtokenzCONFLUENCE:COOKIE:)
startswithendswithsuper__init___set_session_retriesZAPPZREDIS_DBredisr   netloc	redis_keycookies_dict_init_cookies)
selfurlr   r   r   r   r   r   r   kwargs	__class__ ./modules/confluence/api.pyr      s0    
	
zConfluenceApi.__init__c                 C   s>   t tjtjdd}| jdt|d | jdt|d dS )u   
        Конфигурирует стратегию повторных попыток
        и ассоциирует ее с сессией
           )totalZstatus_forcelistZbackoff_factorzhttp://)Zmax_retriesr   N)r   configZIMPORT_REQUEST_RETRY_TOTALZ!IMPORT_REQUEST_RETRY_STATUS_CODES_sessionZmountr   )r   Zretriesr#   r#   r$   r   9   s    z"ConfluenceApi._set_session_retriesc                 C   sX   | j | j}|rTz*t|}| jj| | jj | _	W n tj
k
rR   Y nX dS )u  
        Добавляет cookie в сессию при инициализации,
        что бы не выполнять повторную авторизацию, если cookie еще действуют.
        При недействительных cookie, выполнится авторизация,
        а cookie обновятся в сессии и кеше
        N)r   getr   pickleloadsr(   cookiesupdateget_dictr   ZPickleError)r   cookies_pickler,   r#   r#   r$   r   F   s    
zConfluenceApi._init_cookiesc                 C   s&   t | jj}| jj| j|dd dS )u   
        Сохраняет cookie в кеш (Redis) для последующего использования
        без выполнения повторной авторизации
        i`T  )exN)r*   dumpsr(   r,   r   setr   )r   r/   r#   r#   r$   _save_cookiesV   s    zConfluenceApi._save_cookiesc                 C   s(   | j j }| j|kr$|| _|   dS )u   
        Проверяет изменение cookie и обновляет их в кеше при необходимости
        N)r(   r,   r.   r   r3   )r   Zcurrent_cookies_dictr#   r#   r$   _check_cookies^   s    
zConfluenceApi._check_cookiesc                    s   t  j||}|   |S )N)r   requestr4   )r   argsr    Zresponser!   r#   r$   r5   g   s    zConfluenceApi.request   c           	   
   C   s   | j }|p| j}| jd||d | jj|d||| j| jd`}td| d|j	 d|j
  |  t|d"}|j|d	D ]}|| q~W 5 Q R X W 5 Q R X d
S )us  
        Скачивает файл

        Args:
            download_url (_type_): url файла для скачивания
            save_path (_type_): путь для сохранения файла
            timeout (_type_, optional): Таймаут. Defaults to None.
            chunk_size (_type_, optional): _description_. Defaults to 64*1024.
        ZGET)methodr   headersT)streamr9   r   Zverifyproxiesz
HTTP: GET z ->  zwb+)
chunk_sizeN)Zno_check_headersr   Zlog_curl_debugr(   r)   r   r;   loggerdebugZstatus_codereasonZraise_for_statusopenZiter_contentwrite)	r   Zdownload_urlZ	save_pathr   r=   r9   resfchunkr#   r#   r$   download_filel   s"    

 zConfluenceApi.download_filec                 #   sp   |r|d }|d |d  }nd}d}t  j|||d}|rl|dsHql|d D ]
}|V  qP|rbql||7 }q&dS )u   
        Получим все пространства из Confluence

        :return: Список всех пространств
        r   r%   d   )
space_typestartlimitresultsN)r   get_all_spacesr)   )r   rH   slicerI   rJ   rC   rowr!   r#   r$   rL      s    zConfluenceApi.get_all_spacesr   rG   archivedpagec                 c   s2   | j |||||d}|sq.|E dH  ||7 }q dS )ud   
        Получает архивные документы из пространства
        )content_typeN)Zget_all_pages_from_space)r   spacerI   rJ   statusrQ   rC   r#   r#   r$    get_all_pages_from_space_archive   s
    
z.ConfluenceApi.get_all_pages_from_space_archivec              
   c   s   t ddd}|||< d}zD| j||d}|ds8W d S |d E d H  |d  |d 7  < W q tjk
r } z td	| d
|  W Y d S d }~X Y qX qd S )Nr      rI   rJ   zrest/api/user/memberofparamsrK   rI   rJ   uL   Не удалось получить группы пользователя "". )dictr)   requestsZ	HTTPErrorr>   warning)r   keyvaluerX   r   rC   Zhttp_errr#   r#   r$   user_member_of   s    
zConfluenceApi.user_member_ofc              
   C   sR   z|  |}W n> tk
rL } z td| d|  t }W 5 d }~X Y nX |S )NuL   Не удалось получить данные пользователя "rY   )Zget_mobile_parameters	Exceptionr>   r\   rZ   )r   r   infoerrorr#   r#   r$   get_user_detail   s    zConfluenceApi.get_user_detailc                 #   sv  | j rtddddd}| jd|d}|d s0d S |d D ]\}|d	  | j d
 d}  fdd| D  dd | d
 d
 D  d<  V  q8|d  |d 7  < qntddddd}| jf |}|d sd S |d D ]|}|d	 d dkrt	d q|d	  | j|d	 d d}  fdd| D  dd | d d D  d<  V  q|d  |d 7  < qd S )Nr   rU   zuser=""zoperations,personalSpace)rI   rJ   cqlexpandzrest/api/search/userrW   rK   user	accountIdr   c                 3   s*   | ]"\}}| ks|d kr||fV  qdS  Nr#   .0kvrf   r#   r$   	<genexpr>   s     z.ConfluenceApi.get_all_users.<locals>.<genexpr>c                 S   s   g | ]}|qS r#   r#   rl   gr#   r#   r$   
<listcomp>   s     z/ConfluenceApi.get_all_users.<locals>.<listcomp>groupsrI   rJ   z	type=userz&user.operations,user.status,user.emailr   Zrecovery_adminu   В вашем Confluence включен режим восстановления! Не оставляйте Confluence в режиме восстановления и не используйте учетную запись recovery_admin!c                 3   s*   | ]"\}}| ks|d kr||fV  qdS ri   r#   rk   ro   r#   r$   rp      s     c                 S   s   g | ]}|qS r#   r#   rq   r#   r#   r$   rs      s     )
r   rZ   r)   rc   r-   itemsr_   rd   r>   r\   )r   rX   rC   rN   Z	user_infor#   ro   r$   get_all_users   s4    
zConfluenceApi.get_all_usersc                 #   sF   t ddd}t jf |}|s"d S |E d H  |d  |d 7  < qd S )Nr   rU   rV   rI   rJ   )rZ   r   get_all_groups)r   rX   rC   r!   r#   r$   rw      s    
zConfluenceApi.get_all_groupsc                 #   sP   t dd|dd}t jf |}|s&d S |D ]
}|V  q*|d  |d 7  < qd S )Nr   rU   zoperations,status)rI   rJ   
group_namere   rI   rJ   )rZ   r   get_group_members)r   rx   rX   rC   rN   r!   r#   r$   ry      s    zConfluenceApi.get_group_membersrU   )
content_idrI   rJ   re   returnc                 c   s  d| d}i }|dk	r$t ||d< |dk	r8t ||d< |dk	rH||d< |sTd|d< | j||d	}|d
 D ]0}	|rdd | j|	d ||dD |	d< |	V  qj|d }
|
d}|sq
t|}tt|j}|d |d< |dr|d|d< |drT|d|d< qTdS )u  
        Получает все комментарии к документу

        Args:
            content_id (str): ID страницы(документа) в Confluence
            expand (str): Cвойства элемента, которые нужно расширить, например, expand='body,version,history'
            children (bool): Создать иерархическую структуру с дочерними элементами

        Yields:
            Iterator[list]: элемент
        rest/api/content/z/child/commentNrI   rJ   re   alldepthrW   rK   c                 S   s   g | ]}|qS r#   r#   rl   objr#   r#   r$   rs     s     z3ConfluenceApi.get_page_comments.<locals>.<listcomp>id)re   childrenr   _linksnextcursor)intr)   get_page_commentsr   rZ   r   query)r   rz   rI   rJ   re   r   r   rX   rC   resultlinksnext_
next_parser   r#   r#   r$   r      s:    


zConfluenceApi.get_page_comments)	key_spacere   r{   c                 c   s   d}d}| j |d|||dd}|d D ]X}|drxdd	 | |d
 D |d d d< t|d d d |d d d< |V  q&|d sq||7 }qdS )ui  
        Получим все документы из корня пространства.

        :param key_space: Идентификатор пространства.
        :param expand: Дополнительные данные по документам.

        :return: Соответствие id документа и его данных.
        r   2   rootrP   )r~   re   rI   rJ   rQ   rK   r   c                 S   s   g | ]}|qS r#   r#   r   r#   r#   r$   rs   <  s     z;ConfluenceApi.get_root_pages_from_space.<locals>.<listcomp>r   sizeN)Zget_space_contentr)   get_childrenlen)r   r   re   rI   rJ   rC   rN   r#   r#   r$   get_root_pages_from_space,  s    	
$ z'ConfluenceApi.get_root_pages_from_spacere   c                 c   sZ   t |||d}| j|f|}|rV|ds,qV|d D ]
}|V  q4|d  |d 7  < qd S )N)rI   rJ   re   rK   rI   rJ   )rZ   Zget_attachments_from_contentr)   )r   page_idrI   rJ   re   rX   rC   rN   r#   r#   r$   get_all_attachmentC  s    z ConfluenceApi.get_all_attachmentc                 C   s,   z| j ||dW S  tk
r&   Y d S X d S )N)userkeyre   )Zget_user_details_by_userkeyr   )r   r   re   r#   r#   r$   get_user_info_by_keyN  s    z"ConfluenceApi.get_user_info_by_keyc                 C   s   | j r| j||dS d S )Nr   )r   get_user_details_by_accountid)r   rg   re   r#   r#   r$   get_user_infoT  s    zConfluenceApi.get_user_infoc                 C   sR   z6| j r(| j|d}| j|d |dW S | j||dW S  tk
rL   Y d S X d S )Nrh   rg   )Z	accountidre   )r   re   )r   get_account_idr   Zget_user_details_by_usernamer   )r   r   re   rf   r#   r#   r$   get_user_info_by_usernameX  s    z'ConfluenceApi.get_user_info_by_usernamec                 C   s4   d}|rd|i}nd|i}| j ||d}|d d S )Nzrest/api/user/bulk/migrationr   r   rW   rK   r   r)   )r   r   r   r   rX   rC   r#   r#   r$   r   a  s    
zConfluenceApi.get_account_idc                    s`   t  j|f||}d|ddkr\dd | |D }||d d d< t||d d d	< |S )
Nzchildren.pagere   rj   c                 S   s   g | ]}|qS r#   r#   r   r#   r#   r$   rs   s  s     z0ConfluenceApi.get_page_by_id.<locals>.<listcomp>r   rP   rK   r   )r   get_page_by_idr)   r   r   )r   r   r6   r    rP   r   r!   r#   r$   r   k  s    zConfluenceApi.get_page_by_idc                 c   s6   d}d}| j |||d}|sq2|E d H  ||7 }qd S )Nr   rU   rV   )Zget_page_child_by_type)r   Z	parent_idrI   rJ   rC   r#   r#   r$   r   x  s    
zConfluenceApi.get_childrenc                 #   s&   t t | d d E d H  d S )N)listr    get_all_restrictions_for_contentvalues)r   r   r!   r#   r$   r     s    z.ConfluenceApi.get_all_restrictions_for_contentc                 c   sT   t dd|d}| jf |}|d E d H  |d  |d 7  < |d |d k rqPqd S )Nr   rG   )rI   rJ   r   rK   rI   rJ   r   )rZ   Zget_page_labels)r   r   rX   rC   r#   r#   r$   get_all_page_labels  s    z!ConfluenceApi.get_all_page_labels)rz   version_numberre   r{   c                 C   sJ   | j rd| d| }nd| d| }i }|dk	r<||d< | j||dS )u  
        Получает определенную версию документа

        Args:
            content_id (str): ID страницы(документа) в Confluence
            version_number (int): номер версии страницы(документа)
            expand (str): Cвойства элемента, которые нужно расширить, например, expand='body,version,history'

        Return:
            dict: данные версии документа
        r|   z	/version/rest/experimental/content/Nre   rW   )r   r)   )r   rz   r   re   r   rX   r#   r#   r$   get_page_version  s    zConfluenceApi.get_page_version   r   )rz   current_versionrI   rJ   last_versionsre   r{   c                 c   s  |sdS | j rd| d}nd| d}i }|dk	r@t||d< |dk	rTt||d< |dk	rd||d< d}	zl| j||d	}
|
d
 }|d}|
d D ]>}|	d7 }	d|  kr|	k rn nd} q|d d }|V  qW n   t|ddD ]~}|	d7 }	d|  kr|	k rn n qhz| |||V  W q tk
rd } ztd| d| V  W 5 d}~X Y qX qd}Y nX |s|qt|}tt|j	}|d |d< |dr|d|d< |drh|d|d< qhdS )u  
        Получает версии страницы (историю документа)
        При большом количестве данных в версиях, limit > 5 может не работать,
        зависает, либо падает с ошибкой по таймауту.
        Получение версий списком может упасть с ошибкой 500 "Internal Server Error", если в ответе будет кривая версия.
        При получении ошибки при запросе списков, пытаемся получить версии по одной.

        Args:
            content_id (str): ID страницы(документа) в Confluence
            current_version (int): номер текущй версии страницы(документа)
            last_versions (int): колчество послених версий для получения, при "-1" - получение всех версий
            expand (str): Cвойства элемента, которые нужно расширить, например, expand='body,version,history'

        Yields:
            Iterator[list]: элемент
        Nr|   z/versionr   rI   rJ   re   r   rW   r   r   rK   r%   Fnumberr   u   версия z. r   )
r   r   r)   ranger   r`   r   rZ   r   r   )r   rz   r   rI   rJ   r   re   r   rX   Zversion_countrC   r   r   versionr   excr   r   r#   r#   r$   get_page_versions  sV    
*

zConfluenceApi.get_page_versionsc                 C   sJ   | j r | j|dd}|dg S d}ddd|gd}| j||dd	g S )
NZpermissions)	space_keyre   z!rpc/json-rpc/confluenceservice-v2z2.0ZgetSpacePermissionSets   )Zjsonrpcr8   r   rX   )datar   )r   Z	get_spacer)   Zpost)r   r   Z
space_datar   r   r#   r#   r$   get_space_permissions  s    z#ConfluenceApi.get_space_permissions)r{   c                 C   s   d}|  |S )u   
        Получает связи с другими системами

        Return:
            applinks (dict): данные связей с другими системами
        zrest/applinks/3.0/applinksr   )r   r   r#   r#   r$   get_applinks  s    zConfluenceApi.get_applinks)Nr7   )NN)r   rG   rO   rP   )r   rU   NT)N)r   rU   N)N)N)N)NN)N)r   r   r   N)*__name__
__module____qualname____doc__r'   Z!IMPORT_CONFLUENCE_REQUEST_TIMEOUTZcmfutilZrequests_sessionr   r   r   r3   r4   r5   rF   rL   rT   r_   rc   rv   rw   ry   strr   r   r   rZ   r   r   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__r#   r#   r!   r$   r	      st   )	

	#	        1


	



    Sr	   )urllib.parser   r   Zcmf.includer*   r[   Zrequests.adaptersr   Zurllib3.util.retryr   Z	atlassianr   Zatlassian.errorsr   ZloggingZ	getLoggerr>   r	   r#   r#   r#   r$   <module>   s   
