
    fi\                     v    d dl Z d dlZd dlmZ d dlT d dlmZ d dlmZ d dl	m
Z
  G d de
j        e          ZdS )	    N)Path)*)cmf_hashlib)CmfPluginConvertMixin)cmf_attachmentc                       e Zd Zej        j        j        dz   Zej        j	        e
j	        z   g dz   Z	 fdZdefdZdefdZd Zd	efd
Zd	edefdZd Zd Z fdZd Zd Zd Zd Z fdZe edd          d                         Zed             Z dddZ!edefd            Z"dddddde#fdZ$d  Z%d! Z&d8d"Z'ede(fd#            Z)edefd$            Z*d% Z+dd& fd'
Z,d( Z- fd)Z.d9d*Z/ fd+Z0 fd,Z1 fd-Z2d. Z3d/ Z4d0 Z5d1 Z6 fd2Z7 fd3Z8e9d:d4            Z:e eddd56          d7                         Z; xZ<S );CmfAttachment)file_exists)upsertget_fullviewgen_url_for_webdavget_versionsremove_versionget_url_fileget_local_urlmark_viewed
public_getpublic_createpublic_get_rfilepublic_get_versions
api_create
api_update
api_deletec                 H    d | _          t                      j        |i | d S N)content_updatedsuper__init__selfargskwargs	__class__s      (./modules/files/models/cmf_attachment.pyr   zCmfAttachment.__init__!   s-    #$)&)))))    returnc                     |                      ddg           |                                 }|st          d           g S |                                S )Nst_sizecmf_modified_at   DEV: Не найден Rfile, вероятно не найден файл в хранилище /files для текущего CmfAttachment)load_fields	get_rfile	cmf_alertr   r    rfiles     r$   r   zCmfAttachment.get_versions%   se    )%67888   	  e  f  f  fI!!###r%   versionc                n    |                                  }|st          d           d S  |j        |d|i|S )Nr*   r0   )r,   r-   r   )r    r0   r!   r"   r/   s        r$   r   zCmfAttachment.remove_version/   sV       	  e  f  f  f4#u#TE7EfEEEr%   c                 r    |                                  }|st          d           d S  |j        |g|R i |S )Nr*   )r,   r-   r   )r    editorr!   r"   r/   s        r$   r   z CmfAttachment.gen_url_for_webdav7   s\       	  e  f  f  f4'u'@@@@@@@r%   os_typec                 |    |                                  }|st          d           d S |                    |          S Nr*   )r4   )r,   r-   r   r    r4   r/   s      r$   r   zCmfAttachment.get_url_file?   sP       	  e  f  f  f4!!'!222r%   c                 |    |                                  }|st          d           d S |                    |          S r6   )r,   r-   r   r7   s      r$   r   zCmfAttachment.get_local_urlG   sP       	  e  f  f  f4""7"333r%   c                     | j         j        sd S t          j                            | j         j                  d         }d}t          |          |k    r	|| _        d S d S )N       )	file_name
is_changedospathsplitextvaluelen	file_type)r    	extensionext_max_lengths      r$   _calc_file_typezCmfAttachment._calc_file_typeO   s\    ~( 	FG$$T^%9::1=	y>>^++&DNNN ,+r%   c                     t          | j        j        t          j                  r+|                     dg           | j        j        rd| _        d S d S d S )Nzparent.privateT)
isinstanceparentrA   models
CmfCommentr+   privater    s    r$   _calc_privatezCmfAttachment._calc_privateX   s`    dk'):;; 	$./000{" $#	$ 	$$ $r%   c                 N    t                                                      g dz   S )N)urlurl_previewurl_preview_imgrI   embedded)r   save_preload_fields)r    r#   s    r$   rT   z!CmfAttachment.save_preload_fields^   s%    ww**,,/n/n/nnnr%   c                 >   | j                                          | j         sd S t          j                            t
          j        | j                                                   }t          j                            |          st          	                    |           |S r   )
rI   loadr>   r?   joinconfig
UPLOAD_DIRget_files_direxistsmakedirs)r    
upload_dirs     r$   r]   zCmfAttachment.upload_dira   sy    { 	FW\\&"3T[5N5N5P5PQQ
w~~j)) 	$KK
###r%   c                     t           j        j        j                                        }|                    | j                  }|j        r|j        | _        d S d| _        d S )Nr   )	rJ   CmfRFiledpdata_driverget_rdr,   
_file_namer[   r(   r    rdiskr/   s      r$   _calc_st_sizezCmfAttachment._calc_st_sizej   sP    ".557700< 	 =DLLLDLLLr%   c                     t           j        j        j                                        }|                    | j                  }|j        r#t           j        	                    | dd           d S d S )N
attachment
after_save)
rJ   r_   r`   ra   rb   r,   rc   r[   CmfAutomationCrudTrigger	crud_hookrd   s      r$   _call_automation_hookz#CmfAttachment._call_automation_hookr   sf    ".557700< 	X+55dL,WWWWW	X 	Xr%   c                 v    | j         r/t                              | j                  }|r|j        | _        d S d S d S r   )is_newAPPget_cache_project
project_iddefault_attach_full_search_typefull_search_type)r    projects     r$   _calc_full_search_typez$CmfAttachment._calc_full_search_typey   sT    ; 	P++DO<<G P(/(O%%%	P 	PP Pr%   c                    |                                   |                                  |                                  |                                  |                                   t                      j        |i |}t          j        	                    |            | 
                                 | j        r&t          t          j        j        | j        g           |S )N)r!   )	_calc_urlrF   rf   rN   ru   r   saverJ   CmfBackbonePeerobj_after_save_hookrl   rn   schedule_deferred_jobr	   extract_text_from_attachid)r    r!   r"   resr#   s       r$   rx   zCmfAttachment.save   s    ##%%%egglD+F++224888""$$$; 	a!&"6"OW[W^V_````
