U
    
ci                     @   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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+d,Zddd-d.Ze	eeedd/d0d1Zd<eeeed3d4d5Ze	d=eeeeed6d7d8Ze	eed9d:d;ZdS )>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_img_handle_html_table_handle_html_layout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   sH    








z"CmfPluginConvertMixin._handle_htmlN)r   c                 C   s  ddl m} ddl}| }|dD ]}|jdd}|jdd}|jd}|s^q*|dtj	 r|
dtj	 d	}|d
rBt|}	tjjdd|	gdgd}
|
rt|
j}nt|	
dtj}| rBt|d4}| | }d|j
dd	 d| |jd< W 5 Q R X |r.|sB||}|j\}}|drTzt|}|jdkr||dd d }|dkrd}| |j}d| d| |jd< |r|st| dt dd| }t|d}||j W 5 Q R X ||}|j\}}W nD tk
rR } z$t !d t"d|  W Y q*W 5 d}~X Y nX t#d	$dd t%|D }t#d	$d d t%|D }|| }|t& }|| }|t'ks|dkr|rt'| nd}t'}||9 }| d!|jd< | d!|jd< q*W 5 Q R X dS )"u   
        Функция заменяет адрес картинки на base64

        :param bs4.BeautifulSoup soup: Объект библиотеки
        r   ImageNimgwidthheightsrczhttps:// /url==r   filterZfields/files/rbdata:image/.z;base64,http      )ZpngZbmpZgifZtiffZtifZjpegZjpgz/imgz%Y%m%d-%H%M%Szwb+uL   Не удалось скачать изображения документаuN   Не удалось скачать изображения документа: c                 s   s   | ]}|  r|V  qd S Nisdigit.0elr   r   r   	<genexpr>   s      z9CmfPluginConvertMixin._handle_html_img.<locals>.<genexpr>c                 s   s   | ]}|  r|V  qd S re   rf   rh   r   r   r   rk      s      px)(PILrS   tempfiler   rD   attrsget
startswithconfigZAPP_FQDNr>   r   unquotemodelsCmfAttachmentr   full_path_file
UPLOAD_DIRexistsopenr   readsuffixsizerequestsstatus_coderfindr)   r   ZnowwriterI   rJ   rK   	cmf_alertfloatjoinrH   SCALE_A4A4_PAGE_WIDTH_PX)r   rM   rS   rn   tmp_dirrP   rU   rV   rW   url_path
attachmentZattach_pathZattachment_byterO   rT   resZextension_imgZ	file_pathfpewidth_valueheight_valueproportion_ratiocoefficientr   r   r   rE      sl    

*





z&CmfPluginConvertMixin._handle_html_imgc              	   C   s  |  dD ] }i }|dddD ]&}|r&|d\}}| || < q&|dsh|dd|d< |dszd	|d< |d
sd	|d
< |ds|dd	|d< i }|jdk	rTt|jjddD ]\}}|jdddD ]d}d|kr|d\}}|dr&t	d t
| dd }	nt
| ddt }	|	||< qq|j  | dD ]}
d}|
 dD ]}i }|dddD ]*}|r|d\}}| || < q|s|ddrt	d t
|d dd }nt
|d ddt }nX|| }|d }rft|d t|| D ]}||| 7 }qD|t|7 }n|d7 }| dD ]|}t
|jd dd}t
|jd dd}||krx|| }|d }| d|jd< ||  d|jd< qx| d|d< qrq^q
dS )u  
        Функция добавляет стиль для таблиц
        Для конвертирования таблиц в LibreOffice используем inline style

        :param bs4.BeautifulSoup soup: Объект библиотеки
        tabler0   rX   ;:rU   100%Zcellpadding1ZcellspacingZborderNrd   )start%d   rl   trtdcolspanrT   rV   g)\(@)rD   rp   splitstripZcolgroup	enumeratechildrenro   endswithr   r   r>   r   rC   rangeint)rM   r   Zstyle_tableparamsnamevalueZ
