B
    f9W                 @   sT   d dl mZ d dlmZmZ d dlT d dlZd dlmZ e	
dZG dd dZdS )	    )HTTPBasicAuth)urlparse	parse_qsl)*N)ApiNotFoundErrorzatlassian.rest_clientc            	   @   s|  e Zd ZdZdZe dZdZdZeeeee	e	dddd	Z
eddejfd
dZddddZdLddZdMddZdd Zdd Zdd Zdd Zdd Zd d! ZdNeeeeed$d%d&ZdOeeed'd(d)ZdPed*d+d,Zed-d. ZdQd/d0Z dRd1d2Z!dSd3d4Z"dTd5d6Z#d7d8 Z$d9d: Z%d;d< Z&d=d> Z'dUeeeed?d@dAZ(dVeeeeeeedDdEdFZ)dWdHdIZ*dJdK Z+dS )XConfluenceApiuK    Подключение по API к учетной записи Confluence z/rest/api/3z/user   z"/wiki/rest/api/user/bulk/migrationN)urllogintokenpasswordcloud
verify_sslreturnc          	   C   s   ddl m} |r|}n|}|ds,|d }|dr:|nd| | _|||||||t d| _dd| i| _|| _	|| _
|| _|| _|| _d S )	Nr   )
Confluence/Zhttpzhttps://)r	   usernamer   r   r   r   ZsessionZAuthorizationzBearer )Z	atlassianr   endswith
startswithr	   cmfutilrequests_sessionconnheadersr
   r   r   r   )selfr	   r
   r   r   r   r   r    r   ./modules/confluence/api.py__init__   s*    
zConfluenceApi.__init__c             C   s^   ddd}|p|}dj | ddd | D |s6dnd t||d	}tj||d
 dS )z

        :param method:
        :param url:
        :param data:
        :param headers:
        :param level:
        :return:
        zapplication/json)zContent-TypeAcceptz5curl --silent -X {method} -H {headers} {data} '{url}'z -H c             S   s   g | ]\}}d  ||qS )z
'{0}: {1}')format).0keyvaluer   r   r   
<listcomp>8   s    z0ConfluenceApi.log_curl_debug.<locals>.<listcomp> z--data '{0}')methodr   datar	   )levelmsgN)r   joinitemsjsondumpsloggerlog)r$   r	   r%   r   r&   Zdefault_headersmessager   r   r   log_curl_debug)   s    
zConfluenceApi.log_curl_debugZGET)r$   c            O   sl   | j |d ||dd | jrJ| jrJt j|| j| jf| jd|S t j|| j| jd|S d S )Nr   params)r	   r$   r%   )authverify)r   r2   )r/   getr
   r   r   r   r   r   )r   r$   argskwargsr   r   r   confluence_request>   s    $z ConfluenceApi.confluence_requestc             c   sx   |r|d }|d |d  }nd}d}xL| j j|||d}|rH|dsJP x|d D ]
}|V  qTW |rhP ||7 }q(W dS )u   
        Получим все пространства из Confluence

        :return: Список всех пространств
        r      d   )
space_typestartlimitresultsN)r   get_all_spacesr3   )r   r9   slicer:   r;   resrowr   r   r   r=   E   s    
zConfluenceApi.get_all_spacesr   r8   c             c   s\   xV|r|| |kr|| }| j j|||||d}|E dH  ||7 }|rN||ksR|sP qW dS )u}   
        Получим все документы из пространства со списком потомков
        )r:   r;   statusexpandN)r   get_all_pages_from_space)r   r    r:   r;   maxrA   rB   r?   r   r   r   rC   ]   s    
z&ConfluenceApi.get_all_pages_from_spacec             C   s   t dd | |dD S )Nc             S   s   g | ]}d qS )r7   r   )r   objr   r   r   r"   m   s    z<ConfluenceApi.get_count_pages_from_space.<locals>.<listcomp>r   )lenrC   )r   r    r   r   r   get_count_pages_from_spacel   s    z(ConfluenceApi.get_count_pages_from_spacec          
   c   s   t ddd}|||< | j}| jjr0tj|d}xy\| jtj|d|d}|  |	 }|