r%   T)	only_once
system_jobc                 |   dd l }ddlm} t          j                            | g d          }d}d}t          |j                  }|j        dv rEd}d	}t           ||j	        j
                            d
t          j                                      }n|j        dv rnd S t          ||          5 }|r|                                }n8|                    |          }	d}|	j        D ]}
||
                                z  }d d d            n# 1 swxY w Y   |d d         |_        |                    d           d S )Nr   )unquote)rQ   rC   full_file_pathr}   fieldsTr)z.docz.docxz.dotz.dotxz.docmz.dotmz.rtfz.pdfz.xpsz.fdfz.xlsz.xlsxz.xlsmz.pptz.pptxz.odpz.odsFrbz/files/)z.txtz.csvz.mdz.html i )	only_data)PyPDF2urllib.parser   rJ   r	   getr   full_path_filerC   rQ   rA   replacerX   rY   openread	PdfReaderpagesextract_texttextrx   )	attach_idr   r   attach
force_readmode	file_pathfiler   readerpages              r$   r|   z&CmfAttachment.extract_text_from_attach   s    	((((((%))Y?m?m?m)nn 
.//	  A A A JDWWV%7%=%E%EiQWQb%c%cddeeII!AAA F)T"" 	0d 0yy{{))$//"L 0 0DD--///DD	0 	0 	0 	0 	0 	0 	0 	0 	0 	0 	0 	0 	0 	0 	0 7F7md#####s   0ADDDc                 <    |                                   | j         S r   )r]   r<   rM   s    r$   r   zCmfAttachment.file_path   s!     //##5T^555r%   Nr   c                |   | j         j        s| j        j        sd S t          j                            dt          j        	                    | j
                            | _        t          j                            | j         dd          | _        t          j                            | j         dd          | _        d S )Nz/filesz.metazpreview.pdfzthumbnail.jpg)r<   r=   rP   is_nullr>   r?   rW   urllibparsequoterc   rQ   rR   )r    r   r!   r"   s       r$   rw   zCmfAttachment._calc_url   s    ) 	TX-= 	F7<<&,*<*<T_*M*MNN7<<48(:(:(:MJJ!w||tx,>,>,>PPr%   c                 ^    t          t          t          j        | j        z                       S )u<    Полный фактический путь к файлу )strr   rX   rY   rc   rM   s    r$   r   zCmfAttachment.full_path_file   s$     4)DO;<<===r%   Fbackupsmart_backupmake_preview
