U
    \,hR                     @   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| }|r"|}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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      s,    	
zConfluenceApi.__init__c              	   C   sH   t ddddddddgd	d
}| jdt|d | jdt|d dS )u   
        Конфигурирует стратегию повторных попыток
        и ассоциирует ее с сессией
           i  i  i  i  i  i  i     )totalZstatus_forcelistZbackoff_factorzhttp://)Zmax_retriesr   N)r   _sessionZmountr   )r   Zretriesr!   r!   r"   r   7   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   D   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_cookiesT   s    zConfluenceApi._save_cookiesc                 C   s(   | j j }| j|kr$|| _|   dS )u   
        Проверяет изменение cookie и обновляет их в кеше при необходимости
        N)r&   r*   r,   r   r1   )r   Zcurrent_cookies_dictr!   r!   r"   _check_cookies\   s    
zConfluenceApi._check_cookiesc                    s   t  j||}|   |S )N)r   requestr2   )r   argsr   Zresponser   r!   r"   r3   e   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 )ur  
        Скачивает файл

        Args:
            download_url (_type_): url файла для скачивания
            save_path (_type_): путь для сохранения файла
            timeout (_type_, optional): Таймаут. Defaults to None.
            chunk_size (_type_, optional): _description_. Defaults to 8*1024.
        ZGET)methodr   headersT)streamr7   r   Zverifyproxiesz
HTTP: GET z ->  zwb+)
chunk_sizeN)Zno_check_headersr   Zlog_curl_debugr&   r'   r   r9   loggerdebugZstatus_codereasonZraise_for_statusopenZiter_contentwrite)	r   Zdownload_urlZ	save_pathr   r;   r7   resfchunkr!   r!   r"   download_filej   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   rF   slicerG   rH   rA   rowr   r!   r"   rJ      s    zConfluenceApi.get_all_spacesr   rE   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   spacerG   rH   statusrO   rA   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      rG   rH   zrest/api/user/memberofparamsrI   rG   rH   uL   Не удалось получить группы пользователя "". )dictr'   requestsZ	HTTPErrorr<   warning)r   keyvaluerV   r   rA   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   Не удалось получить данные пользователя "rW   )Zget_mobile_parameters	Exceptionr<   rZ   rX   )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   rS   zuser=""zoperations,personalSpace)rG   rH   cqlexpandzrest/api/search/userrU   rI   user	accountIdr   c                 3   s*   | ]"\}}| ks|d kr||fV  qdS  Nr!   .0kvrd   r!   r"   	<genexpr>   s     z.ConfluenceApi.get_all_users.<locals>.<genexpr>c                 S   s   g | ]}|qS r!   r!   rj   gr!   r!   r"   
<listcomp>   s     z/ConfluenceApi.get_all_users.<locals>.<listcomp>groupsrG   rH   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 rg   r!   ri   rm   r!   r"   rn      s     c                 S   s   g | ]}|qS r!   r!   ro   r!   r!   r"   rq      s     )
r   rX   r'   ra   r+   itemsr]   rb   r<   rZ   )r   rV   rA   rL   Z	user_infor!   rm   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   rS   rT   rG   rH   )rX   r   get_all_groups)r   rV   rA   r   r!   r"   ru      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   rS   zoperations,status)rG   rH   
group_namerc   rG   rH   )rX   r   get_group_members)r   rv   rV   rA   rL   r   r!   r"   rw      s    zConfluenceApi.get_group_membersrS   )
content_idrG   rH   rc   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/commentNrG   rH   rc   alldepthrU   rI   c                 S   s   g | ]}|qS r!   r!   rj   objr!   r!   r"   rq     s     z3ConfluenceApi.get_page_comments.<locals>.<listcomp>id)rc   childrenr   _linksnextcursor)intr'   get_page_commentsr   rX   r   query)r   rx   rG   rH   rc   r   r   rV   rA   resultlinksnext_
next_parser   r!   r!   r"   r      s:    


