
    Th\                         d dl mZmZ d dl 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j                  d      Z G d	 d
e      Zy)    )urlparse	parse_qsl)*N)HTTPAdapter)Retry)
Confluence)ApiNotFoundErrorzatlassian.rest_clientc                       e Zd ZdZddej
                  dej                         ddf fd	Zd Z	d Z
d Zd	 Z fd
Zd.dZd/ fd	Zd0dZd Zd Zd Z fdZ fdZ	 	 d1dededededef
dZd2dededefdZd3defdZd2dZd2dZd2dZd/dZ ddd  fd!
Z!d4d"ed#e"fd$Z# fd%Z$d& Z%d2ded'ededefd(Z&	 	 	 	 d5ded)ededed*ededefd+Z'd, Z(defd-Z) xZ*S )6ConfluenceApiuK    Подключение по API к учетной записи Confluence NTFc	                 f   |j                  d      r|nd| }|j                  d      s|dz  }|r|}nd }t        
|   |f|||||||d|	 | j	                          t
        j                  j                  | _        dt        |      j                   | _
        d | _        | j                          y )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+c8C51A||C 3JCHE
	
!
	
 
	
 	!!#\\''
-hsm.B.B-CD     c                     t        t        j                  t        j                  t        j                  d      }t	        |      }| j
                  j                  d|       | j
                  j                  d|       y)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   s`    
 3344#EE	
 #w7I|4J5r(   c                 N   | j                   j                  | j                        }|re	 t        j                  |      }| j
                  j                  j                  |       | j
                  j                  j                         | _	        yy# t        j                  $ r Y yw xY w)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 ,,~6%%,,W5$(MM$9$9$B$B$D!	 
 %% s   A#B B$#B$c                     t        j                  | j                  j                        }| j                  j                  | j                  |d       y)u   
        Сохраняет cookie в кеш (Redis) для последующего использования
        без выполнения повторной авторизации
        i`T  )exN)r9   dumpsr3   r;   r   setr    )r#   r?   s     r'   _save_cookieszConfluenceApi._save_cookiesX   s6    
  dmm&;&;<

t~~~+Fr(   c                     | j                   j                  j                         }| j                  |k7  r|| _        | j	                          yy)u   
        Проверяет изменение cookie и обновляет их в кеше при необходимости
        N)r3   r;   r=   r!   rD   )r#   current_cookies_dicts     r'   _check_cookieszConfluenceApi._check_cookies`   sE      $}}44==? 44 4D  5r(   c                 F    t        |   |i |}| j                          |S N)r   requestrG   )r#   argsr%   responser&   s       r'   rJ   zConfluenceApi.requesti   s'    7?D3F3r(   c           	         | j                   }|xs | j                  }| j                  d||       | j                  j	                  |d||| j
                  | j                        5 }t        j                  d| d|j                   d|j                          |j                          t        |d      5 }|j                  |	      D ]  }|j                  |        	 d
d
d
       d
d
d
       y
# 1 sw Y   xY w# 1 sw Y   y
xY w)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)streamrP   r   verifyproxiesz
HTTP: GET z ->  zwb+)
chunk_sizeN)no_check_headersr   log_curl_debugr3   r8   r   rS   loggerdebugstatus_codereasonraise_for_statusopeniter_contentwrite)	r#   download_url	save_pathr   rU   rP   resfchunks	            r'   download_filezConfluenceApi.download_filen   s     '')T\\5lGL]]??LL  
 	# LL:l^47H#**VW  "i' #1 ---D #EGGEN##	# 	## #	# 	#s%   &AC<5)C0C<0C9	5C<<Dc              #      K   |r|d   }|d   |d   z
  }nd}d}	 t         |   |||      }|r|j                  d      sy|d   D ]  }|  |ry||z  }=w)u   
        Получим все пространства из Confluence

        :return: Список всех пространств
        r   r*   d   )
space_typestartlimitresultsN)r   get_all_spacesr8   )r#   rh   sliceri   rj   rb   rowr&   s          r'   rl   zConfluenceApi.get_all_spaces   s      !HE!HuQx'EEE'(JeSX(YCcggi09~ 	 UNE s   AAc              #   b   K   	 | j                  |||||      }|sy|E d{    ||z  })7 
w)ud   
        Получает архивные документы из пространства
        )content_typeN)get_all_pages_from_space)r#   spaceri   rj   r,   rp   rb   s          r'    get_all_pages_from_space_archivez.ConfluenceApi.get_all_pages_from_space_archive   sG      //ueVZf/gCNNUNE  s    /-/c              #   6  K   t        dd      }|||<   d}	 	 | j                  ||      }|j                  d      sy |d   E d {    |dxx   |d   z  cc<   D7 # t        j                  $ r%}t        j                  d	| d
