
    fi\                         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
e          ZdS )    )urlparse	parse_qsl)*N)HTTPAdapter)Retry)
Confluence)ApiNotFoundErrorzatlassian.rest_clientc                       e Zd ZdZddej        de                                ddf fd	Zd Z	d Z
d Zd	 Z fd
Zd6dZd7 fd	Zd8dZd Zd Zd Z fdZ fdZ	 	 d9dededededef
dZd:dededefd Zd;defd!Zd:d"Zd:d#Zd:d$Zd7d%Z ddd& fd'
Z!d<d(ed)e"fd*Z# fd+Z$d, Z%d:ded-ededefd.Z&	 	 	 	 d=ded1ededed2ededefd3Z'd4 Z(defd5Z) xZ*S )>ConfluenceApiuK    Подключение по API к учетной записи Confluence NTFc	                    |                     d          r|nd| }|                    d          s|dz  }|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endswithsuper__init___set_session_retriesAPPREDIS_DBredisr   netloc	redis_keycookies_dict_init_cookies)selfurlr   r   r   r   r   r   r   kwargs	__class__s             ./modules/confluence/api.pyr   zConfluenceApi.__init__   s     ^^F++Acc1AC1A1A||C   	3JC 	HHE
	
!
	
 
	
 
	
 
	
 
	
 	!!###\'
Dhsmm.BDD     c                     t          t          j        t          j        t          j        d          }t	          |          }| j                            d|           | j                            d|           dS )u   
        Конфигурирует стратегию повторных попыток
        и ассоциирует ее с сессией
           )totalstatusstatus_forcelistbackoff_factor)max_retrieszhttp://r   N)r   configIMPORT_REQUEST_RETRY_TOTAL!IMPORT_REQUEST_RETRY_STATUS_CODESr   _sessionmount)r#   retrieshttp_adapters      r'   r   z"ConfluenceApi._set_session_retries9   su    
 34#E	
 
 
 #w777I|444J55555r(   c                 &   | j                             | j                  }|ro	 t          j        |          }| j        j                            |           | j        j                                        | _	        dS # t          j
        $ r Y dS w xY wdS )u  
        Добавляет cookie в сессию при инициализации,
        что бы не выполнять повторную авторизацию, если cookie еще действуют.
        При недействительных cookie, выполнится авторизация,
        а cookie обновятся в сессии и кеше
        N)r   getr    pickleloadsr3   cookiesupdateget_dictr!   PickleError)r#   cookies_pickler;   s      r'   r"   zConfluenceApi._init_cookiesH   s     77 	 ,~66%,,W555$(M$9$B$B$D$D!!!%   	 	s   AA; ;BBc                     t          j        | j        j                  }| j                            | j        |d           dS )u   
        Сохраняет cookie в кеш (Redis) для последующего использования
        без выполнения повторной авторизации
        i`T  )exN)r9   dumpsr3   r;   r   setr    )r#   r?   s     r'   _save_cookieszConfluenceApi._save_cookiesX   s:    
  dm&;<<
t~~+FFFFFr(   c                     | j         j                                        }| j        |k    r|| _        |                                  dS dS )u   
        Проверяет изменение cookie и обновляет их в кеше при необходимости
        N)r3   r;   r=   r!   rD   )r#   current_cookies_dicts     r'   _check_cookieszConfluenceApi._check_cookies`   sR      $}4==?? 444 4D      54r(   c                 b     t                      j        |i |}|                                  |S N)r   requestrG   )r#   argsr%   responser&   s       r'   rJ   zConfluenceApi.requesti   s4    "577?D3F33r(      c           	         | j         }|p| j        }|                     d||           | j                            |d||| j        | j                  5 }t                              d| d|j	         d|j
                    |                                 t          |d          5 }|                    |	          D ]}|                    |           	 d
d
d
           n# 1 swxY w Y   d
d
d
           d
S # 1 swxY w Y   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.
        GET)methodr$   headersT)streamrQ   r   verifyproxiesz
HTTP: GET z ->  zwb+)
chunk_sizeN)no_check_headersr   log_curl_debugr3   r8   r   rT   loggerdebugstatus_codereasonraise_for_statusopeniter_contentwrite)	r#   download_url	save_pathr   rV   rQ   resfchunks	            r'   download_filezConfluenceApi.download_filen   s    ')T\5lGLLL]?L  
 
 	# LLVlVVVV#*VVWWW  """i'' #1 ---DD # #EGGENNNN## # # # # # # # # # # # # # #	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	#s7   AC9%/C!C9!C%	%C9(C%	)C99C= C=c              #      K   |r|d         }|d         |d         z
  }nd}d}	 t                                          |||          }|r|                    d          sdS |d         D ]}|V  |rdS ||z  }V)u   
        Получим все пространства из Confluence

        :return: Список всех пространств
        r   r*   d   T)
