U
    dr                     @   s   d dl Z 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
 d dlmZ d dlZd dlZd dlT d dlmZ d	Zd
Zee ZG dd dZdS )    N)Path)TemporaryDirectory)Dict)parse)datetime)*)RFilei  i  c                   @   s  e Zd ZdZeedddZeedddZeedddZe	eed	d
dZ
eedddZe	ddddZddddZe	ddddZe	ddddZe	ddddZe	eeedddZeedddZeedd d!Ze	eedd"d#d$Ze	eedd%d&d'Zeedd(d)d*Zeedd+d,d-Zeedd.d/d0Zddd1d2Ze	eeedd3d4d5Zd@eeeed7d8d9Ze	dAeeeeed:d;d<Ze	eed=d>d?ZdS )BCmfPluginConvertMixinuO   
    Используется в классах CmfDocument, CmfAttachment
    )	html_textreturnc                 C   s8   |  |}| t|dddd}| |dd}| |S )u   
        Сохраняет HTML -> PDF
        Используется преобразование через DOCX, из-за этого нет разрыва страниц.

        :return: Данные pdf в виде строки base64
        utf-8encoding.htmldocx:MS Word 2007 XMLz.docxzpdf:writer_pdf_Export_handle_htmlobj_to_formatbytes_get_base64)selfr
   html
docx_bytes	pdf_bytes r   +./common/models/cmf_plugin_convert_mixin.pysave_to_pdf   s    
z!CmfPluginConvertMixin.save_to_pdfc                 C   s*   |  |}| t|dddd}| |S )uu   
        Сохраняет HTML -> DOCX

        :return: Данные docx в виде строки base64
        r   r   r   r   r   )r   r
   r   r   r   r   r   save_to_docx*   s    
z"CmfPluginConvertMixin.save_to_docxc           	   
   C   s~   ddl m} ddlm} | }| }t J}| ||}||| t }|	| |
d | W  5 Q R  S Q R X dS )ud   
        Преобразует HTML -> DOCX

        :return: Данные в байтах
        r   )Document)
HtmlToDocxN)Zdocxr   Zhtmldocxr   r   _handle_view_htmlZadd_html_to_documentioBytesIOsaveseekgetvalue)	r   r
   r   r   ZdocumentZ
new_parsertmp_dir_namer   	docx_filer   r   r   html_to_docx5   s    

z"CmfPluginConvertMixin.html_to_docx)contentr   c                 C   s   t |  S )up   
        Преобразует байты в строку base64

        :return: Строка base64
        )base64Z	b64encodedecode)r)   r   r   r   r   I   s    z!CmfPluginConvertMixin._get_base64c              	   C   s  ddl m} ddl}i }ttjdtjd|D ]:}t|	 }|
 }d| d}|||}|||< q0||}	|	d}
|	jd	d
d}d|_|	j|
 |	jj| |	d}|r|  |	dD ]}|jdkr||	d q| |	 | |	 | |	 | |	 | |	 t|	}|D ]|}z6|j|| d}| |}d| d}|||}W n> tk
r   d||  }t| |||| }Y nX q*|S )u   
        Обработка страницы html для сохранения

        :param html_text: Страница html
        :return: Обработанная страница html
        r   BeautifulSoupNz(<svg.*?svg>))flagsz	<div id="z"></div>headstyleztext/css)typez@page { size: 21.0cm 29.7cm }h1pbr)Z
bytestringz <img src="data:image/png;base64,z">u=   Не удалось конвертировать svg в png: )bs4r-   cairosvgrefindallcompileDOTALLhashlibmd5encodeZ	hexdigestreplacenew_tagstringr   appendr/   find	decomposefind_all_handle_html_card_preview_handle_html_img_handle_html_table_handle_html_layout_handle_html_cleanstrZsvg2pngr   	Exceptionlogging	exception)r   r
   r-   r6   Zsvg_replaceZsvgr<   Zmd5sumkeysoupZhead_tag	style_tagr2   r3   Zimg_contentattach_base64img_tagerr_msgr   r   r   r   R   sL    