|        Y d }~y d }~ww xY ww)Nr      ri   rj   zrest/api/user/memberofparamsrk   ri   rj   uL   Не удалось получить группы пользователя "". )dictr8   requests	HTTPErrorrX   warning)r#   keyvaluerx   r$   rb   http_errs          r'   user_member_ofzConfluenceApi.user_member_of   s     AR(s&hhs6h2wwy)y>))w6'?2 
 *%% !mnsmttw  yA  xB   C  DsJ   B$A BA AA BA B1BBBBc                     	 | j                  |      }|S # t        $ r0}t        j                  d| d|        t	               }Y d }~|S d }~ww xY w)NuL   Не удалось получить данные пользователя "ry   )get_mobile_parameters	ExceptionrX   r}   rz   )r#   r   infoerrors       r'   get_user_detailzConfluenceApi.get_user_detail   s[    	--h7D
 	  	NNijrissvw|v}~6D		s    	A%A		Ac              #   >  K   | j                   rt        dddd      }	 | j                  d|      }|d   sy |d   D ]n  }|d	   | j                  d
         }j	                  fd|j                         D               | j                  d
d
         D cg c]  }| c}d<    p |dxx   |d   z  cc<   t        dddd      }	  | j                  di |}|d   sy |d   D ]  }|d	   d   dk(  rt        j                  d       $|d	   | j                  |d	   d         }j	                  fd|j                         D               | j                  dd         D cg c]  }| c}d<     |dxx   |d   z  cc<   c c}w c c}w w)Nr   ru   zuser=""zoperations,personalSpace)ri   rj   cqlexpandzrest/api/search/userrw   rk   user	accountIdr   c              3   >   K   | ]  \  }}|vs|d k7  r||f  yw N .0kvr   s      r'   	<genexpr>z.ConfluenceApi.get_all_users.<locals>.<genexpr>   -       =41a#$D=AG "#A  =   groupsri   rj   z	type=userz&user.operations,user.status,user.emailr   recovery_adminu   В вашем Confluence включен режим восстановления! Не оставляйте Confluence в режиме восстановления и не используйте учетную запись recovery_admin!c              3   >   K   | ]  \  }}|vs|d k7  r||f  ywr   r   r   s      r'   r   z.ConfluenceApi.get_all_users.<locals>.<genexpr>   r   r   r   )
r   rz   r8   r   r<   itemsr   r   rX   r}   )r#   rx   rb   rn   	user_infogr   s         @r'   get_all_userszConfluenceApi.get_all_users   s    ::C]^Fhh5fhE9~y> Cv;D $ 4 4d;>O 4 PIKK  =9??3D  = =151D1D[RVWbRc1d%eAa%eDNJ w6'?2  EmnFdhh((9~y> C6{:.2BB (t u !v;D $ 4 4c&k*>U 4 VIKK  =9??3D  = =151D1DZQUV`Qa1b%cAa%cDNJ w6'?2!  &f& &ds   BF	F#C
F-	F6'Fc              #      K   t        dd      }	 t        |   di |}|sy |E d {    |dxx   |d   z  cc<   -7 w)Nr   ru   rv   ri   rj   r   )rz   r   get_all_groups)r#   rx   rb   r&   s      r'   r   zConfluenceApi.get_all_groups   sQ     AR('(262CNN7Ovg.O  s   &A?Ac              #      K   t        dd|d      }	 t        |   di |}|sy |D ]  }|  |dxx   |d   z  cc<   .w)Nr   ru   zoperations,status)ri   rj   
group_namer   ri   rj   r   )rz   r   get_group_members)r#   r   rx   rb   rn   r&   s        r'   r   zConfluenceApi.get_group_members   s^     ARJGZ['+5f5C 	7Ovg.O s   ?A
content_idri   rj   r   returnc              #   R  K   d| d}i }|t        |      |d<   |t        |      |d<   |||d<   |sd|d<   	 | j                  ||	      }|d
   D ]8  }	|r0|	d   dk(  r(| j                  |	d   ||      D 
cg c]  }
|
 c}