mark_dirtycontentc                2   t           j        j        j                                        }|                    | j                  }	|	                    ddd           |	                    |||||           d| _	        | 
                                 d| _	        dS )u    Загрузка файла FT)is_direxist_okparentsr   N)rJ   r_   r`   ra   rb   r,   rc   createwriter   rx   )
r    r   r   r   r   r   r!   r"   re   r/   s
             r$   upload_filezCmfAttachment.upload_file   s     ".557700ED$???%%! 	 	
 	
 	
  $		$r%   c                     |                                  }|r|                                 dS t          d|  dd           dS )u   Делаем отметку в мете что эту версию файла менять нельзя поскольку она опубликована
        uW   При обработке документа обнаружен пустой файл: u   . Возможно, произошла ошибка при загрузке файла. Пожалуйста, загрузите файл повторно.FabortN)r,   
do_publishr-   r.   s     r$   r   zCmfAttachment.do_publish   s}        	`  Rpt  R  R  R  Z_  `  `  `  `  `  `r%   c                     |                      d          }|si }t          j        j        |d<   t          j        j        |d<    |j        |i | d| _        |                                  d| _        d S )NT)r   task_attachment_max_sizedocument_attachment_max_sizeF)r,   gglobal_settingsr   r   stream_writer   rx   r    r!   r"   r/   s       r$   upload_stream_filez CmfAttachment.upload_stream_file   s    d++ 	F-.->-W)*121B1_-.D+F+++#		$r%   c              +     K   |                                  }|                    |          }|r	|d         }n!|                      dg          j        j        }t	          |d          5 }|V  d d d            d S # 1 swxY w Y   d S )Nabspathr   r   )r,   get_versionr   rA   r   )r    r0   r"   r/   rfile_versionr   r   s          r$   get_contentzCmfAttachment.get_content   s        ))'22 	G#I.GGnnYKn88@FG'4   	DJJJ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	s   (A::A>A>c                     t           j        j        j                                        }|                    | j                  }|j        S r   )rJ   r_   r`   ra   rb   r,   rc   r[   rd   s      r$   r
   zCmfAttachment.file_exists   s6    ".557700|r%   c                     |                      ddg           | j        rAt          j                            | j                                        | j        j                  S t          dd           dS )uT    Имя файла вложения в зависимости от родителя rI   r<   u   Вложение должно быть привязано к объекту, нельзя сохранять в корень диска.Tr   N)	r+   rI   r>   r?   rW   rZ   r<   rA   r-   rM   s    r$   rc   zCmfAttachment._file_name  s     	(K0111; 	o7<< 9 9 ; ;T^=QRRR  b  jn  o  o  o  o  o  or%   c                 D    |                                  } |j        |i |S r   )r,   r   r   s       r$   r   zCmfAttachment.get_fullview  s)      ""D3F333r%   )forcec                     t                      j        |d|i|}|                                  t          j                            |            |S )Nr   )r   deletedelete_filerJ   ry   obj_after_delete_hook)r    r   r!   r"   r~   r#   s        r$   r   zCmfAttachment.delete  sP    eggnd:%:6::44T:::
r%   c                     | j         rst                              d          s!t          j                            | dd           |                                 }|r$|                    | j        j	                   d S d S d S )NTEXKOM_db_deletedelete_attachmentri   )prefix)
rc   r"   r   rJ   rj   rk   r,   move_to_trashcoderA   r.   s     r$   r   zCmfAttachment.delete_file  s    ? 	<::011 c/99$@SUabbbNN$$E <##49?#;;;;;	< 	<
< <r%   c                      t                      j        di |}t          j                            | j        j         d| j        j         | j                   |S )N_)name_before
target_dir )	r   restorerJ   r_   restore_from_trashr   rA   r<   rc   )r    r"   r~   r#   s      r$   r   zCmfAttachment.restore   sY    eggo''''**$)/7b7bDNL`7b7boso~*
r%   c                 t   dd l }t          j                            | j        |          }|s|rt                              | j        d          }| j        |_        t          j                            |j                            |j        j	                  d          |_
        |                                 |S )Nr   r   F)namer   T)r}   mkdir)r>   rJ   r_   r   rc   r<   r}   r?   dirnamerA   rI   rx   )r    r   r   _kwargsr>   r~   s         r$   r,   zCmfAttachment.get_rfile%  s    			o!!T_V!DD 	v 	//t~e/DDC_CF,,0M0MUY,ZZCJHHJJJ