z"CmfPluginConvertMixin._handle_htmlN)r   c                 C   s   | j ddD ]z}|d}d|jd< |jdd| d}|jdd| d}| d}|| || || || qd	S )
u  
        Метод парсит DIV вложения и оставляет в нем только нужные теги: изображение, имя файла и дата

        :param bs4.BeautifulSoup soup: Объект библиотеки
        zapp-tinymce-card-previewclass_imgZ150pxwidthzapp-tinymce-file-name-viewdivzapp-tinymce-file-create-viewN)rD   rB   attrswrapr?   rA   replace_with)rO   ZpreviewrV   	file_nameZfile_createrX   r   r   r   rE      s    





z/CmfPluginConvertMixin._handle_html_card_previewc                 C   s  ddl m} ddl}| x}|dD ]d}|jd}|jd}|r|drttd t	|
 dd	 }nt	|
 d
d	}|r|drtd t	|
 dd	 }nt	|
 d
d	}|jd}|sq*|dtj r|dtj d	}|dr|dd}t|}	tjjdd|	gdgd}
|
rNt|
j}nt|	dtj}| sxttjd }t|d4}| | }d|jdd	 d| |jd< W 5 Q R X ||}|j\}}|drzt|}|jdkr||dd d }|dkrd}| |j }d| d| |jd< t| dt!" dd| }t|d }|#|j  W 5 Q R X ||}|j\}}W nD t$k
r } z$t%&d! t'd"|  W Y q*W 5 d}~X Y nX |r|s|| }|| }|r|s|| }|| }|s"|s"|}|}|| }|t( }|| }|t)ksN|dkrp|r\t)| nd}t)}|t*|9 }| d
|jd< | d
|jd< q*W 5 Q R X dS )#u#  
        Метод заменяет адрес картинки на base64 и масштабирует размер изображения под формат А4 относительно исходного

        :param bs4.BeautifulSoup soup: Объект библиотеки
        r   ImageNrV   rW   height%d    pxsrczhttps:///z%25url==r   filterZfields/files/common/static/file-outline.pngrbdata:image/.z;base64,http      )ZpngZbmpZgifZtiffZtifZjpegZjpgz/imgz%Y%m%d-%H%M%Szwb+uL   Не удалось скачать изображения документаuN   Не удалось скачать изображения документа: )+PILr^   tempfiler   rD   rY   getendswithWEB_PAGE_WIDTH_PXfloatstripr>   
startswithconfigZAPP_FQDNr   unquotemodelsCmfAttachmentr   full_path_file
UPLOAD_DIRexistsPROJECT_DIRopenr   readsuffixsizerequestsstatus_coderfindr)   r   ZnowwriterK   rL   rM   	cmf_alertSCALE_A4A4_PAGE_WIDTH_PXabs)r   rO   r^   rs   tmp_dirrR   rW   r_   rd   url_path
attachmentZattach_pathZattachment_byterQ   rV   Zwidth_originalZheight_originalresZextension_imgZ	file_pathfpeZscaleproportion_ratiocoefficientr   r   r   rF      s    



*