dsjd S |d E d H  |d  |d	 7  < W q2 tjk
r } ztd
| d|  d S d }~X Y q2X q2W d S )Nr      )r:   r;   Zwikizrest/api/user/memberof)r0   r<   r:   r;   uL   Не удалось получить группы пользователя "z". )dictr	   r   r   ospathr(   r6   raise_for_statusr*   r3   requestsZ	HTTPErrorr,   warning)r   r    r!   r0   r	   r?   Zhttp_errr   r   r   user_member_ofo   s"    
zConfluenceApi.user_member_ofc          
   C   s   t j| jd|}| jjr,t j| jd|}y| |}|  | }W n> t	k
r } z t
d| d|  t }W d d }~X Y nX |S )Nzrest/mobile/1.0/profile/zwiki/rest/mobile/1.0/profile/uL   Не удалось получить данные пользователя "z". )rJ   rK   r(   r	   r   r   r6   rL   r*   	Exceptionr,   rN   rI   )r   r   r	   r?   infoerrorr   r   r   get_user_detail   s    
zConfluenceApi.get_user_detailc             #   s  | j jrtddddd}x| jtj| jd|d }|d sDd S xh|d D ]\}|d	  | j	 d
 d} 
 fdd| D  dd | d
 d
 D  d<  V  qNW |d  |d 7  < qW ntddddd}x| j jf |}|d sd S x|d D ]~}|d	 d dkr td q|d	  | j	|d	 d d} 
 fdd| D  dd | d d D  d<  V  qW |d  |d 7  < qW d S )Nr   rH   zuser=""zoperations,personalSpace)r:   r;   cqlrB   zwiki/rest/api/search/user)r0   r<   user	accountId)r   c             3   s*   | ]"\}}| ks|d kr||fV  qdS )r#   Nr   )r   kv)rU   r   r   	<genexpr>   s    z.ConfluenceApi.get_all_users.<locals>.<genexpr>c             S   s   g | ]}|qS r   r   )r   gr   r   r   r"      s    z/ConfluenceApi.get_all_users.<locals>.<listcomp>groupsr:   r;   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 )r#   Nr   )r   rW   rX   )rU   r   r   rY      s    c             S   s   g | ]}|qS r   r   )r   rZ   r   r   r   r"      s    )r   r   rI   r6   rJ   rK   r(   r	   r*   rS   updater)   rO   rT   r,   rN   )r   r0   r?   r@   Z	user_infor   )rU   r   get_all_users   s8    