space_typestartlimitresultsN)r   get_all_spacesr8   )r#   ri   slicerj   rk   rc   rowr&   s          r'   rm   zConfluenceApi.get_all_spaces   s        	!HE!HuQx'EEEE
	''((JeSX(YYC cggi00 9~  				 UNE
	r(   r   rh   archivedpagec              #   `   K   	 |                      |||||          }|sdS |E d{V  ||z  },)ud   
        Получает архивные документы из пространства
        T)content_typeN)get_all_pages_from_space)r#   spacerj   rk   r,   rs   rc   s          r'    get_all_pages_from_space_archivez.ConfluenceApi.get_all_pages_from_space_archive   sV      	//ueVZf/ggC NNNNNNNUNE	r(   c              #   \  K   t          dd          }|||<   d}	 	 |                     ||          }|                    d          sd S |d         E d {V  |dxx         |d	         z  cc<   n=# t          j        $ r+}t                              d
| d|            Y d }~d S d }~ww xY w)Nr      rj   rk   zrest/api/user/memberofTparamsrl   rj   rk   uL   Не удалось получить группы пользователя "". )dictr8   requests	HTTPErrorrY   warning)r#   keyvaluer{   r$   rc   http_errs          r'   user_member_ofzConfluenceApi.user_member_of   s     AR(((s&		hhs6h22wwy)) Fy>)))))))w6'?2%      Cns   C   C  yA   C   C  D  D  D		s   ,A0 $A0 0B*? B%%B*c                     	 |                      |          }nE# t          $ r8}t                              d| d|            t	                      }Y d }~nd }~ww xY w|S )NuL   Не удалось получить данные пользователя "r|   )get_mobile_parameters	ExceptionrY   r   r}   )r#   r   infoerrors       r'   get_user_detailzConfluenceApi.get_user_detail   sz    	--h77DD 	 	 	NN~jr~~w|~~66DDDDDD	 s    
A.AAc              #     K   | j         rt          dddd          }	 |                     d|          }|d	         sd S |d	         D ]}|d
         |                     d                   }                    fd|                                D                        d |                     dd                   D             d<   V  |dxx         |d         z  cc<   t          dddd          }	  | j        di |}|d	         sd S |d	         D ]}|d
         d         dk    rt          	                    d           /|d
         |                     |d
         d                   }                    fd|                                D                        d |                     dd                   D             d<   V  |dxx         |d         z  cc<   )Nr   rx   zuser=""zoperations,personalSpace)rj   rk   cqlexpandTzrest/api/search/userrz   rl   user	accountIdr   c              3   :   K   | ]\  }}|vs|d k    ||fV  dS  N .0kvr   s      r'   	<genexpr>z.ConfluenceApi.get_all_users.<locals>.<genexpr>   D        =  =41a#$D==AGG "#A4;GGG =  =r(   c                     g | ]}|S r   r   r   gs     r'   