z&CmfPluginConvertMixin._handle_html_imgc              	   C   s,  |  dD ]}i }|jddd}|r0|| |dddD ]&}|rB|d\}}| || < qB|d	s|d	d
|d	< |dsd|d< |dsd|d< |ds|dd|d< i }|jdk	rpt|jjddD ]\}}	|	j	dddD ]d}d	|kr|d\}}|
drBtd t| dd }
nt| ddt }
|
||< qq|j  | dD ]}d}| dD ]}i }|dddD ]*}|r|d\}}| || < q|s0|d	 }r|
drtd t| dd }nt| ddt }nX|| }|d }rt|d t|| D ]}||| 7 }q^|t|7 }n|d7 }| dD ]|}t|j	d	 dd}t|j	d dd}||kr|| }|d }| d|j	d	< ||  d|j	d< q| d|d	< qqzq
dS )u  
        Функция добавляет стиль для таблиц
        Для конвертирования таблиц в LibreOffice используем inline style

        :param bs4.BeautifulSoup soup: Объект библиотеки
        tablerX   ztableView-content-wraprT   r0   rb   ;:rW   100%Zcellpadding1ZcellspacingZborderNrq   )startr`   ra   rc   trtdcolspanrV   r_   g)\(@)rD   Zfind_parentr[   rt   splitrx   Zcolgroup	enumeratechildrenrY   ru   r   rw   r>   r   rC   rangeint)rO   r   Zstyle_tableparentparamsnamevalueZ
cols_widthZcol_numcolZwidth_pxr   r   Ztd_styleZtd_widthr   irV   Z	img_widthZ
img_heightr   r   r   r   rG      sp    	






z(CmfPluginConvertMixin._handle_html_tablec                    s   ddl m  | dddiD ]}d|d< d|_| d	} fd
d|jD }t|}td| d}|D ]*}d|_|d| d|d< |	| qf|	| qdS )u   
        Функция добавляет стиль для макета, используем table, так как flex не поддерживается в LibreOffice

        :param bs4.BeautifulSoup soup: Объект библиотеки
        r   TagrX   zdata-layout-sectiontruer   rW   r   r   c                    s   g | ]}t | r|qS r   )
isinstance.0elr   r   r   
<listcomp>]  s     
 z=CmfPluginConvertMixin._handle_html_layout.<locals>.<listcomp>ra      r   zdata-column-widthr`   N)
r5   r   rD   r   r?   r   lenroundrt   rA   )rO   Zlayoutr   columnsZ	nums_colsZwidth_columncolumnr   r   r   rH   O  s    
z)CmfPluginConvertMixin._handle_html_layoutc                 C   s"   | j ddgdD ]}|  qdS )u   
        Метод очищает HTML от лишних тегов

        :param bs4.BeautifulSoup soup: Объект библиотеки
        ztable-context-menuzcell-dropbox-buttonrT   N)rD   rC   )rO   tagr   r   r   rI   f  s    z(CmfPluginConvertMixin._handle_html_clean)r
   tmp_pathr   c           !   
   C   s  ddl m}m} ddlm} || }g }|dD ]>}d|jddkrZ|t	|dd	 |jd
s2d|jd
< q2|dD ]}|t	|dd	 q||dD ]}|
  q|dD ]}|
  qt|D ]\}}	|	d }|jdd}
|jdd}|jd}|dr|d\}}|dd}|dd}t|d| d|  }t|d$}|t| t||jd< W 5 Q R X |dr
t|}tjjddtjgdgd}|rt|j}nt|dtj}| r
t||jd< |
s
||}|j\}
}d}tdd d! t|
D }|d"rBttj d# }|!d$d%kr\t"|n|!d$}||!d| }t#|}|j$d&kr4t|}|d'| |  % }t|d}||j& W 5 Q R X z>||}|j\}
}t||jd< |r|n|
r|
n|}W n$ |k
r0   t||jd< Y nX nt||jd< ||krP|n|}|r|| rj|| nd(}||jd< tdd)d! t|D } t| | |jd< qt|S )*u   
        Функция заменяет адрес картинки, файла на фактический

        :return: HTML с фактическими адресами картинок, файлов
        r   )r^   UnidentifiedImageErrorr,   azcmf-fileclassrb   file)objr1   ZhrefrV   Zimager0   titler   rW   r_   rd   z
data:image,rm   z;base64Zfile_rn   wbrj   rf   rg   r   rh   i  c                 s   s   | ]}|  r|V  qd S Nisdigitr   r   r   r   	<genexpr>  s      z:CmfPluginConvertMixin._handle_view_html.<locals>.<genexpr>ro   rk   ?rp   Zname_rq   c                 s   s   | ]}|  r|V  qd S r   r   r   r   r   r   r     s      )'rr   r^   r   r5   r-   rD   rY   rt   rA   dictrC   r   ry   r   r>   r   r   r   r*   Z	b64decoderJ   r   r{   r|   r}   rz   r   r~   r   r   r   joinr   r   r   r   r   Zresolver)   )!r
   r   r^   r   r-   rO   filesr   indexZ_filerW   r_   Zfull_urlZtype_imgZb64dataZ	name_fileZfile_imgr   r   Zattachment_pathrV   Zwidth_defaultZwidth_valueZpath_defaultZend_nameZfile_extensionZresponser   filepathr   Z	width_newr   Zheight_valuer   r   r   r    p  s    





