U
    %ðÌjÖ   ã                Y   @   sÜ  d dl Z de jd< d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
Z
d dlZd dlZd dlZd dlZd dlZd dlmZ d dlmZmZmZmZ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 m!Z! d dl"m#Z# d dl$m%Z% d dl&m'Z' d dl(m)Z) ej*ej+dej,ddd�e -ej.¡gd� e!ƒ  zd dl/Z/W n e0k
�rj   dZ/Y nX zd dl1m2Z2 W n e0k
�r–   dZ2Y nX e  3dd¡ 4¡  5dd¡Z6e  3dd¡ 4¡  5dd¡Z7e  3dd¡ 4¡  5dd¡Z8e  3dd¡ 4¡ Z9e  3dd¡ 4¡  5dd¡Z:e;e  3dd¡ƒZ<e  3dd¡ 4¡  5dd¡Z=e  3dd¡ 4¡  5dd¡Z>e  3d d!¡ ?¡ d!kZ@e  3d"d¡ 4¡ ZAe  3d#d$¡ 4¡ ZBe  3d%d&¡ 4¡ ZCe;e  3d'd(¡ƒZDe;e  3d)d*¡ƒZEe;e  3d+d(¡ƒZFe  3d,d-¡ ?¡ d!kZGe  3d.d-¡ ?¡ d!kZHe  3d/d0¡ 4¡ ZIe  3d1d2¡ 4¡ ZJe  3d3d4¡ 4¡ ZKeeLƒ M¡ jNZOe  3d5d6¡ 4¡ ZPeQeOeP ƒZReSe  3d7d8¡ƒZTd9d:d;d<d=d>d?d@dAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd[d\d]d^d_d`dadbdch+ZUdddedfdgdhdidjdkdldmdndodpdqdrdsdtdudvdwdxdydzd{d|d}d~dd€d�d‚dƒd„d…d†d‡dˆd‰dŠd‹dŒd�dŽd�d�d‘d’d“d”d•d–d—d˜d™dšd9d›dœd�dždŸd d¡d¢d£d¤d¥d¦d§d¨d©dªd«d¬d­d®d¯d°d±d²dOd³d´dµd¶d·d¸d¹dºhYZVdZWz e/dk�rveXd»ƒ‚e/ Yd¼¡ZWW n4 eZk
�r¶ Z[ ze \d½e[› �¡ W 5 dZ[[[X Y nX dZ]e2�rìze2d¾d¿�Z]W n eZk
�rê   dZ]Y nX eeQ eQdÀœdÁdÂ„Z^eQe_dÃœdÄdÅ„Z`eaeea dÆœdÇdÈ„ZbeaeQdÉœdÊdË„Zceae_dÌœdÍdÎ„Zd�d5eae;eQdÐœdÑdÒ„ZeeQeQdÓœdÔdÕ„ZfeaeeQ dÌœdÖd×„ZgeQeee;eQf  dØœdÙdÚ„ZhdÛdÜdÝdÞdßdàdádâdãdädådædçdèdédêdëdìdídîdïdðdñdòdóhZidôdõdöd÷dødùdúdûdüdýdþdÿ�d �d�d�d�d�d�d�dhZjeQeeQ dØœ�d�d	„ZkeQeQeQ�d
œ�d�d„ZleQeee;e;f  dØœ�d�d„Zme;eee;e;f  e_�dœ�d�d„Zn�d6eQe;eeQ �dœ�d�d„Zoe p�d¡Zqe p�d¡Zre p�d¡ZseQe_�dœ�d�d„ZteQeeQ e_�dœ�d�d„ZueQeQeee;e;f  eeQee f �dœ�d �d!„ZveQee dØœ�d"�d#„ZweQeQ�d$œ�d%�d&„Zx�d7eQeQeQe_ee_eQeQf �d(œ�d)�d*„ZyeaeQeSeea �d+œ�d,�d-„Zz�d8�d.�d/„Z{�d0�d1„ Z|�d2�d3„ Z}e~�d4k�rØe}ƒ  dS (9  é    NÚ ZCUDA_VISIBLE_DEVICES)ÚPath)ÚTupleÚListÚDictÚOptionalÚSet)Údecode_header)ÚEmailMessage)Ú	parseaddr)ÚMIMEText)Úload_dotenv)ÚDocument)Ú	parse_xml)ÚTable)Ú	Paragraphz)%(asctime)s [%(levelname)s] - %(message)szapp.logúutf-8)Úencoding)ÚlevelÚformatZhandlers)ÚSpellCheckerÚ	IMAP_HOSTú"Ú	IMAP_USERÚ	IMAP_PASSÚ
IMAP_LABELZINBOXÚ	SMTP_HOSTÚ	SMTP_PORTZ465Ú	SMTP_USERÚ	SMTP_PASSÚUSE_SMTP_SSLÚtrueÚGEMINI_API_KEYÚGEMINI_MODELzgemini-3.5-flash-liteZ
DISCIPLINAu   NÃ£o IdentificadaÚMAX_ISSUES_TECHZ12ÚMAX_ISSUES_LANGÚ8ÚMAX_FORMAT_ISSUESÚCOUNT_ANGLICISM_IN_LANGUAGEZfalseÚIA_CAN_FAILÚEMAIL_APROVADO_PARAz$direccao.academica.insutec@gmail.comÚEMAIL_CC_GERALzrouget.ruano@insutec.aoÚ
ASSINATURAu'   Atenciosamente,
A Equipa de ValidaÃ§Ã£oÚSIGN_IMAGE_PATHzimg/assina.pngÚSIGN_IMAGE_WIDTH_CMÚ5ÚaÚoÚosÚasZumZumaZunsZumasZdeZdoZdaZdosZdasZnoZnaZnosZnasÚeZouZmasZqueZseZaoZaosõ   Ã u   Ã sZporZparaZcomZsemZemZcomou   nÃ£oZsimZerau   sÃ£oõ   Ã©ZfoiZserZestarZvaiZvemZterZosiZtcpZudpZipZhttpZhttpsZdnsZdhcpZvpnZlanZwanZwlanZnatZmplsZqosZbgpZospfZrouterZswitchZfirewallÚproxyZgatewayZ	bandwidthZ
throughputZpacketÚframeZlteZ5gZgsmZwcdmaZcdmaZofdmZqamZpskZmimoÚpythonÚjavaZ
javascriptZ
typescriptZsqlZnosqlÚjsonÚxmlZapiÚrestZdockerZlinuxZwindowsZdbZdbmÚhzZkhzZmhzZghzÚvÚwZvaÚvarZohmZomegaZkpaZmpaZgpaÚlogÚlnZsenZcosZtanZcotZsecZcscZdetZlimZinsutecZeisiZertZluandaZangolaZkzu   1Âªu   2Âªu   3Âªu   4Âªu   1Âºu   2Âºu   3Âºu   4Âºu#   language_tool_python nÃ£o instaladozpt-PTzFalha LanguageTool: Zen)Úlanguage)Ú
raw_headerÚreturnc              	   C   sÀ   | sdS z–t | ƒ}d}|D ]j\}}t|tƒrx|r4|nd}z||j|dd�7 }W q„ tk
rt   ||jddd�7 }Y q„X q|t|ƒ7 }q| dd¡ dd¡ ¡ W S  tk
rº   t| ƒ Y S X d S )Nr   r   Úignore©ÚerrorsÚcp1252Ú
ú)	r	   Ú
isinstanceÚbytesÚdecodeÚLookupErrorÚstrÚreplaceÚstripÚ	Exception)rE   Zdecoded_fragmentsZ
header_strÚbytes_contentr   Úenc© rW   úworkflow.pyÚclean_headerŒ   s     
rY   )Úassunto_emailrF   c                 C   s6   | sdS t  d| ¡ dd¡ d¡ ¡ }tt d|¡ƒS )NFZNFKDÚASCIIrG   r   zenunciad[oa]s?)ÚunicodedataZ	normalizeÚencoderO   ÚlowerÚboolÚreÚsearch)rZ   Ztexto_normalizadorW   rW   rX   Úverificar_assunto_inteligenteŸ   s    rb   )Ú	doc_bytesrF   c                 C   sÐ   t  ¡ �¾}t|ƒ}|d }| | ¡ zZddddt|ƒdt|ƒg}tj|dtjtjd� |d	 }| ¡ rn| 	¡ nd W W  5 Q R £ S  t
k
rÀ } z$t d
|› �¡ W Y ¢W 5 Q R £ d S d }~X Y nX W 5 Q R X d S )Nztemp_input.docZlibreofficez
--headlessz--convert-toÚdocxz--outdirT)ÚcheckÚstdoutÚstderrztemp_input.docxu   Erro conversÃ£o .doc: )ÚtempfileZTemporaryDirectoryr   Zwrite_bytesrQ   Ú
subprocessÚrunZDEVNULLÚexistsZ
read_bytesrT   ÚloggingÚerror)rc   Ztemp_dirZtemp_dir_pathZ
input_pathÚcmdZoutput_pathr4   rW   rW   rX   Úconverter_doc_para_docx¥   s    

"ro   )rU   rF   c                    s„  �zBt  | ¡��}t|ƒ}dg‰d‰ tdœ‡ ‡fdd„}|jj}| ¡ D ]Æ}|j}| d¡rn|t	||ƒj
ƒ qH| d¡rHz`t||ƒ}tƒ }|jD ]D}	|	jD ]8}
t|
jƒ}||kr²qš| |¡ |
jD ]}||j
ƒ qÂqšq�W qH tk
�r } zt d|› �¡ W 5 d }~X Y qHX qHW 5 Q R X ˆ�r:ˆd	 d
k�r:ˆ ¡  �qd ˆ¡W S  tk
�r~ } zt d|› �¡ W Y ¢d
S d }~X Y nX d S )Nz--- BODY ---F)Úrawc                    sL   | pd  dd¡}t dd|¡ ¡ }|r6ˆ |¡ d‰ nˆ sHˆ d¡ d‰ d S )Nr   õ   Â ú ú[ \t]+FT)rR   r`   ÚsubrS   Úappend)rp   Út©Z
last_blankÚlinesrW   rX   Úadd_line¿   s    

z(extract_full_docx_text.<locals>.add_linez}pz}tblu   Tabela ignorada na extraÃ§Ã£o: éÿÿÿÿr   rK   u   Erro extraÃ§Ã£o DOCX: )ÚioÚBytesIOr   rQ   ÚelementÚbodyZiterchildrenÚtagÚendswithr   Útextr   ÚsetZrowsZcellsÚidZ_tcÚaddÚ
paragraphsrT   rl   ÚwarningÚpopÚjoinrm   )rU   Zfile_streamÚdocry   r~   Zchildr   ZtblZ
seen_cellsÚrowZcellÚkeyÚpr4   rW   rw   rX   Úextract_full_docx_text¸   s>    







.r�   )Ú
docx_bytesrF   c              	   C   sŽ   ztt  t | ¡¡�Z}| ¡ D ]J}| d¡r< W 5 Q R £ W dS | d¡r| ¡  d¡r W 5 Q R £ W dS qW 5 Q R X W n tk
rˆ   Y nX dS )Nzword/embeddings/Tzword/media/)z.wmfz.emfF)	ÚzipfileÚZipFiler{   r|   ÚnamelistÚ
startswithr^   r€   rT   )rŽ   ÚzÚnrW   rW   rX   Údocx_has_ole_formulasì   s    
"r•   é@œ  )rŽ   Ú	max_charsrF   c           
   
      sL  | sdS �zddl ‰ ttdœ‡ fdd„}t t | ¡¡�®}g }g }| ¡ D ]6}|dkrb| |¡ qJ| d¡rJ| 	d	¡rJ| |¡ qJ|s˜d
d„ | ¡ D ƒ}|D ]D}z&| 
|¡jddd�}| ||ƒ¡ W qœ tk
rÞ   Y qœY qœX qœW 5 Q R X d dd„ |D ƒ¡}|d|… W S  tk
�rF }	 zt d|	› �¡ W Y ¢dS d}	~	X Y nX dS )z>Extrai texto bruto do DOCX lendo diretamente os XMLs internos.r   r   N)r<   rF   c                    s¢   t  dd| ¡} t  dd| ¡} t  dd| ¡} t  dd| ¡} t  dd| ¡} t  dd	| ¡}ˆ  |¡}| d
d¡ dd¡}| dd¡}t  dd|¡}t  dd|¡}| ¡ S )Nz	</w:p\s*>rK   z
</w:tc\s*>z
<w:br\s*/>z
<w:cr\s*/>z<w:tab\s*/>ú	z<[^>]+>r   z
rL   rq   rr   rs   z\n{3,}ú

)r`   rt   ZunescaperR   rS   )r<   Ztxt©ÚhtmlrW   rX   Úxml_to_text  s    
z/_extract_docx_text_via_xml.<locals>.xml_to_textzword/document.xmlzword/headerú.xmlc                 S   s$   g | ]}|  d ¡r| d¡r|‘qS )zword/r�   )r’   r€   )Ú.0r”   rW   rW   rX   Ú
<listcomp>  s     
 
 z._extract_docx_text_via_xml.<locals>.<listcomp>r   rG   rH   rK   c                 S   s   g | ]}|r|‘qS rW   rW   )rž   rŒ   rW   rW   rX   rŸ   !  s      z!Erro _extract_docx_text_via_xml: )r›   rQ   r�   r�   r{   r|   r‘   ru   r’   r€   ÚreadrO   rT   rˆ   rl   rm   )