r%   c                     | j         r?t                              | j                   x}r|                    d| j                   d S t                                                       d S )NzPPP-ATT-CREATEobj)rq   ro   rp   check_project_role_accessrI   r   check_edit_permr    rt   r#   s     r$   r   zCmfAttachment.check_edit_perm/  sg    ? 	&3+@+@+Q+Q Q 	&--.>DK-PPPPPGG##%%%%%r%   c                    |                      g d           | j        rt                              | j                  }t          j        | j        k    rL	 |                    d| j                   d S # t          $ r  |                    d| j                   Y d S w xY w|                    d| j                   d S t                                                       d S )N)rq   rI   	cmf_ownerzPPP-ATT-DELETE-ALLr   zPPP-ATT-DELETE-OWN)r+   rq   ro   rp   r   current_userr   r   rI   CmfPermissionErrorr   check_delete_permr   s     r$   r   zCmfAttachment.check_delete_perm6  s    >>>???? 
	(++DO<<G~//]556JPTP[5\\\\\) ] ] ]556JPTP[5\\\\\\] 112FDK1XXXXXGG%%'''''s   A3 3&BBc                     |                                   |                                  |                                   t                      j        |i | d S r   )rw   rF   rf   r   _save_importr   s      r$   r   zCmfAttachment._save_importE  sY    d-f-----r%   c                     dS )u^  
            TODO: Сделать data-tag
            <div
                data-need-rebuild="1"
                data-macros="wiki-attachment"
                data-attach-id="CmfAttachment:2c767cfe-dbe6-11f0-965f-0242ac120003"
                data-attach-name="!!! escape"
                data-attach-url=""
                data-attach-url-preview=""
                data-attach-url-preview-img=""
                data-attach-cmf-created-at="2025-12-19T09:18:16.291725+00:00"
            >
                <span>Вложение: <a download=abs_url>Имя файла</a><span>
            </div>
        Nr   rM   s    r$   create_preview_tag_todoz%CmfAttachment.create_preview_tag_todoK  s      r%   c                     ddl m} d}|                     g d            | |                    dd          j        d	i | j        | j        | j        | j        | j	        | j
        j        dd          }|j        S )