zConfluenceApi.get_all_usersc             c   sJ   t ddd}x8| jjf |}|s$d S |E d H  |d  |d 7  < qW d S )Nr   rH   )r:   r;   r:   r;   )rI   r   get_all_groups)r   r0   r?   r   r   r   r^      s    
zConfluenceApi.get_all_groupsc             c   sX   t dd|dd}xB| jjf |}|s(d S x|D ]
}|V  q.W |d  |d 7  < qW d S )Nr   rH   zoperations,status)r:   r;   
group_namerB   r:   r;   )rI   r   get_group_members)r   r_   r0   r?   r@   r   r   r   r`      s    

zConfluenceApi.get_group_membersrH   T)
content_idr:   r;   rB   r   c             c   sH  | j jr"tj| jd| d}ntj| jd| d}i }|dk	rRt||d< |dk	rft||d< |dk	rv||d< |sd|d	< x| j||d
 }x<|d D ]0}	|rdd | j	|	d ||dD |	d< |	V  qW |d }
|

d}|sP t|}tt|j}|d |d< |
dr(|
d|d< |
dr|
d|d< qW dS )u  
        Получает все комментарии к документу

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

        Yields:
            Iterator[list]: элемент
        zwiki/rest/api/content/z/child/commentzrest/api/content/Nr:   r;   rB   alldepth)r0   r<   c             S   s   g | ]}|qS r   r   )r   rE   r   r   r   r"      s    z3ConfluenceApi.get_page_comments.<locals>.<listcomp>id)rB   childrenre   _linksnextcursor)r   r   rJ   rK   r(   r	   intr6   r*   get_page_commentsr3   r   rI   r   query)r   ra   r:   r;   rB   re   r	   r0   r?   resultlinksnext_
next_parserk   r   r   r   rj      s>    


zConfluenceApi.get_page_comments)	key_spacerB   r   c             c   s   d}d}x| j j|d|||dd}xd|d D ]X}|dr~dd	 | |d
 D |d d d< t|d d d |d d d< |V  q,W |d sP ||7 }q
W dS )ui  
        Получим все документы из корня пространства.

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

        :return: Соответствие id документа и его данных.
        r   2   rootpage)rc   rB   r:   r;   Zcontent_typer<   re   c             S   s   g | ]}|qS r   r   )r   rE   r   r   r   r"     s    z;ConfluenceApi.get_root_pages_from_space.<locals>.<listcomp>rd   sizeN)r   Zget_space_contentr3   get_childrenrF   )r   rp   rB   r:   r;   r?   r@   r   r   r   get_root_pages_from_space   s    	
$ 
z'ConfluenceApi.get_root_pages_from_space)rB   c             c   s   t |||d}xz| jjr:| j| j d| d|d }n| jj|f|}|rX|dsZP x|d D ]
}|V  qdW |d  |d 7  < qW d S )N)r:   r;   rB   z/wiki/rest/api/content/z/child/attachment)r0   r<   r:   r;   )rI   r   r   r6   r	   r*   Zget_attachments_from_contentr3   )r   page_idr:   r;   rB   r0   r?   r@   r   r   r   get_all_attachment  s    
z ConfluenceApi.get_all_attachmentc       	      C   sN   t ||}ddi}x6t| jD ](}t j||||dd}|jdkrP qW |S )Nr   zapplication/json
   )r1   r0   r   Ztimeout   )r   rangeRETRY_COUNTr   r   r3   Zstatus_code)	clsr
   r   r	   r0   r1   r   ir?   r   r   r   call$  s    

zConfluenceApi.callc             C   s*   y| j j||dS  tk
r$   d S X d S )N)userkeyrB   )r   Zget_user_details_by_userkeyr   )r   r   rB   r   r   r   get_user_info_by_key1  s    z"ConfluenceApi.get_user_info_by_keyc             C   s   | j jr| j j||dS d S )N)rB   )r   r   get_user_details_by_accountid)r   rV   rB   r   r   r   get_user_info7  s    zConfluenceApi.get_user_infoc             C   sR   y8| j jr*| j|d}| j j|d |dS | j j||dS  tk
rL   d S X d S )N)r   rV   )Z	accountidrB   )r   rB   )r   r   get_account_idr   Zget_user_details_by_usernamer   )r   r   rB   rU   r   r   r   get_user_info_by_username;  s    z'ConfluenceApi.get_user_info_by_usernamec             C   s>   |rd|i}nd|i}|  | j | j |}| d d S )Nr   r   r<   r   )r6   r	   USER_ACCOUNTS_ID_URIr*   )r   r   r   r0   r?   r   r   r   r   D  s    
zConfluenceApi.get_account_idc             O   s`   | j j|f||}d|ddkr\dd | |D }||d d d< t||d d d	< |S )
Nzchildren.pagerB   r#   c             S   s   g | ]}|qS r   r   )r   rE   r   r   r   r"   W  s    z0ConfluenceApi.get_page_by_id.<locals>.<listcomp>re   rs   r<   rt   )r   get_page_by_idr3   ru   rF   )r   rd   r4   r5   rs   re   r   r   r   r   O  s    zConfluenceApi.get_page_by_idc             c   s<   d}d}x.| j j|||d}|s"P |E d H  ||7 }q
W d S )Nr   rq   )r:   r;   )r   Zget_page_child_by_type)r   Z	parent_idr:   r;   r?   r   r   r   ru   \  s    
zConfluenceApi.get_childrenc             c   s   t ddd}| jjrpx| j| j d| d|d }|d E d H  |d  |d	 7  < |d
 |d k rP qW n<t| jtj	| jd| d|d 
 d d E d H  d S )Nr   r8   )r:   r;   zwiki/rest/api/content/z/restriction)r0   r<   r:   r;   rt   zrest/api/content/z/restriction/byOperation)rI   r   r   r6   r	   r*   listrJ   rK   r(   values)r   rw   r0   r?   r   r   r    get_all_restrictions_for_contentf  s    z.ConfluenceApi.get_all_restrictions_for_contentc             c   sZ   t dd|d}xF| jjf |}|d E d H  |d  |d 7  < |d |d k rP qW d S )Nr   r8   )r:   r;   rw   r<   r:   r;   rt   )rI   r   Zget_page_labels)r   rw   r0   r?   r   r   r   get_all_page_labelsv  s    z!ConfluenceApi.get_all_page_labels)ra   version_numberrB   r   c             C   sN   | j jrd| d| }nd| d| }i }|dk	r>||d< | j j||dS )u  
        Получает определенную версию документа

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

        Return:
            dict: данные версии документа
        zrest/api/content/z	/version/zrest/experimental/content/NrB   )r0   )r   r   r3   )r   ra   r   rB   r	   r0   r   r   r   get_page_version  s    zConfluenceApi.get_page_version   r   )ra   current_versionr:   r;   last_versionsrB   r   c             c   s  |sdS | j jrd| d}nd| d}i }|dk	rBt||d< |dk	rVt||d< |dk	rf||d< d}	xnyp| j j||d	}