rŽ   r—   rœ   r“   ÚpartsÚ
candidatesÚnamer<   Úoutr4   rW   rš   rX   Ú_extract_docx_text_via_xmlû   s4    r¥   )ÚvalrF   c                 C   sF   | pd  ¡ }| dd¡}t dd|¡}t dd|¡  ¡ }|  d¡}|S )Nr   rq   rr   rs   z\s*\n\s*z 	
:;,.)rS   rR   r`   rt   )r¦   r?   rW   rW   rX   Ú_normalize_disciplina'  s    
r§   c                 C   s²   t | dd�}|sd S d}d|› d�d|› d�g}|D ].}t ||¡}|r4t| d¡ƒ}|r4|  S q4t d|¡}|r®t| d¡ƒ}t d	|› d
�|¡d  ¡ }t|ƒ}|r®|S d S )Nr–   )r—   uc   Ano\s*Lec?tivo|Ano\s*Letivo|Data|Curso|Docente|Nome|Prova|Dura(?:Ã§|c)Ã£o|N[Âºo]|Turma|Variante|Anozp(?is)\b(?:Disciplina|Cadeira|Unidade\s+Curricular|UC|U\.C\.|Curricular\s+Unit)\b\s*[:\-\.]\s*(.+?)\s*(?=\n\s*(?:z)\b|$)z4(?is)\b(?:Assunto)\b\s*[:\-\.]\s*(.+?)\s*(?=\n\s*(?:é   z/(?is)\bdisciplina\b\s*[:\-\.]?\s*([^\n]{3,200})z	(?i)\b(?:z)\br   )r¥   r`   ra   r§   ÚgroupÚsplitrS   )rŽ   ZsampleZstop_labelsÚpatternsZpatÚmr¦   rW   rW   rX   Ú&try_extract_discipline_from_docx_bytes/  s,    ÿ