Nr   )BeautifulSoupa  
        <div contenteditable="false" class="app-tinymce-card-preview app-tinymce-is-preview"
            data-attach-id="{id}" data-mce-contenteditable="false"
            bis_skin_checked="1"><a class="app-tinymce-href-preview app-tinymce-is-preview"
                cmf_converted="true"
                title="{title}"
                rel="{urlPreview}"
                download="{url}">
                <span class="app-tinymce-img-preview-block app-tinymce-is-preview"> <span
                        class="app-tinymce-img-preview-size app-tinymce-is-preview"> <img
                            class="app-tinymce-img-preview app-tinymce-is-preview"
                            src="{urlPreviewImg}"
                            alt="attachment"
                            data-mce-src="{urlPreviewImg}">
                    </span> </span> <span class="app-tinymce-file-preview-block app-tinymce-is-preview"> <span
                        class="app-tinymce-file-name-block app-tinymce-is-preview"> <span
                            class="app-tinymce-file-name-view app-tinymce-is-preview">{title}</span>
                        </span> <span
                        class="app-tinymce-file-create-view app-tinymce-is-preview display-contents">{createDate}</span> <svg class="remove-file-icon" style="width: 24px; height: 24px;" viewBox="0 0 24 24"
                        data-mce-style="width: 24px; height: 24px;">
                        <path style="pointer-events: none;" fill="#e8e8e8"
                            d="M19,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5A2,2 0 0,0 19,3M19,19H5V5H19V19M17,8.4L13.4,12L17,15.6L15.6,17L12,13.4L8.4,17L7,15.6L10.6,12L7,8.4L8.4,7L12,10.6L15.6,7L17,8.4Z"
                            data-mce-style="pointer-events: none;"></path>
                    </svg> </span> </a>
            <div contenteditable="false" class="app-tinymce-preview-actions" data-mce-contenteditable="false"
                bis_skin_checked="1">
                <div data-obj-id="{id}" bis_skin_checked="1"><svg
                        class="preview-action edit-preview" viewBox="0 0 24 24"
                        style="width: 18px; height: 18px; color: #444444;"
                        data-mce-style="width: 18px; height: 18px; color: #444444;">
                        <path _ngcontent-mjc-c10="" fill="#444"
                            d="M20.71,7.04C21.1,6.65 21.1,6 20.71,5.63L18.37,3.29C18,2.9 17.35,2.9 16.96,3.29L15.12,5.12L18.87,8.87M3,17.25V21H6.75L17.81,9.93L14.06,6.18L3,17.25Z">
                        </path>
                    </svg><br></div>
                <div bis_skin_checked="1"><svg class="preview-action show-preview" viewBox="0 0 24 24"
                        style="width: 18px; height: 18px; color: #202020;"
                        data-mce-style="width: 18px; height: 18px; color: #202020;">
                        <path _ngcontent-chu-c10="" fill="#202020"
                            d="M12,9A3,3 0 0,1 15,12A3,3 0 0,1 12,15A3,3 0 0,1 9,12A3,3 0 0,1 12,9M12,4.5C17,4.5 21.27,7.61 23,12C21.27,16.39 17,19.5 12,19.5C7,19.5 2.73,16.39 1,12C2.73,7.61 7,4.5 12,4.5M3.18,12C4.83,15.36 8.24,17.5 12,17.5C15.76,17.5 19.17,15.36 20.82,12C19.17,8.64 15.76,6.5 12,6.5C8.24,6.5 4.83,8.64 3.18,12Z">
                        </path>
                        <defs _ngcontent-chu-c10="">
                            <linearGradient _ngcontent-chu-c10="" id="MyGradient" x1="0" x2="0" y1="0" y2="1">
                                <stop _ngcontent-chu-c10="" offset="20%" stop-color="#ffd19e"></stop>
                                <stop _ngcontent-chu-c10="" offset="80%" stop-color="#ffeec2"></stop>
                            </linearGradient>
                        </defs>
                    </svg><br></div>
                <div bis_skin_checked="1"><svg class="preview-action download-preview" viewBox="0 0 24 24"
                        style="width: 18px; height: 18px; color: #202020;"
                        data-mce-style="width: 18px; height: 18px; color: #202020;">
                        <path _ngcontent-chu-c10="" fill="#202020" d="M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z"></path>
                    </svg><br></div>
            </div>
        </div>
        )rR   rQ   rP   cmf_created_atr<   
r   )titler}   urlPreviewImg
urlPreviewrP   
createDatezhtml.parserr   )bs4r   r+   r   formatr<   r}   rR   rQ   rP   r   json
currentTag)r    r   TAG_TMPLss       r$   create_preview_tagz CmfAttachment.create_preview_tag\  s    %%%%%%6n 	aaabbbM;(**444; & &EIW484H151A*.(151D1I?% ?% & & (56 6 |r%   c                 N    | j         rt          j        j        | dg|R i | d S d S )Nattachment_created)rn   rJ   CmfEventdo_eventr    r!   r"   s      r$   _do_event_savezCmfAttachment._do_event_save  sE    ; 	RO$T+?Q$QQQ&QQQQQ	R 	Rr%   c                 <    t          j        j        | dg|R i | d S )Nattachment_deleted)rJ   r   r   r   s      r$   _do_event_deletedzCmfAttachment._do_event_deleted  s.     ';MdMMMfMMMMMr%   c                    t          t                                                                }|                     dg           | j        r1| j                                        D ]}|                    |           t          |          S )NrI   )setr   
get_ownersr+   rI   addlist)r    r!   r"   ownersparent_ownerr#   s        r$   r  zCmfAttachment.get_owners  s     UWW''))**($$$; 	) $ 6 6 8 8 ) )

<((((F||r%   c                      t                      j        |i |}t          | j        d          5 }|                    |           d d d            d S # 1 swxY w Y   d S )Nr   )r   copyr   r   r   )r    r!   r"   obj_copyfr#   s        r$   r  zCmfAttachment.copy  s    577<000$%t,, 	+''***	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+s   AAAc                    |r|t           j        k    rLt           j        st           j        rdS |rt           j        j        |k    rdS t           j        }t           j        }nd}t                              |dg d          }|j        |j	        k    rdS |j
        sdS t           j        dk    rdS |j        s5|j        j        dk    r%|j        r|                    |j        d	          rdS |j        D ]u}|j        d