zConfluenceApi.get_page_comments)	key_spacerc   ry   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   rootrN   )r|   rc   rG   rH   rO   rI   r   c                 S   s   g | ]}|qS r!   r!   r}   r!   r!   r"   rq   :  s     z;ConfluenceApi.get_root_pages_from_space.<locals>.<listcomp>r   sizeN)Zget_space_contentr'   get_childrenlen)r   r   rc   rG   rH   rA   rL   r!   r!   r"   get_root_pages_from_space*  s    	
$ z'ConfluenceApi.get_root_pages_from_spacerc   c                 c   sZ   t |||d}| j|f|}|rV|ds,qV|d D ]
}|V  q4|d  |d 7  < qd S )N)rG   rH   rc   rI   rG   rH   )rX   Zget_attachments_from_contentr'   )r   page_idrG   rH   rc   rV   rA   rL   r!   r!   r"   get_all_attachmentA  s    z ConfluenceApi.get_all_attachmentc                 C   s,   z| j ||dW S  tk
r&   Y d S X d S )N)userkeyrc   )Zget_user_details_by_userkeyr   )r   r   rc   r!   r!   r"   get_user_info_by_keyL  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   re   rc   r!   r!   r"   get_user_infoR  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 )Nrf   re   )Z	accountidrc   )r   rc   )r   get_account_idr   Zget_user_details_by_usernamer   )r   r   rc   rd   r!   r!   r"   get_user_info_by_usernameV  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   rU   rI   r   r'   )r   r   r   r   rV   rA   r!   r!   r"   r   _  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.pagerc   rh   c                 S   s   g | ]}|qS r!   r!   r}   r!   r!   r"   rq   q  s     z0ConfluenceApi.get_page_by_id.<locals>.<listcomp>r   rN   rI   r   )r   get_page_by_idr'   r   r   )r   r   r4   r   rN   r   r   r!   r"   r   i  s    zConfluenceApi.get_page_by_idc                 c   s6   d}d}| j |||d}|sq2|E d H  ||7 }qd S )Nr   rS   rT   )Zget_page_child_by_type)r   Z	parent_idrG   rH   rA   r!   r!   r"   r   v  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   rE   )rG   rH   r   rI   rG   rH   r   )rX   Zget_page_labels)r   r   rV   rA   r!   r!   r"   get_all_page_labels  s    z!ConfluenceApi.get_all_page_labels)rx   version_numberrc   ry   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: данные версии документа
        rz   z	/version/rest/experimental/content/Nrc   rU   )r   r'   )r   rx   r   rc   r   rV   r!   r!   r"   get_page_version  s    zConfluenceApi.get_page_versionr#   r   )rx   current_versionrG   rH   last_versionsrc   ry   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]: элемент
        Nrz   z/versionr   rG   rH   rc   r   rU   r   r   rI   r$   Fnumberr   u   версия z. r   )
r   r   r'   ranger   r^   r   rX   r   r   )r   rx   r   rG   rH   r   rc   r   rV   Zversion_countrA   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_keyrc   z!rpc/json-rpc/confluenceservice-v2z2.0ZgetSpacePermissionSets   )Zjsonrpcr6   r   rV   )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)ry   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)Nr5   )NN)r   rE   rM   rN   )r   rS   NT)N)r   rS   N)N)N)N)NN)N)r   r#   r   N)*__name__
__module____qualname____doc__ZconfigZ!IMPORT_CONFLUENCE_REQUEST_TIMEOUTZcmfutilZrequests_sessionr   r   r   r1   r2   r3   rD   rJ   rR   r]   ra   rt   ru   rw   strr   r   r   rX   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(   rY   Zrequests.adaptersr   Zurllib3.util.retryr   Z	atlassianr   Zatlassian.errorsr   ZloggingZ	getLoggerr<   r	   r!   r!   r!   r"   <module>   s   