þ
r­   )r�   rF   c                 C   s<   |   ¡ }g }d}|D ]"}| ||f¡ |t|ƒd 7 }q|S )Nr   r¨   )Ú
splitlinesru   Úlen)r�   rx   ÚoffsetsZoffrC   rW   rW   rX   Ú_line_offsetsN  s    r±   u   lÃ­nguaZlinguaZ
portuguesau
   portuguÃªsZ
literaturau
   gramÃ¡ticaZ	gramaticau	   redaÃ§Ã£oZredacaou   interpretaÃ§Ã£oZinterpretacaou   compreensÃ£oZcompreensaou   comunicaÃ§Ã£oZcomunicacaou   comunicaÃ§Ã£o pessoalzcomunicacao pessoalZempresarialu   comunicaÃ§Ã£o empresarialzcomunicacao empresarialu
   expressÃ£oZ	expressaoZtextoõ   produÃ§Ã£o textualúproducao textualZtelecomZ	telecomunZredesZsistemasu   informÃ¡ticaZinformaticau   fÃ­sicaZfisicaZmatemu   cÃ¡lculoZcalculoZelectrZeletrZcircuitZprogramZ
engenhariau   quÃ­micaZquimicaZestatZ	econometrc                 C   sz   | sd S | d d… }d}d| d d| d g}|D ]@}t  ||¡}|r4| d¡ ¡  d¡}t|ƒ}|rl|nd   S q4d S )Ni¬  un   Ano\s*Lec?tivo\s*:|Data\s*:|Curso\s*:|Docente\s*:|Nome\s*:|Prova\s*:|DuraÃ§Ã£o\s*:|NÂº\s*:|Turma\s*:|Ano\s*:|$zS(?i)(?:Disciplina|Cadeira|Unidade Curricular|Curricular Unit)\s*[:\.]\s*(.+?)\s*(?=ú)z%(?i)(?:Assunto)\s*[:\.]\s*(.+?)\s*(?=r¨   z.,;)r`   ra   r©   rS   Úrstripr§   )r�   Zheader_sampleZ	lookaheadr«   Úpatternr¬   r?   rW   rW   rX   Útry_extract_discipline_regexg  s    

þr·   )Ú
disciplinar�   rF   c                    s†   | pd  ¡ ‰ |pd  ¡ ‰t‡ fdd„tD ƒƒr2dS ddddd	d
ddddddg}t‡fdd„|D ƒƒrhdS t‡ fdd„tD ƒƒr‚dS dS )Nr   c                 3   s   | ]}|ˆ kV  qd S ©NrW   ©rž   Úk©ÚdrW   rX   Ú	<genexpr>|  s     z#classify_profile.<locals>.<genexpr>rD   u   leitura e interpretaÃ§Ã£ozleitura e interpretacaou   funcionamento da lÃ­nguazfuncionamento da linguau   virgulaÃ§Ã£oZ
virgulacaor²   r³   ZpronominalizeZdespronominalizau   pronominalizaÃ§Ã£oZpronominalizacaoc                 3   s   | ]}|ˆ kV  qd S r¹   rW   )rž   Úh)rv   rW   rX   r¾   †  s     c                 3   s   | ]}|ˆ kV  qd S r¹   rW   rº   r¼   rW   rX   r¾   ‰  s     Ú	technical)r^   ÚanyÚLANGUAGE_KEYWORDSÚTECH_KEYWORDS)r¸   r�   Zcontent_hitsrW   )r½   rv   rX   Úclassify_profilex  s,           ûrÄ   c           
      C   sâ   | sd S t | ƒ}d }t|ƒD ]$\}\}}t d| ¡ ¡r|} qBq|d kr\dtt| ƒdƒfS || d }t d¡}t|d t|ƒƒD ]B}|| d  ¡ }| |¡r„|| d }	|	|d kr„||	f  S q„tt| ƒ|d ƒ}	||	fS )Nu   (?i)^\s*instru[Ã§c][Ãµo]es?\s*$r   iÐ  ul   (?i)^\s*(parte\s+[ivx]+|parte\s+\d+|texto\s*(?:i|ii|iii|1|2|3)|quest(?:Ãµes|oes)|perguntas|exerc[Ã­i]cios)\br¨   é   iÄ	  )	r±   Ú	enumerater`   ra   rS   Úminr¯   ÚcompileÚrange)