k    r$|j        r|                    |j        |          c S |j        |j        k    r dS |du r!t$          j                            |d          }|j        |v r dS vdS )u  
        !!! Копия метода в CmfComment
        https://bcrm.carbonsoft.ru/project/Document/DOC-014685#spec-014684b
        Проверяем видимость аттача для g.current_person (или check_for_person)
        При использовании check_for_user метод можт выполняться долго! Обязательно перед вызовом
        проверяйте, что аттач имеет флаг private
        T.)
spectatorscmf_owner_idrL   rt   zproject.logic_prefix)simpler   apiFzproject.servicedeskzsdesk-agent:default)rt   	role_codeCmfProjectRole)id_onlyN)r   r   disable_permissionsacl_admin_modecurrent_personr}   current_person__member_ofcmfutilget_obj_by_idr  rL   	api_scoper  rt   logic_prefix
user_localin_project_role
class_namerJ   CmfAccessListsubject_full_group_list)clsattachment_idowner_idcheck_for_usercheck_for_user__member_ofr   subjects          r$   check_visibilityzCmfAttachment.check_visibility  s     
	,1>!A!A$ (8 t A,/8;;t^N()(C%% ),%&&$___ ' a a  3334~ 	4 ;%5  	N/3HHH"- I"226>Uj2kk I
 4( 	 	G!%555&.5%55fngNNNNN GJ..tt )C//,2,@,X,XYgqu,X,v,v)z666tt 7	 	r%   z	@minutely)r   r   schedulec                     t           j        j        j                                        } | j                            t          j                  s'| j        	                    t          j        dd           | j        
                    t          j                  D ]}	 |                    d          d         }t                              |          }|                    |           t                       | j                            |           v# t"          $ rD}t%                       t&                              d| d| t*          j                   Y d }~d }~ww xY wd S )NT)r   r   /u4   Не удалось обработать файлы z: )level)rJ   r_   r`   ra   rb   io	io_existsrX   
DIRTY_PATHio_mkdir
io_iterdirsplitr  get_model_by_idprocess_dirty_attach
cmf_commit	io_rmtree	Exceptioncmf_rollbackr   debugloggingERROR)re   
dirty_pathobj_idmodeles        r$   cron_check_dirtyzCmfAttachment.cron_check_dirty  sW    ".5577x!!&"344 	NHf/MMM(--f.?@@ 		w 		wJw#))#..r2//77**6222"":.... w w w`z``]^``hohuvvvvvvvvw		w 		ws   A2D
E:EEr   )NF)NN)=__name__
__module____qualname__cmfrJ   	CmfEntityui_meta_skipr   r	   api_methodsr   r   r	  r   intr   r   r   r   r   rF   rN   rT   r]   rf   rl   ru   rx   staticmethodcmf_deferred_jobr|   propertyr   rw   r   bytesr   r   r   r   boolr
   rc   r   r   r   r   r,   r   r   r   r   r   r  r  r  r  classmethodr+  rD  __classcell__)r#   s   @r$   r	   r	      s       :'47GGL .:

+,
 
 

K(* * * * *$d $ $ $ $FS F F F FA A A3C 3 3 3 34S 4S 4 4 4 4' ' '$ $ $o o o o o    X X XP P P      666"$ "$ 76 \"$H 6 6 X6 '+ Q Q Q Q Q > > > > X> % % %% % % %2` ` `	% 	% 	%    T    X
 oC o o o Xo4 4 4 #(       < < <    
   & & & & &( ( ( ( (. . . . .  "B B BHR R RN N N    + + + + +
 5 5 5 [5l LLLw w ML \w w w w wr%   r	   )mathr   pathlibr   cmf.includecmf.utilr   &common.models.cmf_plugin_convert_mixinr   modules.files.fieldsr   r	   r   r%   r$   <module>rZ     s                            H H H H H H / / / / / /sw sw sw sw swN02G sw sw sw sw swr%   