cols_widthZcol_numcolZwidth_pxr   r   Ztd_styleZtd_widthr   irT   Z	img_widthZ
img_heightr   r   r   r   rF      sh    	




$ 
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   TagZdivzdata-layout-sectiontruer   rU   r   r   c                    s   g | ]}t | r|qS r   )
isinstancerh   r   r   r   
<listcomp>,  s     
 z=CmfPluginConvertMixin._handle_html_layout.<locals>.<listcomp>r      r   zdata-column-widthr   N)
r5   r   rD   r   r?   r   lenroundrp   rA   )rM   Zlayoutr   columnsZ	nums_colsZwidth_columncolumnr   r   r   rG     s    
z)CmfPluginConvertMixin._handle_html_layout)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   )rS   UnidentifiedImageErrorr,   azcmf-fileclassrX   file)objr1   ZhrefrT   Zimager0   titler   rU   rV   rW   z
data:image,r`   z;base64Zfile_ra   wbr^   rZ   r[   r   r\   i  c                 s   s   | ]}|  r|V  qd S re   rf   rh   r   r   r   rk   p  s      z:CmfPluginConvertMixin._handle_view_html.<locals>.<genexpr>rb   zcommon/static/file-outline.png?rc   Zname_rd   c                 s   s   | ]}|  r|V  qd S re   rf   rh   r   r   r   rk     s      )'rm   rS   r   r5   r-   rD   ro   rp   rA   dictrC   r   rq   r   r>   r   ry   r   r*   Z	b64decoderH   r   rs   rt   ru   rr   rw   rv   rx   r|   r   r   ZPROJECT_DIRr   r   r}   r~   Zresolver)   )!r
   r   rS   r   r-   rM   filesr   indexZ_filerU   rV   Zfull_urlZtype_imgZb64dataZ	name_fileZfile_imgr   r   Zattachment_pathrT   Zwidth_defaultr   Zpath_defaultZend_nameZfile_extensionZresponser   filepathr   Z	width_newr   r   r   r   r   r    5  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NotoSansrX   r   r   rU   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findAllro   r   Z
write_htmlr    Zprettifyr   output)r   r
   r   r   r-   r   Z	path_fontZpdfrM   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_htmlr_   N)Zmammothr   r   r   rx   ry   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   rx   ry   r   rz   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   rR   N)rm   rS   ry   r#   )r   r   r   rS   rT   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   rd   )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_value  s    

z?CmfPluginConvertMixin.xls_to_xlsx.<locals>._get_xlrd_cell_valuec                 3   s   | ]} |V  qd S re   r   )ri   r   )r   r   r   rk     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     s    z CmfPluginConvertMixin.obj_to_pdfrX   )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   rX   r/   r0   T)class_r   ra   {rd   })rn   r5   r-   r   r   r   ry   r   get_encoding_typerH   r+   r>   rB   Zget_textrD   rp   )r   r   r{   r   rn   r-   Z
bytes_htmlr   Zfull_path_htmlr   r   r
   rM   r/   r0   Z
style_texttagrN   Zstyle_classZ	class_tagZstart_pos_classZstyle_startZ	style_endr   r   r   obj_to_html  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   rI   rH   rq   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   )UniversalDetectorr_   r   r   zwindows-1251zwindows-1250zwindows-1252asciiz
iso-8859-1latin1r   r   )Zchardet.universaldetectorr   ry   ZfeedZdoner   rp   closer!   	readlinesr$   UnicodeDecodeError)r   r   Zdetectorr   liner   	encodingsZformat_encodingr   r   r   r   S  s*    

z'CmfPluginConvertMixin.get_encoding_type)rX   )rX   )__name__
__module____qualname____doc__rH   r   r   r   r(   staticmethodr   r   rE   rF   rG   r    r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r	      s>   9HJ[		+	(r	   )r*   r;   r!   pathlibr   rn   r   typingr   Zurllibr   r   r   r}   Zcmf.includeZrdiskr   ZWEB_PAGE_WIDTH_PXr   r   r	   r   r   r   r   <module>   s   