r�   r°   Zinst_iÚiÚ_rC   Z	start_offZstop_hdrÚjZend_offrW   rW   rX   Údetect_instructions_span‘  s,    ÿ
rÍ   )ÚoffsetÚspanrF   c                 C   s(   |sdS |\}}||   ko"|k S   S )NFrW   )rÎ   rÏ   r0   ÚbrW   rW   rX   Úin_span°  s    rÑ   é   )r�   Úmin_freqrF   c           	      C   sv   t ƒ }| s|S t d| ¡}i }|D ]*}| ¡ }|tkr8q"| |d¡d ||< q"| ¡ D ]\}}||krV| |¡ qV|S )Nu   [A-Za-zÃ€-Ã–Ã˜-Ã¶Ã¸-Ã¿]{3,}r   r¨   )r‚   r`   Úfindallr^   ÚSTOPWORDS_PTÚgetÚitemsr„   )	r�   rÓ   ÚwlÚtokensZfreqrv   Ztlr@   ÚcrW   rW   rX   Úbuild_dynamic_tech_whitelist¹  s    rÛ   u9   [=<>Â±Ã—Ã·âˆšâˆ‘âˆ�âˆ«â‰ˆâ‰ Â°Î©ÂµÎ¼Ï€Î»Î”Î±Î²Î³Î´Î¸Ï†Ï‰]u>   (?i)\b(khz|mhz|ghz|hz|dbm|db|mw|w|v|a|ohm|Î©|kÎ©|mÎ©|va|var)\bz<(?i)\b([a-z]{1,3}\s*=\s*[^ ]+|[a-z]\([a-z]\)|[a-z]\^[0-9])\b)ÚtokenrF   c                 C   sn   | sdS t dd„ | D ƒƒr0t dd„ | D ƒƒr0dS t | ¡r>dS t | ¡rLdS t | ¡rZdS t d| ¡rjdS dS )NFc                 s   s   | ]}|  ¡ V  qd S r¹   )Úisdigit©rž   ZchrW   rW   rX   r¾   Ó  s     z/looks_like_formula_or_symbol.<locals>.<genexpr>c                 s   s   | ]}|  ¡ V  qd S r¹   )ÚisalpharÞ   rW   rW   rX   r¾   Ó  s     Tz	[_/\\@#%])rÁ   ÚMATH_SYMBOLS_REra   ÚUNITS_REÚFORMULA_LIKE_REr`   )rÜ   rW   rW   rX   Úlooks_like_formula_or_symbolÐ  s    $