<listcomp>z/ConfluenceApi.get_all_users.<locals>.<listcomp>   s    %e%e%eAa%e%e%er(   groupsrj   rk   z	type=userz&user.operations,user.status,user.emailr   recovery_adminu   В вашем Confluence включен режим восстановления! Не оставляйте Confluence в режиме восстановления и не используйте учетную запись recovery_admin!c              3   :   K   | ]\  }}|vs|d k    ||fV  dS r   r   r   s      r'   r   z.ConfluenceApi.get_all_users.<locals>.<genexpr>   r   r(   c                     g | ]}|S r   r   r   s     r'   r   z/ConfluenceApi.get_all_users.<locals>.<listcomp>   s    %c%c%cAa%c%c%cr(   r   )
r   r}   r8   r   r<   itemsr   r   rY   r   )r#   r{   rc   ro   	user_infor   s        @r'   get_all_userszConfluenceApi.get_all_users   s     :  	3C]^^^F3hh5fhEE9~ Fy>  Cv;D $ 4 4d;>O 4 P PIKK  =  =  =  =9??3D3D  =  =  = = = =%e%e1D1D[RVWbRc1d1d%e%e%eDNJJJJw6'?23 EmnnnF3dh((((9~ Fy>  C6{:.2BBB (t u u u !v;D $ 4 4c&k*>U 4 V VIKK  =  =  =  =9??3D3D  =  =  = = = =%c%c1D1DZQUV`Qa1b1b%c%c%cDNJJJJw6'?2!3r(   c              #      K   t          dd          }	  t                      j        di |}|sd S |E d {V  |dxx         |d         z  cc<   <)Nr   rx   ry   Trj   rk   r   )r}   r   get_all_groups)r#   r{   rc   r&   s      r'   r   zConfluenceApi.get_all_groups   sw      AR(((	/(%''(22622C NNNNNNN7OOOvg.OOO	/r(   c              #      K   t          dd|d          }	  t                      j        di |}|sd S |D ]}|V  |dxx         |d         z  cc<   =)	Nr   rx   zoperations,status)rj   rk   
group_namer   Trj   rk   r   )r}   r   get_group_members)r#   r   r{   rc   ro   r&   s        r'   r   zConfluenceApi.get_group_members   s      ARJGZ[[[	/+%''+55f55C   				7OOOvg.OOO	/r(   rx   
content_idrj   rk   r   returnc              #     K   d| d}i }|t          |          |d<   |t          |          |d<   |||d<   |sd|d<   	 |                     ||
          }|d         D ]?}	|r7|	d         dk    r+d |                     |	d         ||          D             |	d<   |	V  @|d         }
|
                    d          }|sdS t          |          }t	          t          |j                            }|d         |d<   |                    d          r|                    d          |d<   |                    d          r|                    d          |d<   )u  
        Получает все комментарии к документу

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

        Yields:
            Iterator[list]: элемент
        rest/api/content/z/child/commentNrj   rk   r   alldepthTrz   rl   r,   currentc                     g | ]}|S r   r   )r   objs     r'   r   z3ConfluenceApi.get_page_comments.<locals>.<listcomp>  s*     *d *d *d## *d *d *dr(   id)r   childrenr   _linksnextcursor)intr8   get_page_commentsr   r}   r   query)r#   r   rj   rk   r   r   r$   r{   rc   resultlinksnext_