"



z'CmfPluginConvertMixin._handle_view_htmlc              
   C   s  ddl m}m} ddlm} tjd||fd}tj	tj
tjtdd}tj
|ddd	d
dd}| }d|_|  |dd| |d ||}|dD ]}	d|	jd< q|dD ]}	d|	jd< d|	jd< qt 0}
|| | |
 t| W  5 Q R  S Q R X dS )uw   
        Конвертирует HTML -> PDF

        :return: Возвращает байты PDF файла
        r   )FPDF	HTMLMixinr,   	_HTML2PDF)basesz..modulesZappZassetsZfontsz	noto-sanszNotoSans-Regular.ttfr   ZNotoSansrb   r   r   rW   r   Z100r   r   N)Zfpdfr   r   r5   r-   types	new_classospathabspathr   dirname__file__Zcore_fonts_encodingZadd_pageZadd_fontZset_fontZfindAllrY   r   Z
write_htmlr    Zprettifyr   output)r   r
   r   r   r-   r   Z	path_fontZpdfrO   r   r&   r   r   r   html_to_pdf  s&     

z!CmfPluginConvertMixin.html_to_pdf)	path_docxr   c              
   C   sH   ddl m} tj|rDt|d}||}|jW  5 Q R  S Q R X dS )u7   
        Конвертирует DOCX -> HTML
        r   )convert_to_htmlrl   N)Zmammothr   r   r   r   r   r   )r   r   r   r'   resultr   r   r   docx_to_html  s
    z"CmfPluginConvertMixin.docx_to_html)path_imgr   r   c                 C   s   t | | dS u5   
        Конвертирует PDF -> PNG
        N)r   pdf_bytes_to_imgr   r   r   r   r   r     s    z&CmfPluginConvertMixin.pdf_bytes_to_img)path_pdfr   r   c                 C   s   t | | dS r   )r   
pdf_to_img)r   r   r   r   r   r     s    z CmfPluginConvertMixin.pdf_to_img)	path_htmlr   r   c              	   C   sB   t j|r>t|d"}| | }| j||d W 5 Q R X dS )u6   
        Конвертирует HTML -> PNG
        rr   N)r   r   r   r   r   r   r   )r   r   r   	file_htmlr   r   r   r   html_to_img  s    z!CmfPluginConvertMixin.html_to_img)	path_xlsxr   r   c                 C   s   ddl m } ||| dS )u7   
        Конвертирует XLSX -> HTML
        r   	xlsx2htmlNr   )r   r   r   r   r   r   r   xlsx_to_html  s    z"CmfPluginConvertMixin.xlsx_to_html)r   path_pngr   c                 C   s$   ddl m} ||}|| dS )u<   
        Сохранение в формате PNG
        r   r]   N)rr   r^   r   r#   )r   r   r   r^   rV   r   r   r   save_img  s    
zCmfPluginConvertMixin.save_imgc              
      s  ddl m} ddlm} ddlm  ddlm ||ddd}| }| }tt	|D ]}|
|| }	|dkr|j}
|| |
_n|j|| d}
|	jD ]*}|\}}}}|
j|d	 ||d	 |d
 q fddt|	jD ],}|
fdd|	j||	|dD  qqZ|| dS )u6   
        Конвертирует XLS -> XLSX
        r   )workbook)open_workbook)XL_CELL_DATE)xldate_as_tupleT)Zformatting_infoZragged_rows)r   rq   )Z	start_rowZend_rowZstart_columnZ
end_columnc                    sJ   | j }| j krF|d}|dd dkr>tj|dd   }nt| }|S )Nr      )r   r   r   )r   Zctyper   time)cellr   Zdatetime_tup)r   r   r   r   _get_xlrd_cell_value8  s    