rã   )ÚwordÚ
dynamic_wlrF   c                 C   sP   | sdS |   ¡ }| ¡ }t|ƒdk r(dS |tkr4dS ||kr@dS t|ƒrLdS dS )NTé   F)rS   r^   r¯   ÚWHITELIST_TECNICArã   )rä   rå   r@   rØ   rW   rW   rX   Úis_technical_or_tokenß  s    rè   )r�   ÚprofileÚinstructions_spanrF   c              
   C   sØ  g g g dœ}| d ks|s|S t |dd�}dh}ddh}�z^|  |¡}|D �]F}	|dkrh|	j||B krtqHn|	j|krtqH||	j|	j|	j … }
|
 d¡}|sšqH|td	|	jd
 ƒ|	j… d||	j|	j|	j … › d� ||	j|	j |	j|	j d
 …  }|d	  ¡ �r|d  d||	jdœ¡ qHt	||ƒ�r@|d  d||	jdœ¡ qHd}t
�r|zt
 | ¡ g¡ }W n tk
�rz   d}Y nX |�rÜ|dk�r¨|d  d||	jdœ¡ qHn4d||	jdœ}t�rÌ|d  |¡ qH|d  |¡ qHtt|	dd ƒƒ}d||	jtt|	dg ƒƒd d… dœ}|dk�rVt|	j|ƒ�r>|�r>|d  |¡ n|d  |ddi–¡ qHt|	j|ƒ�rz|�rz|d  |¡ qH|d  |ddi–¡ qH|W S  tk
�rÒ } zt d|› �¡ | W Y ¢S d }~X Y nX d S )N)ÚcountedÚalertsÚignoredrÒ   )rÓ   ZMORFOLOGIK_RULE_PT_PTZWHITESPACE_RULEZDOUBLE_PUNCTUATIONrD   z.,;:?!()[]{}"'r   é   ú[[ú]]rí   u   Ignorado (nome prÃ³prio).©ÚmessageÚcontextÚruleu&   Ignorado (tÃ©cnico/fÃ³rmula/sÃ­mbolo).FrÀ   u-   Ignorado (anglicismo aceitÃ¡vel em tÃ©cnico).u   Anglicismo detectado (lÃ­ngua).rë   rì   Zreplacementsu   PossÃ­vel erro.é   )rò   ró   rô   Úsuggestionsrò   u*   Alerta (fora de INSTRUÃ‡Ã•ES em tÃ©cnico).u)   Alerta (fora de INSTRUÃ‡Ã•ES em lÃ­ngua).zErro check_spelling_profiled: )rÛ   re   ZruleIdrÎ   ZerrorLengthrS   ÚmaxÚisupperru   rè   ÚENGLISH_CHECKERÚunknownr^   rT   r(   r_   ÚgetattrÚlistrÑ   rl   rm   )Ztool_ptr�   ré   rê   r¤   rå   ZALLOWED_RULESZLANGUAGE_EXTRAZmatchesr¬   rp   r@   ÚctxZis_english_wordÚitemZhas_suggestionsr4   rW   rW   rX   Úcheck_spelling_profiledñ  s|    



ÿþÿ