|
d
 }|d}xH|
d D ]<}|	d7 }	d|  kr|	k rn nd}P |d d }|V  qW W n   xt|ddD ]z}|	d7 }	d|  kr|	k rn nP y| |||V  W q tk
rl } ztd| d| V  W dd}~X Y qX qW d}Y nX |sP t|}tt	|j
}|d |d< |dr|d|d< |drn|d|d< qnW d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]: элемент
        Nzrest/api/content/z/versionzrest/experimental/content/r:   r;   rB   r   )r0   rf   rg   r<   r7   FZnumberr   u   версия z. rh   )r   r   ri   r3   r{   r   rP   r   rI   r   rk   )r   ra   r   r:   r;   r   rB   r	   r0   Zversion_countr?   rm   rn   versionr   excro   rk   r   r   r   get_page_versions  sX    
,

zConfluenceApi.get_page_versionsrq   c             c   s  | j jrtj| jd}ntj| jd}i }|d k	r>||d< |d k	rRt||d< |d k	rft||d< |d k	rv||d< x| j||d }x|d D ]
}|V  qW |d	 }	|		d
}
|
sP t
|
}tt|j}|d |d< |	dr|	d|d< |	d
rx|	d
|d
< qxW d S )Nzwiki/rest/api/content/searchzrest/api/content/searchrT   r:   r;   rB   )r0   r<   rf   rg   rh   )r   r   rJ   rK   r(   r	   ri   r6   r*   r3   r   rI   r   rk   )r   rT   r:   r;   rB   r	   r0   r?   Zcontentrm   rn   ro   rk   r   r   r   content_cql  s6    



zConfluenceApi.content_cqlc             C   sP   | j jr$| j j|dd}|dg S d}ddd|gd}| j j||dd	g S )
NZpermissions)	space_keyrB   z!rpc/json-rpc/confluenceservice-v2z2.0ZgetSpacePermissionSets   )Zjsonrpcr$   rd   r0   )r%   rl   )r   r   Z	get_spacer3   Zpost)r   r   Z
space_datar	   r%   r   r   r   get_space_permissions  s    
z#ConfluenceApi.get_space_permissions)NN)r   r8   NNN)r   rH   NT)N)r   rH   N)N)N)N)NN)N)r   r   r   N)r   rq   N),__name__
__module____qualname____doc__ZAPI_VERSIONZUSER_URIr|   r   strboolr   staticmethodloggingDEBUGr/   r6   r=   rC   rG   rO   rS   r]   r^   r`   ri   r   rj   rI   rv   rx   classmethodr   r   r   r   r   r   ru   r   r   r   r   r   r   r   r   r   r   r   	   sL   


#	 4


	


   K
%r   )Zrequests.authr   Zurllib.parser   r   Zcmf.includerM   Zatlassian.errorsr   r   Z	getLoggerr,   r   r   r   r   r   <module>   s   