next_parser   s                 r'   r   zConfluenceApi.get_page_comments   s      =*<<<!%jjF7O!%jjF7O%F8 	$#F7O	3((3v(..Ci.   dx 0I = =*d *d9O9OPVW[P\W]Ya :P :c :c *d *d *dF:& MEIIf%%E !%J:#34455E#GnF7Oyy"" 7#(99X#6#6x yy   3!&6!2!2v-	3r(   	key_spacec              #     K   d}d}	 |                      |d|||d          }|d         D ]}|d         |d	         |d
         dg ddid}|                    d          rmd |                     |d         d          D             }|                    d            ||d         d         d<   t	          |          |d         d         d<   |V  |d         sdS ||z  })ui  
        Получим все документы из корня пространства.

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

        :return: Соответствие id документа и его данных.
        r   2   Trootrq   )r   r   rj   rk   rs   rl   r   titletyperl   size)r   r   r   r   r   c                     g | ]}|S r   r   r   childs     r'   r   z;ConfluenceApi.get_root_pages_from_space.<locals>.<listcomp>I  s    ```%```r(   Fdetailedc                     | d         S Npositionr   ps    r'   <lambda>z9ConfluenceApi.get_root_pages_from_space.<locals>.<lambda>J  s
    * r(   r   r   N)get_space_contentr8   get_childrensortlen)	r#   r   r   rj   rk   rc   ro   datar   s	            r'   get_root_pages_from_spacez'ConfluenceApi.get_root_pages_from_space.  s@      	((&W\di;A ) C CC9~  d) \K')$%! !!	
 
 77:&& E``43D3DSYY^3D3_3_```HMM&=&=M>>>:BD$V,Y77:8}}D$V,V4



y> UNE/	r(   c              #      K   t          |||          }	  | j        |fi |}|r|                    d          sd S |d         D ]}|V  |dxx         |d         z  cc<   M)N)rj   rk   r   Trl   rj   rk   )r}   get_attachments_from_contentr8   )r#   page_idrj   rk   r   r{   rc   ro   s           r'   get_all_attachmentz ConfluenceApi.get_all_attachmentR  s      Ev>>>	/3$3GFFvFFC cggi00 9~  				7OOOvg.OOO	/r(   c                 T    	 |                      ||          S # t          $ r Y d S w xY w)N)userkeyr   )get_user_details_by_userkeyr	   )r#   r   r   s      r'   get_user_info_by_keyz"ConfluenceApi.get_user_info_by_key]  sB    	33GF3SSS 	 	 	44	s    
''c                 B    | j         r|                     ||          S d S )N)r   )r   get_user_details_by_accountid)r#   r   r   s      r'   get_user_infozConfluenceApi.get_user_infoc  s2    : 	P55i5OOO	P 	Pr(   c                     	 | j         r3|                     |          }|                     |d         |          S |                     ||          S # t          $ r Y d S w xY w)Nr   r   )	accountidr   )r   r   )r   get_account_idr   get_user_details_by_usernamer	   )r#   r   r   r   s       r'   get_user_info_by_usernamez'ConfluenceApi.get_user_info_by_usernameg  s    	z f**H*==99DDU^d9eee44hv4VVV 	 	 	44	s   9A A 
A! A!c                 f    d}|rd|i}nd|i}|                      ||          }|d         d         S )Nzrest/api/user/bulk/migrationr   r   rz   rl   r   r8   )r#   r   r   r$   r{   rc   s         r'   r   zConfluenceApi.get_account_idp  sI    , 	* (+FF)Fhhs6h**9~a  r(   )r   with_childrenc                2    t                      j        |g|R i |}|s%|d         |d         |d         |d         d         d}|rOd |                     ||          D             }|                    d	 
           d|t	          |          di|d<   |S )u  
        Возвращает данные контента

        Николай1: expand='children.page' имеет лимит 25 элементов, запрашиваем детей вручную
        https://jira.atlassian.com/browse/CONFSERVER-52558?src=confmacro
        get_page_child_by_type - без лимита падает, т.к. в коде думает что урлы не относительные
        поэтому лимиты считаем руками
        Bспользуется в двух местах, поэтому вынес в глобальный API

        Args:
            page_id (str, int): ID контента
            detailed (bool, optional): Вернуть подробные данные. Defaults to True.
            with_children (bool, optional): Запросить дочерние объекты. Defaults to False.

        Returns:
            page (dict): данные контента
        r   r   r   
extensionsr   r   r   r   r   c                     g | ]}|S r   r   r   s     r'   r   z0ConfluenceApi.get_page_by_id.<locals>.<listcomp>  s    YYY%YYYr(   r   c                     | d         S r   r   r   s    r'   r   z.ConfluenceApi.get_page_by_id.<locals>.<lambda>  s
    * r(   r   rq   r   r   )r   get_page_by_idr   r   r   )	r#   r   r   r   rK   r%   rq   r   r&   s	           r'   r   zConfluenceApi.get_page_by_idz  s    $ &uww%g?????? 	4jgV .z:	 D  	YY4+<+<Wx+<+X+XYYYHMM55M666'MM  D r(   typesr   c              #      K   || j         sdgnddg}|D ]b}d}d}	 |                     ||||          }|sn?|r	|E d{V  n.|D ]+}|d         |d	         |d
         |d         d         d}	|	V  ,||z  }[cdS )u  
        Возвращает дочерние объекты(контент)

        Args:
            parent_id (_type_): ID родительского контента
            types (list, optional): Список типов дочерних объектов. Defaults to None.
            detailed (bool, optional): Вернуть подробные данные. Defaults to True.

        Yields:
            dict: данные дочернего объекта(контента)
        Nrq   folderr   rx   T)r   rj   rk   r   r   r   r   r   r   )r   get_page_child_by_type)
r#   	parent_idr   r   type_rj   rk   rl   r   r   s
             r'   r   zConfluenceApi.get_children  s       =$(JFVHHVX4FE 	 	EEE55	 6     
#&&&&&&&&&") # #"(,%+G_$*6N(.|(<Z(H	    #



) 	 	r(   c              #      K   t          t                                          |                                                    d d         E d {V  d S )N)listr    get_all_restrictions_for_contentvalues)r#   r   r&   s     r'   r   z.ConfluenceApi.get_all_restrictions_for_content  sW      @@IIPPRRSSTWUWTWXXXXXXXXXXr(   c              #      K   t          dd|          }	  | j        d	i |}|d         E d {V  |dxx         |d         z  cc<   |d         |d         k     rd S F)
Nr   rh   )rj   rk   r   Trl   rj   rk   r   r   )r}   get_page_labels)r#   r   r{   rc   s       r'   get_all_page_labelsz!ConfluenceApi.get_all_page_labels  s      AS':::	&$&0000C9~%%%%%%%7OOOvg.OOO6{VG_,,	r(   version_numberc                 r    | j         r	d| d| }nd| d| }i }|||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/Nr   rz   )r   r8   )r#   r   r  r   r$   r{   s         r'   get_page_versionzConfluenceApi.get_page_version  sf     : 	UKjKK>KKCCTzTTNTTC%F8xxFx+++r(      r   current_versionlast_versionsc           	   #     K   |sdS | j         rd| d}nd| d}i }|t          |          |d<   |t          |          |d<   |||d<   d}		 	 |                     ||
          }
|
d         }|                    d          }|
d         D ]*}|	dz  }	d|cxk    r|	k     rn nd} n|d         dz
  }|V  +n|#  t          |dd          D ]a}|	dz  }	d|cxk    r|	k     rn n nI	 |                     |||          V  4# t
          $ r!}t          d| d|           V  Y d}~Zd}~ww xY wd}Y nxY w|sdS t          |          }t          t          |j	                            }|d         |d<   |                    d          r|                    d          |d<   |                    d          r|                    d          |d<   )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  rj   rk   r   r   Trz   r   r   rl   r*   Fnumberr   u   версия z. r   )
r   r   r8   ranger  r   r   r}   r   r   )r#   r   r  rj   rk   r  r   r$   r{   version_countrc   r   r   versionr  excr   r   s                     r'   get_page_versionszConfluenceApi.get_page_versions  s     2  	4: 	D:j:::CCCzCCCC!%jjF7O!%jjF7O%F8'	3hhs6h22H		&))"9~ " "G!Q&MM9999M99999 %&-h&7!&;O!MMMM&+OQ&C&C Q QN!Q&MM9999M99999Q"33JPVWWWWWW$ Q Q Q'(O(O(O#(O(OPPPPPPPPPPQ  !%J:#34455E#GnF7Oyy"" 7#(99X#6#6x yy   3!&6!2!2vO'	3s7   A'B8 8,D1%C?>D1?
D*	D% D1%D**D1c                     | j         r-|                     |d          }|                    dg           S d}ddd|gd}|                     ||                              d	g           S )
Npermissions)	space_keyr   z!rpc/json-rpc/confluenceservice-v2z2.0getSpacePermissionSets   )jsonrpcrP   r   r{   )r   r   )r   	get_spacer8   post)r#   r  
space_datar$   r   s        r'   get_space_permissionsz#ConfluenceApi.get_space_permissionsA  s|    : 	5)MRRJ>>-4441. k	
 
 yy4y((,,Xr:::r(   c                 0    d}|                      |          S )u   
        Получает связи с другими системами

        Return:
            applinks (dict): данные связей с другими системами
        zrest/applinks/3.0/applinksr   )r#   r$   s     r'   get_applinkszConfluenceApi.get_applinksO  s     ,xx}}r(   )NrM   )NN)r   rh   rp   rq   )r   rx   NTrI   )r   rx   N)NT)r   r  r   N)+__name__
__module____qualname____doc__r0   !IMPORT_CONFLUENCE_REQUEST_TIMEOUTcmfutilrequests_sessionr   r   r"   rD   rG   rJ   rf   rm   rv   r   r   r   r   r   strr   r   r   r}   r   r   r   r   r   r   r   boolr   r   r   r  r  r  r  __classcell__)r&   s   @r'   r   r      s       UU 8((**' ' ' ' ' 'R6 6 6   G G G! ! !    
# # # #:     0	 	 	 	     !3 !3 !3F/ / / / // / / / / 8:7;/3 /3C /3!$/314/3"%/3@D/3 /3 /3 /3b" "3 " "t " " " "H	/ 	/S 	/ 	/ 	/ 	/   P P P P   ! ! ! ! 7;% % % % % % % %N' 'T 'D ' ' ' 'RY Y Y Y Y  , ,3 , ,S ,\` , , , ,6 Q3 Q3Q3 Q3 	Q3
 Q3 Q3 Q3 
Q3 Q3 Q3 Q3f; ; ;	d 	 	 	 	 	 	 	 	r(   r   )urllib.parser   r   cmf.includer9   r~   requests.adaptersr   urllib3.util.retryr   	atlassianr   atlassian.errorsr	   logging	getLoggerrY   r   r   r(   r'   <module>r-     s    , , , , , , , ,       ) ) ) ) ) ) $ $ $ $ $ $             - - - - - -			2	3	3J	 J	 J	 J	 J	J J	 J	 J	 J	 J	r(   