ü
rÿ   c                 C   sè   g }| s|S t  d¡}| | ¡D ]º}| d¡| d¡| d¡  }}}| ¡ | ¡ | ¡   }}}	|tks |tks |	tkr|q | ¡ | ¡  }
}| td|
d ƒ|
… d| |
|… › d� | ||d …  }| 	d	|d
dœ¡ q |d d… S )Nud   \b([A-Za-zÃ€-Ã–Ã˜-Ã¶Ã¸-Ã¿]{2,5})\s+([A-Za-zÃ€-Ã–Ã˜-Ã¶Ã¸-Ã¿]{1,3})\s+([A-Za-zÃ€-Ã–Ã˜-Ã¶Ã¸-Ã¿]{1,3})\br¨   rÒ   ræ   r   é   rï   rð   u6   PossÃ­vel palavra partida por espaÃ§os (formataÃ§Ã£o).ZFORMAT_SPLIT3rñ   éP   )
r`   rÈ   Úfinditerr©   r^   rÕ   ÚstartÚendr÷   ru   )r�   ZissuesZpat3r¬   r0   rÐ   rÚ   ZalZblZclr  r  rý   rW   rW   rX   Údetect_formatting_breaksF  s    
":r  )Úfull_promptrF   c              	   C   s¬   ddl }ddl}dt› dt› �}t dd| igigddd	œd
œ¡ d¡}|jj||ddidd�}|jj	|dd��}t 
| ¡  d¡¡}W 5 Q R X |d d d d d d S )zN
    Chama a API Gemini directamente via HTTPS/REST usando apenas urllib.
    r   Nz8https://generativelanguage.googleapis.com/v1beta/models/z:generateContent?key=r¡   r�   i   zapplication/json)ZmaxOutputTokensZresponseMimeType)ÚcontentsZgenerationConfigr   zContent-TypeZPOST)ÚdataZheadersÚmethodé<   )Ztimeoutr¢   Zcontent)Zurllib.requestZurllib.errorr#   r"   r;   Údumpsr]   ZrequestZRequestZurlopenÚloadsr    rO   )r  ZurllibZurlÚpayloadZreqZrespr~   rW   rW   rX   Ú_gemini_rest_callZ  s*    ÿþþú ýr  F)r�   r¸   ré   Úhas_ole_formulasrF   c                 C   sÄ  t sdS |dkrd}nd}|r&|d7 }t| ƒdkr>| dd… n| }|› d|› �}d	}zbt|ƒ}| ¡ }t d
d	|¡}t dd	|¡ ¡ }t |¡}t| 	dd¡ƒ| 	dd	¡| 	dd	¡fW S  tj
k
�rx }	 z t d|	› d|dd… › �¡ t d|¡}
|
�r
|
 d¡dknd}t d|¡}|�r2| d¡ ¡ d nd}t d|¡}|�rV| d¡ ¡ nd	}|||f W Y ¢S d}	~	X Y nH tk
�r¾ }	 z(t d|	› �¡ dd|	› �d	f W Y ¢S d}	~	X Y nX dS )u}   
    Avalia o conteÃºdo do enunciado usando Google Gemini (REST puro).
    Por padrÃ£o NÃƒO reprova (IA_CAN_FAIL=false).
    )Tu.   Sem IA (GEMINI_API_KEY nÃ£o definida no .env).r   rD   u]  Aja como Coordenador PedagÃ³gico de LÃ­ngua/ComunicaÃ§Ã£o. Analise clareza, coerÃªncia e se hÃ¡ ambiguidades. NÃ£o assuma que ambiguidades sÃ£o proibidas; em lÃ­nguas pode haver interpretaÃ§Ã£o. Responda APENAS com JSON vÃ¡lido, sem markdown, sem blocos ```json: {"permissivel":true,"justificativa":"mÃ¡ximo 3 frases","sugestoes":"mÃ¡ximo 3 frases"}uB  Aja como Coordenador PedagÃ³gico de Engenharia. Analise clareza, completude e avaliabilidade. Termos tÃ©cnicos, sÃ­mbolos e fÃ³rmulas sÃ£o esperados e nÃ£o sÃ£o erros. Responda APENAS com JSON vÃ¡lido, sem markdown, sem blocos ```json: {"permissivel":true,"justificativa":"mÃ¡ximo 3 frases","sugestoes":"mÃ¡ximo 3 frases"}u™   ATENÃ‡ÃƒO: este documento contÃ©m fÃ³rmulas/expressÃµes matemÃ¡ticas embutidas como objetos (Equation Editor/imagens) que foram REMOVIDAS na extraÃ§Ã£o de texto. As questÃµes podem parecer incompletas (ex.: 'a) ;') mas as expressÃµes existem no documento original. NÃƒO considere a ausÃªncia de expressÃµes matemÃ¡ticas como falha de completude; avalie apenas a redaÃ§Ã£o, instruÃ§Ãµes e estrutura visÃ­veis.ià.  Nz

Enunciado a avaliar:
r   z^```(?:json)?\s*z
\s*```\s*$ÚpermissivelTZjustificativaZ	sugestoesu   Gemini JSON invÃ¡lido: z | resposta: i,  z "permissivel"\s*:\s*(true|false)r¨   r!   z"justificativa"\s*:\s*"([^"]*)z [resposta IA truncada]u#   Aviso IA: resposta nÃ£o parseÃ¡vel.z"sugestoes"\s*:\s*"([^"]*)zErro Gemini REST: zErro IA Gemini: )r"   r¯   r  rS   r`   rt   r;   r  r_   rÖ   ZJSONDecodeErrorrl   rm   ra   r©   rT   )r�   r¸   ré   r  Zsystem_promptZtext_truncatedr  rp   r  r4   r¬   r  rÌ   ÚjustÚsÚsugrW   rW   rX   Úevaluate_proof_contentw  sH    ÿ	ÿ
ÿ


ýr  )rc   Úimage_path_strÚimage_width_cmrF   c              
   C   sÀ   t |ƒ}| ¡ s| S znt | ¡}t|ƒ}dd„ }|jd }|j}|jrP|jd n| ¡ }	||	t	|ƒ|ƒ t ¡ }
| 
|
¡ |
 ¡ W S  tk
rº } zt d|› �¡ W Y ¢d S d }~X Y nX d S )Nc           
      S   s€   |   ¡ }| j |¡\}}t|d ƒ}|j|jf}t||d  |d  ƒ}d|› d|› d|› d|› d|› d�}	|j t|	ƒ¡ d S )	Ni@~ r¨   r   a•  <w:drawing xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture"><wp:anchor distT="0" distB="0" distL="114300" distR="114300" simplePos="0" relativeHeight="251658240" behindDoc="1" locked="0" layoutInCell="1" allowOverlap="1"><wp:simplePos x="0" y="0"/><wp:positionH relativeFrom="margin"><wp:align>right</wp:align></wp:positionH><wp:positionV relativeFrom="page"><wp:posOffset>540000</wp:posOffset></wp:positionV><wp:extent cx="z" cy="a}  "/><wp:effectExtent l="0" t="0" r="0" b="0"/><wp:wrapNone/><wp:docPr id="1" name="Signature"/><wp:cNvGraphicFramePr><a:graphicFrameLocks noChangeAspect="1"/></wp:cNvGraphicFramePr><a:graphic><a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture"><pic:pic><pic:nvPicPr><pic:cNvPr id="0" name="Sig"/><pic:cNvPicPr/></pic:nvPicPr><pic:blipFill><a:blip r:embed="zµ" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"/><a:stretch><a:fillRect/></a:stretch></pic:blipFill><pic:spPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="z„"/></a:xfrm><a:prstGeom prst="rect"><a:avLst/></a:prstGeom></pic:spPr></pic:pic></a:graphicData></a:graphic></wp:anchor></w:drawing>)	Zadd_runÚpartZget_or_add_imageÚintZpx_widthZ	px_heightZ_rru   r   )
Z	paragraphr  Zwidth_cmrj   ZrIdZimageZ	width_emuZimg_sizeZ
height_emuZgraphic_xmlrW   rW   rX   Úinsert_floating_image_in_headerÇ  s    "ÿz=add_signature_to_doc.<locals>.insert_floating_image_in_headerr   zErro assinatura DOCX: )r   Úis_filer{   r|   r   ZsectionsÚheaderr…   Zadd_paragraphrQ   ZsaveÚgetvaluerT   rl   rm   )rc   r  r  Z
image_pathZ
doc_streamr‰   r  Zsectionr  rŒ   r¤   r4   rW   rW   rX   Úadd_signature_to_doc¿  s"    
!