z?CmfPluginConvertMixin.xls_to_xlsx.<locals>._get_xlrd_cell_valuec                 3   s   | ]} |V  qd S r   r   )r   r   )r   r   r   r   C  s   z4CmfPluginConvertMixin.xls_to_xlsx.<locals>.<genexpr>)Zend_colxN)Zopenpyxlr   Zxlrdr   r   r   ZWorkbooksheet_namesr   r   Zsheet_by_nameZactiver   Zcreate_sheetZmerged_cellsZmerge_cellsZnrowsrA   Z	row_sliceZrow_lenr#   )r   Zpath_xlsr   r   r   Zbook_xlsZ	book_xlsxr   Zsheet_indexZ	sheet_xlsZ
sheet_xlsxZcrangeZrloZrhiZcloZchirowr   )r   r   r   r   xls_to_xlsx  s2    
 
z!CmfPluginConvertMixin.xls_to_xlsx)dataoutput_pathr   r   c                 C   s   t | || dS )u(  
        Конвертация данных в PDF через libreoffice
        :param data: Данные файла в виде байт
        :param output_path: Путь сохранения итогового pdf файла
        :param suffix: Расширение файла
        N)r   
obj_to_pdf)r   r   r   r   r   r   r   I  s    z CmfPluginConvertMixin.obj_to_pdfrb   )r   r   mimetyper   c              
   C   sZ  ddl }ddlm} | ||d|}| @}t|d }t|d}	|	| | t	|}
W 5 Q R X W 5 Q R X |j
|
ddd	d
}|dd}||}|d}|rR|d}|rR| }|jddD ]}|dd}d}|d D ]T}|d| }|||d d d }|||d d }|||| 7 }q||  |d< qt	|S )u  
        Конвертация данных в HTML через libreoffice

        :param data: Данные файла источника в виде байт
        :param suffix: Расширение файла источника

        :return: Строка HTML
        r   Nr,   r   z	file.htmlr   ignore)errors u   �u   rb   r/   r0   TrT   r   rn   {rq   })rs   r5   r-   r   r   r   r   r   get_encoding_typerJ   r+   r>   rB   Zget_textrD   rt   )r   r   r   r   rs   r-   Z
bytes_htmlr   Zfull_path_htmlr   r   r
   rO   r/   r0   Z
style_textr   rP   Zstyle_classZ	class_tagZstart_pos_classZstyle_startZ	style_endr   r   r   obj_to_htmlS  s4    	

"

z!CmfPluginConvertMixin.obj_to_html)r   r   	to_formatr   r   c              
   C   s\   zt | |||}W nB tk
rV } z$t|drBtddd n|W 5 d}~X Y nX |S )u*  
        Конвертация данных в HTML через libreoffice
        :param data: Данные файла в виде байт
        :param suffix: Расширение файла
        :param to_format: Формат файла который хотим получить
        u8   Не удалось конвертировать в htmlua   Импорт документов данного формата не поддерживаетсяT)abortN)r   r   rK   rJ   ry   r   )r   r   r  r   Zconverted_dataerrr   r   r   r   {  s    z#CmfPluginConvertMixin.obj_to_format)	path_filer   c              
   C   s   ddl m} | }t| d8}|D ]$}|| |jr"|jdr" qHq"|  W 5 Q R X |jd}|sddddd	d
dg}|D ]d}zFtj| d|d,}|	  |
d |}W 5 Q R  W  qW 5 Q R X W q tk
r   d}Y qX q|S )u   
        Определяем кодировку файла

        :param path_file: Путь к файлу
        :return: Кодировка файла
        r   )UniversalDetectorrl   r   r   zwindows-1251zwindows-1250zwindows-1252asciiz
iso-8859-1latin1r   r   )Zchardet.universaldetectorr  r   ZfeedZdoner   rt   closer!   	readlinesr$   UnicodeDecodeError)r  r  Zdetectorr   liner   	encodingsZformat_encodingr   r   r   r    s*    

z'CmfPluginConvertMixin.get_encoding_type)rb   )rb   )__name__
__module____qualname____doc__rJ   r   r   r   r(   staticmethodr   r   rE   rF   rG   rH   rI   r    r   r   r   r   r   r   r   r   r   r  r   r  r   r   r   r   r	      sF   ;]P	[		+	(r	   )r*   r;   r!   pathlibr   rs   r   typingr   Zurllibr   r   r   r   Zcmf.includeZrdiskr   rv   r   r   r	   r   r   r   r   <module>   s   