|	d<   |	 : |d   }|j                  d      }|syt        |      }t	        t        |j                              }|d   |d<   |j                  d      r|j                  d      |d<   |j                  d      r|j                  d      |d<   c c}
w w)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   r   alldepthrw   rk   r,   currentid)r   childrenr   _linksnextcursor)intr8   get_page_commentsr   rz   r   query)r#   r   ri   rj   r   r   r$   rx   rb   resultobjlinksnext_
next_parser   s                  r'   r   zConfluenceApi.get_page_comments   si     "*^<!%jF7O!%jF7O%F8#F7O((3v(.Ci. x 0I =9=9O9OPVW[P\W]Ya :P :c *d## *dF:&  MEIIf%E!%J:#3#345E#GnF7Oyy"#(99X#6x yy !&6!2v- *ds   A6D'8	D"B&D'	key_spacec              #   v  K   d}d}	 | j                  |d|||d      }|d   D ]  }|d   |d   |d	   dg dd
id}|j                  d      rU| j                  |d   d      D cg c]  }| }	}|	j                  d        |	|d   d   d<   t	        |	      |d   d   d<   |  |d   sy||z  }c c}w w)ui  
        Получим все документы из корня пространства.

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

        :return: Соответствие id документа и его данных.
        r   2   rootpage)r   r   ri   rj   rp   rk   r   titletyperk   size)r   r   r   r   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   ri   rj   rb   rn   datachildr   s
             r'   get_root_pages_from_spacez'ConfluenceApi.get_root_pages_from_space.  s     ((&W\di;A ) CC9~ d) \K')$%!!	
 77:&373D3DSYY^3D3_`%`H`MM&=M>:BD$V,Y77:8}D$V,V4
#$ y>UNE/    as   A#B9%	B4.AB9c              #      K   t        |||      }	  | j                  |fi |}|r|j                  d      sy |d   D ]  }|  |dxx   |d   z  cc<   Fw)N)ri   rj   r   rk   ri   rj   )rz   get_attachments_from_contentr8   )r#   page_idri   rj   r   rx   rb   rn   s           r'   get_all_attachmentz ConfluenceApi.get_all_attachmentR  sn     Ev>3$33GFvFCcggi09~ 	7Ovg.O s   AAc                 H    	 | j                  ||      S # t        $ r Y y 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]  s/    	33GF3SS 		s    	!!c                 B    | j                   r| j                  ||      S y )N)r   )r   get_user_details_by_accountid)r#   r   r   s      r'   get_user_infozConfluenceApi.get_user_infoc  s$    ::55i5OO r(   c                     	 | j                   r(| j                  |      }| j                  |d   |      S | j                  ||      S # t        $ r Y y 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  se    	zz**H*=99DDU^d9ee44hv4VV 		s   3A	 A	 		AAc                 R    d}|rd|i}nd|i}| j                  ||      }|d   d   S )Nzrest/api/user/bulk/migrationr   r   rw   rk   r   r8   )r#   r   r   r$   rx   rb   s         r'   r   zConfluenceApi.get_account_idp  s?    , (+F)Fhhs6h*9~a  r(   )r   with_childrenc                    t        	|   |g|i |}|s|d   |d   |d   |d   d   d}|rF| j                  ||      D cg c]  }| }}|j                  d 	       d
|t	        |      di|d<   |S c c}w )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   r   c                     | d   S r   r   r   s    r'   r   z.ConfluenceApi.get_page_by_id.<locals>.<lambda>  s
    * r(   r   r   r   r   )r   get_page_by_idr   r   r   )
r#   r   r   r   rK   r%   r   r   r   r&   s
            r'   r   zConfluenceApi.get_page_by_idz  s    $ w%g???4jgV .z:	D +/+<+<Wx+<+XY%YHYMM5M6'M D  Zs   	A7typesr   c              #      K   || j                   sdgnddg}|D ]R  }d}d}	 | j                  ||||      }|s |r|E d{    n!|D ]  }|d   |d   |d	   |d
   d   d}	|	  ||z  }L y7 .w)u  
        Возвращает дочерние объекты(контент)

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

        Yields:
            dict: данные дочернего объекта(контента)
        Nr   folderr   ru   )r   ri   rj   r   r   r   r   r   r   )r   get_page_child_by_type)
r#   	parent_idr   r   type_ri   rj   rk   r   r   s
             r'   r   zConfluenceApi.get_children  s      =$(JJVHVX4FE 	EEE55	 6  &&&") #"(,%+G_$*6N(.|(<Z(H	  #
# ) 		 's   ?A2A0/A2c              #   t   K   t        t        | 	  |      j                               d d E d {    y 7 w)N)listr    get_all_restrictions_for_contentvalues)r#   r   r&   s     r'   r   z.ConfluenceApi.get_all_restrictions_for_content  s1     @IPPRSTWUWXXXs   -868c              #      K   t        dd|      }	  | j                  di |}|d   E d {    |dxx   |d   z  cc<   |d   |d   k  ry <7 !w)	Nr   rg   )ri   rj   r   rk   ri   rj   r   r   )rz   get_page_labels)r#   r   rx   rb   s       r'   get_all_page_labelsz!ConfluenceApi.get_all_page_labels  sh     AS':&$&&00C9~%%7Ovg.O6{VG_,  &s   *AA"Aversion_numberc                 t    | j                   r	d| d| }nd| d| }i }|||d<   | j                  ||      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/r   rw   )r   r8   )r#   r   r   r   r$   rx   s         r'   get_page_versionzConfluenceApi.get_page_version  sY     ::%j\>:JKC.zl)NCSTC%F8xxFx++r(   current_versionlast_versionsc           	   #   $  K   |sy| j                   rd| d}nd| d}i }|t        |      |d<   |t        |      |d<   |||d<   d}		 	 | j                  ||	      }
|
d
   }|j                  d      }|
d   D ]%  }|	dz  }	d|cxk  r|	k  rn nd} n|d   dz
  }| ' |syt        |      }t        t        |j                              }|d   |d<   |j                  d      r|j                  d      |d<   |j                  d      r|j                  d      |d<   #  t        |dd      D ]V  }|	dz  }	d|cxk  r|	k  rn n nA	 | j	                  |||       /# t
        $ r}t        d| d|        Y d}~Pd}~ww xY w d}Y xY ww)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   r   r   rw   r   r   rk   r*   Fnumberr   u   версия z. r   )
r   r   r8   ranger   r   r   rz   r   r   )r#   r   r   ri   rj   r   r   r$   rx   version_countrb   r   r   versionr   excr   r   s                     r'   get_page_versionszConfluenceApi.get_page_versions  s    2 ::%j\:C.zl(CC!%jF7O!%jF7O%F8hhs6h2H		&)"9~ "G!Q&MM9M9 %&-h&7!&;O!M"* !%J:#3#345E#GnF7Oyy"#(99X#6x yy !&6!2vO &+OQ&C QN!Q&MM9M9Q"33JPVWW$ Q'-7Gr#(OPPQQ sJ   A	FAD! "A?F!'F	EF	F(F ;F FFFc                     | j                   r%| j                  |d      }|j                  dg       S d}ddd|gd}| j                  ||      j                  d	g       S )
Npermissions)	space_keyr   z!rpc/json-rpc/confluenceservice-v2z2.0getSpacePermissionSets   )jsonrpcrO   r   rx   )r   r   )r   	get_spacer8   post)r#   r  
space_datar$   r   s        r'   get_space_permissionsz#ConfluenceApi.get_space_permissionsA  sh    ::)MRJ>>-441. k	
 yy4y(,,Xr::r(   c                 (    d}| j                  |      S )u   
        Получает связи с другими системами

        Return:
            applinks (dict): данные связей с другими системами
        zrest/applinks/3.0/applinksr   )r#   r$   s     r'   get_applinkszConfluenceApi.get_applinksO  s     +xx}r(   )Ni   )NN)r   rg   archivedr   )r   ru   NTrI   )r   ru   N)NT)r      r   N)+__name__
__module____qualname____doc__r0   !IMPORT_CONFLUENCE_REQUEST_TIMEOUTcmfutilrequests_sessionr   r   r"   rD   rG   rJ   re   rl   rs   r   r   r   r   r   strr   r   r   rz   r   r   r   r   r   r   r   boolr   r   r   r   r  r  r  __classcell__)r&   s   @r'   r   r      s   U 88((*'R6 G!
#:0	 !3F// 8:7;/3C /3!$/314/3"%/3@D/3b"3 " "t "H	/S 	/P! 7;% %N'T 'D 'RY,3 , ,S ,\` ,6 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	getLoggerrX   r   r   r(   r'   <module>r%     s<    ,    ) $   -			2	3J	J J	r(   