r  c              	   C   s’  t tttgƒsd S tƒ }t| |  |d< |d< |d< |r@||d< |r\d| tdƒd¡› d�nd	}| |› d
|› �dd¡ | d| tdƒd¡› d|› d�dd¡ |�rF| 	¡  |D ]’\}}	zrt
 |¡d pÌd dd¡\}
}| d¡�rt|	jddd�ddƒ}|jdd|d� | |¡ n|j|	|
||d� W q² tk
�rB   Y q²X q²t�rRtjntjttƒ�*}t�sn| ¡  | tt¡ | |¡ W 5 Q R X d S )NÚFromZToÚSubjectZCcz<br><br><p>é
   z<br>z</p>r   r™   Zplainr   z<html><body><p>z</body></html>r›   r   zapplication/octet-streamú/r¨   z.txtz	utf-8-sigrR   rH   zContent-DispositionZ
attachment)Úfilename)ZmaintypeZsubtyper"  )Úallr   r   r   r
   rR   ÚchrZset_contentZadd_alternativeZ
make_mixedÚ	mimetypesZ
guess_typerª   r€   r   rO   Z
add_headerZattachZadd_attachmentrT   r    ÚsmtplibZSMTP_SSLZSMTPr   ZstarttlsÚloginZsend_message)Útort   r~   ÚattsÚccÚ
assinaturaÚmsgZhtml_sigÚfnameÚfbytesZmtÚstr  r  rW   rW   rX   Ú
send_email÷  s4     (r0  c            (      C   sb  t tttgƒst d¡ d S z,t t¡} |  tt¡ |  	dt
› d�¡ W n8 tk
r€ } zt d|› �¡ W Y ¢d S d }~X Y nX |  d d¡\}}|dks¢|d sÀt d¡ |  ¡  |  ¡  d S |d  ¡ D �]~}�z<|  |d¡\}}|dkròW qÌt |d d	 ¡}t| d
d¡ƒ}t|ƒ�s2t d|› �¡ W qÌtt| dd¡ƒƒd	 }	t d|	› d|› �¡ g }
| ¡ D ]`}| ¡ }|�s‚�qlt|ƒ}| d¡�rš�ql| ¡  d¡�rl|jdd�}|�rl|
 ||f¡ �ql|
�st d|	› d|› �¡ t |	ddt!d� |  "|dd¡ W qÌ|
D �]ì\}}| ¡  d¡�r^t#|ƒ}|�sRt |	d|› �dt!d� �q|}|d }t$|ƒ}|�s–t d|› �¡ t |	d|› �dt!d� �qt%|ƒ�p¬t&|ƒ�p¬t'}t(||ƒ}t)|ƒ}t*|ƒ}|�rÞt |› d �¡ t+t,|||ƒ}t-|d! ƒ}t.|ƒ}t-|ƒ}t/||||d"�\}}}|d#k�r,t0nt1}| �o:t2}| �oT||k�oT|t3k}|�r`d$nd%} dZt4t5t6 t7t4d'œd(d)„}!g }"|" d*| › �¡ |" d+|› �¡ |" d,|› d-�¡ |" d.t8› d/�¡ |�rÖ|" d0¡ |" d¡ |" d1¡ |" |�pöd2¡ |�r|" d3|› �¡ |" d4¡ |" d5¡ |" d6¡ |" d7t9�r>d8nd9 d: ¡ |" d¡ |" |!d;|d! d<d=�¡ |" d>|› d?|› d@�¡ |" |!dA|dB d&d=�¡ |" |!dC|dD d&d=�¡ |" d4¡ |" dE¡ |" |!dF|d&d=�¡ |" dG|› d?t3› �¡ t:j;d@ <|"¡ =dH¡ }#dI|#f}$|�rtt>|t?t@ƒ}%|%�rPt tAdJ|› �dKdL|› �|%f|$gtBt!dM� t |	dJ|› �dN|$||fgtBt!dM� nˆg }&|�rˆ|& dO¡ ||k�rœ|& dP¡ |t3k�r°|& dQ¡ dR}'|&�rÒ|'dSdT <|&¡ dU 7 }'n|'dV7 }'t |	dW|› �|'|$||fgtBt!dM� �q|  "|dd¡ W qÌ tk
�rJ } zt dX|› dY|› �¡ W 5 d }~X Y qÌX qÌ|  ¡  |  ¡  d S )[Nu$   ConfiguraÃ§Ãµes de IMAP incompletas.r   zErro ao conectar IMAP: z(UNSEEN)ZOKr   zNenhum email novo.z(BODY.PEEK[])r¨   r  r   u)   Assunto sem 'Enunciado(s)' â€” ignorado: r  zProcessando: z | z~$)z.docxú.docT)rO   z"Sem anexos .doc/.docx no email de u   [ERRO] Sem anexo vÃ¡lidouÄ   O seu email foi recebido, mas nÃ£o foi encontrado nenhum ficheiro .doc ou .docx anexado.
Verifique se anexou o documento diretamente (nÃ£o como link do Google Drive/OneDrive) e reenvie, por favor.)r+  z+FLAGSz\Seenr1  z[ERRO] zFalha ao converter .doc.Úxu   ExtraÃ§Ã£o de texto vazia: ug   NÃ£o foi possÃ­vel extrair texto do documento. Verifique se o ficheiro nÃ£o estÃ¡ corrompido e reenvie.uJ   : fÃ³rmulas OLE/Equation Editor detetadas â€” parecer IA em modo limitado.rë   )r  rD   ZAPROVADOu   REVISÃƒOr   )Útitler×   ÚlimitrF   c                 S   s¦   |s| › d�S | › dt |ƒ› d�}t|d |… dƒD ]H\}}d}| d¡r\dd |d ¡ }||› d	| d
d¡› |› d�7 }q4t |ƒ|kr¢|dt |ƒ| › d�7 }|S )Nz: 0
ú: rK   r¨   r   rö   z	 | Sug.: z, z. ró   z... (z
 ocultos)
)r¯   rÆ   rÖ   rˆ   )r3  r×   r4  r  rÊ   ÚitZsug_txtrW   rW   rX   Úfmt_list‰  s    

"zprocess_inbox.<locals>.fmt_listu   VALIDAÃ‡ÃƒO: zDisciplina: zPerfil: u)    (language=rigoroso, technical=flexÃ­vel)zMotor IA: Google Gemini (r´   uº   NOTA: o documento contÃ©m fÃ³rmulas como objetos (Equation Editor) invisÃ­veis Ã  extraÃ§Ã£o de texto â€” o parecer IA avaliou apenas a redaÃ§Ã£o/estrutura, nÃ£o o conteÃºdo matemÃ¡tico.u(   [IA - ALERTA] (nÃ£o reprova por padrÃ£o)u   Sem observaÃ§Ãµes.u   
[IA - SugestÃµes]:
z
====================u   ORTOGRAFIA / GRAMÃ�TICAuH   - Nomes prÃ³prios / fÃ³rmulas / sÃ­mbolos / termos tÃ©cnicos: IGNORADOS.u(   - Anglicismos: tÃ©cnico ignora; lÃ­ngua ZCONTAZALERTAÚ.zCONTAM (podem reprovar)é(   )r4  zTOTAL_CONTAM = z | LIMITE = rK   u   ALERTAS (nÃ£o reprovam)rì   zIGNORADOS (esperados)rí   u   FORMATAÃ‡ÃƒOzSuspeitas de palavra partidau   TOTAL_FORMATAÃ‡ÃƒO = r   zrelatorio.txtz[APROVADO] u&   Segue enunciado assinado e relatÃ³rio.Z	ASSINADO_)r)  r*  r+  u   Aprovado. Segue relatÃ³rio.zparecer IA (IA_CAN_FAIL=true)u'   ocorrÃªncias que contam acima do limiteu   formataÃ§Ã£ou   NecessÃ¡ria revisÃ£o.
z	Motivos: z; z.
u(   Motivo: regra interna (ver relatÃ³rio).
u   [REVISÃƒO] u   Erro crÃ­tico ID r5  )r   )Cr#  r   r   r   rl   rm   ÚimaplibZ	IMAP4_SSLr'  Zselectr   rT   ra   ÚinfoÚcloseZlogoutrª   ZfetchÚemailZmessage_from_bytesrY   rÖ   rb   r   ÚwalkÚget_filenamer’   r^   r€   Zget_payloadru   r†   r0  r,   Zstorero   r�   r­   r·   ÚDISCIPLINA_FALLBACKrÄ   rÍ   r•   rÿ   ÚLANG_TOOL_PTr¯   r  r  r%   r$   r)   r'   rQ   r   r   r  r#   r(   ÚcodecsÚBOM_UTF8rˆ   r]   r  r-   r.   r*   r+   )(Zimapr4   Zstatusr  ZnumÚresrp   r,  ZsubjectZsenderZ
docs_partsr  Zraw_filenamer-  r  r.  Z	convertedr�   r¸   ré   rê   Zhas_oleZspellrë   Z
fmt_issuesZ	fmt_countZok_iar  r  Z
max_issuesZ	ia_blocksZaprovadoZ
status_tagr7  ÚreportZ	rep_bytesZatt_repZdoc_assinadoZmotivosr~   rW   rW   rX   Úprocess_inbox  s<   


 
ù	û
ÿý









ú
ú	





ú
	* rF  c                   C   s
   t ƒ  d S r¹   )rF  rW   rW   rW   rX   Úmainç  s    rG  Ú__main__)r–   )rÒ   )F)NNr   )r2   Úenvironr`   Úsysr;   r=  r:  r&  rl   r%  r{   rB  r�   ri   rh   r\   Úpathlibr   Útypingr   r   r   r   r   Zemail.headerr	   Zemail.messager
   Zemail.utilsr   Zemail.mime.textr   Zdotenvr   rd   r   Z	docx.oxmlr   Z
docx.tabler   Zdocx.text.paragraphr   ZbasicConfigÚINFOZFileHandlerZStreamHandlerrf   Zlanguage_tool_pythonÚImportErrorZspellcheckerr   ÚgetenvrS   rR   r   r   r   r   r   r  r   r   r   r^   r    r"   r#   r@  r$   r%   r'   r(   r)   r*   r+   r,   Ú__file__ZresolveÚparentZ
SCRIPT_DIRZSIGN_IMAGE_PATH_FROM_ENVrQ   r-   Úfloatr.   rÕ   rç   rA  ÚRuntimeErrorZLanguageToolrT   r4   rm   rù   rY   r_   rb   rN   ro   r�   r•   r¥   r§   r­   r±   rÂ   rÃ   r·   rÄ   rÍ   rÑ   rÛ   rÈ   rà   rá   râ   rã   rè   rÿ   r  r  r  r  r0  rF  rG  Ú__name__rW   rW   rW   rX   Ú<module>   s@  
ý

                                      û
                                                                                 ó
"
4,                    û                 ý $	 2U*H8$ M