Ë
    ÍþÍjë$  ã                   óV  — d 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
mZ ddlmZ ddlmZmZ dd	lmZmZ dd
lmZ  ej,                  e«      ZdddœZdedefd„Zdedededee   fd„Zdededefd„Zd)dedededefd„Z dedede!dedef
d„Z"dededefd„Z#dedefd„Z$dede!dedefd„Z%dedede!dedef
d„Z&dZ'ded edededef
d!„Z(ded ededede!dedee   fd"„Z)dededefd#„Z*dedede!dedef
d$„Z+d)d%ededee   fd&„Z,d)dededededee   f
d'„Z-dedede.e   fd(„Z/y)*uk  
media_service.py â€” acceso seguro a las fotos de las familias.

Antes de pagar, el navegador solo recibe una vista previa reducida, servida por una URL firmada con
caducidad. Los originales nunca se exponen como archivos estÃ¡ticos: se descargan Ãºnicamente con un
enlace firmado ligado a un pedido pagado (ver main.py::download_original).

La vista previa es, por orden de preferencia:
  1. La foto con las CARAS PROTEGIDAS en servidor (StoryFace KIS), si el colegio lo tiene activado
     (`protection_service`, mismo mecanismo que hec-photo-app).
  2. Un respaldo propio: versiÃ³n reducida (sin marca de agua: la protecciÃ³n es la de arriba). Se usa si la
     protecciÃ³n de caras estÃ¡ apagada o si KIS falla â€” a diferencia de HEC, nunca se cae al original sin proteger.
Encima, el navegador puede dibujar el overlay animado (lens/puzzle) que estropea las capturas.
é    N)ÚPath)ÚOptional)Úquote)ÚImageÚImageOps)Úconfig)ÚsignÚverify_signature)Úphoto_serviceÚprotection_service)ÚCODE_REiè  ià  )ÚfullÚthumbÚcodeÚreturnc                 óF   — t        t        j                  | xs d«      «      S )NÚ )Úboolr   Úmatch)r   s    ú1/var/www/photos/backend/services/media_service.pyÚ
valid_coder   !   s   € Ü”—‘˜dšj bÓ)Ó*Ð*ó    Ú	school_idÚfilenamec                 óH   — t        |«      syt        j                  | ||«      S )uk   Ruta absoluta del original, o None si el cÃ³digo/archivo es sospechoso (../, absoluto, oculto) o no existe.N)r   r   Ú
find_photo)r   r   r   s      r   Úsafe_photo_pathr   %   s"   € ä�dÔØÜ×#Ñ# I¨t°XÓ>Ð>r   c                 ól  — di i}t        j                  | |«      D ]‡  \  }}|dz  }|j                  «       sŒ	 t        j                  |j                  d¬«      «      }|d   j                  |j                  di «      «       |j                  d|j                  dd«      «       Œ‰ |S # t        $ r Y Œ—w xY w)ua   meta.json de la familia (nombre del niÃ±o, etiquetas de fotos IA), fusionando todas sus carpetas.Úphoto_namesz	meta.jsonzutf-8)ÚencodingÚ
child_namer   )
r   Úfamily_dirsÚis_fileÚjsonÚloadsÚ	read_textÚ	ExceptionÚupdateÚgetÚ
setdefault)r   r   ÚmergedÚ_phÚfolderÚfÚdatas          r   Ú	read_metar0   ,   sµ   € à! 2Ð&€FÜ$×0Ñ0°¸DÓAò H‰ˆˆVØ�[Ñ ˆØ�9‰9�;ðÜ—z‘z !§+¡+°w +Ó"?Ó@�ð �=Ñ!×(Ñ(¨¯©°-ÀÓ)DÔEØ×Ñ˜l¨D¯H©H°\À2Ó,FÕGðHð €Møô	 ò Ùðús   ¸%B'Â'	B3Â2B3Úsizec           
      ó|   — t        d| › d|› �t        j                  «      \  }}d| › dt        |«      › d|› d|› d|› �
S )Núpreview:ú/z/api/media/preview/ú?exp=ú&sig=z&size=)r	   r   ÚMEDIA_URL_TTL_SECSr   )r   r   r1   ÚexpÚsigs        r   Úpreview_urlr:   =   sQ   € Ü�h˜t˜f A h ZÐ0´&×2KÑ2KÓL�H€CˆØ    a¬¨h«Ð'8¸¸c¸UÀ%ÈÀuÈFÐSWÐRXÐYÐYr   r8   r9   c                 ó(   — t        d| › d|› �||«      S )Nr3   r4   ©r
   )r   r   r8   r9   s       r   Úcheck_preview_signaturer=   B   s   € Ü˜h t f¨A¨h¨ZÐ8¸#¸sÓCÐCr   Úorder_idc                 óv   — t        d| › d|› �t        j                  «      \  }}d| › dt        |«      › d|› d|› �S )Nú	download:r4   z/api/portal/download/r5   r6   )r	   r   ÚDOWNLOAD_URL_TTL_SECSr   ©r>   r   r8   r9   s       r   Údownload_urlrC   F   sI   € Ü�i ˜z¨¨8¨*Ð5´v×7SÑ7SÓT�H€CˆØ" 8 *¨A¬e°H«oÐ->¸eÀCÀ5ÈÈcÈUÐSÐSr   c                 óX   — t        d| › �t        j                  «      \  }}d| › d|› d|› �S )Núdownloadzip:z/api/portal/download-zip/r5   r6   )r	   r   rA   ©r>   r8   r9   s      r   Údownload_zip_urlrG   K   s8   € Ü�l 8 *Ð-¬v×/KÑ/KÓL�H€CˆØ& x j°°c°U¸%À¸uÐEÐEr   c                 ó"   — t        d| › �||«      S )NrE   r<   rF   s      r   Úcheck_download_zip_signaturerI   P   s   € Ü˜l¨8¨*Ð5°s¸CÓ@Ð@r   c                 ó(   — t        d| › d|› �||«      S )Nr@   r4   r<   rB   s       r   Úcheck_download_signaturerK   T   s   € Ü˜i¨ z°°8°*Ð=¸sÀCÓHÐHr   i,  Úphotographerc                 ó„   — t        d| › d|› d|› d|› �d«      \  }}d| › dt        |«      › d|› dt        |«      › d|› d|› �S )Núadmin:r4   é  z/api/media/admin-thumb/r5   r6   )r	   r   )r   rL   r   r   r8   r9   s         r   Úadmin_thumb_urlrP   _   sg   € Ü�f˜Y˜K q¨¨°a¸°v¸Q¸x¸jÐIÈ4ÓP�H€CˆØ% i [°´%¸Ó2EÐ1FÀaÈÀvÈQÌuÐU]ËÐN_Ø�C�5˜˜c˜Uð$ð %r   c           
      óX  — t        d| › d|› d|› d|› �||«      sy| |||fD ]  }|r|j                  d«      s	d|v sd|v sŒ y t        j                  | «      }||z  |z  |z  }|dk(  s%|j	                  «       rt        j
                  |«      sy	 |j                  «       j                  |j                  «       «       t        j                  |dt        › d�«      }		 |	j                  «       r7|	j                  «       j                  |j                  «       j                  k\  r|	S |	j                  j                  d	d	¬
«       t!        j"                  |«      5 }
t%        j&                  |
«      }
|
j)                  t        t        ft         j*                  «       |	j-                  d«      }|
j/                  d«      j1                  |dd¬«       |j3                  |	«       ddd«       |	S # t        $ r Y yw xY w# 1 sw Y   |	S xY w# t4        $ r!}t6        j9                  d||«       Y d}~yd}~ww xY w)z`Miniatura del original (o None si la firma no vale o la ruta se sale de la carpeta del colegio).rN   r4   Nú.ú\r   z.adm.ú.webpT©ÚparentsÚexist_okú.tmpÚRGBÚWEBPéK   ©ÚformatÚqualityz#Miniatura de admin imposible %s: %s)r
   Ú
startswithr   Úschool_rootr#   Úis_imageÚresolveÚrelative_toÚ
ValueErrorÚmirror_pathÚADMIN_THUMB_PXÚexistsÚstatÚst_mtimeÚparentÚmkdirr   Úopenr   Úexif_transposeÚ	thumbnailÚLANCZOSÚwith_suffixÚconvertÚsaveÚreplacer'   ÚloggerÚwarning)r   rL   r   r   r8   r9   ÚpartÚbaseÚsrcÚdstÚimÚtmpÚexcs                r   Úadmin_thumb_pathr}   e   sî  € ä˜f Y K¨q°°¸aÀ¸vÀQÀxÀjÐQÐSVÐX[Ô\ØØ˜L¨$°Ð9ò ˆÙ�t—‘ sÔ+¨s°d©{¸dÀdºlÙðô ×$Ñ$ YÓ/€DØ
�Ñ
 Ñ
$ xÑ
/€CØ�rÒ §¡¤´m×6LÑ6LÈXÔ6VØðØ�‰‹×!Ñ! $§,¡,£.Ô1ô ×
#Ñ
# C¨5´Ð0@ÀÐ)FÓ
G€CðØ�:‰:Œ<˜CŸH™H›J×/Ñ/°3·8±8³:×3FÑ3FÒFØˆJØ�
‰
×Ñ °ÐÔ5Ü�Z‰Z˜‹_ð 	 Ü×(Ñ(¨Ó,ˆBØ�L‰Lœ.¬.Ð9¼5¿=¹=ÔIØ—/‘/ &Ó)ˆCØ�J‰J�uÓ×"Ñ" 3¨v¸rÐ"ÔBØ�K‰K˜Ô÷	ð ˆ
øô ò Ùðú÷	ð ˆ
ûÜò Ü�‰Ð<¸cÀ3ÔGÜûðúsP   Â-G# ÃAG? Ä"2G? ÅBG2Ç	G? Ç#	G/Ç.G/Ç2G<Ç7G? Ç<G? Ç?	H)ÈH$È$H)c                 óH   — t        d| › d|› �d«      \  }}d| › d|› d|› d|› �S )Núcard:r4   rO   z/api/media/card/z	.png?exp=r6   )r	   ©r   r   r8   r9   s       r   Úcard_urlr�   ‰   s>   € Ü�e˜I˜; a¨ vÐ.°Ó5�H€CˆØ˜i˜[¨¨$¨¨y¸¸¸UÀ3À%ÐHÐHr   c                 ó(   — t        d| › d|› �||«      S )Nr   r4   r<   r€   s       r   Úcheck_card_signaturerƒ   Ž   s   € Ü˜e I ;¨a°¨vÐ6¸¸SÓAÐAr   rx   c                 óè  — t         j                  |t         d   «      }t        j                  | d|› d�«      }	 |j	                  «       r7|j                  «       j                  | j                  «       j                  k\  r|S |j                  j                  dd¬«       t        j                  | «      5 }t        j                  |«      }|j                  ||ft        j                  «       |j                  d«      }ddd«       |j!                  d«      }j#                  |d	d
¬«       |j%                  |«       |S # 1 sw Y   ŒAxY w# t&        $ r!}t(        j+                  d| |«       Y d}~yd}~ww xY w)uÉ   Genera (una vez) la vista previa reducida (â‰¤ PREVIEW_PX, sin texto ni marca) y devuelve su ruta.
    Nombre `.pv.`: las copias `.wm.` de versiones anteriores llevaban marca de agua y ya no se sirven.r   z.pv.rT   TrU   rY   NrX   rZ   éF   r\   zVista previa imposible %s: %s)Ú
PREVIEW_PXr)   r   re   rg   rh   ri   rj   rk   r   rl   r   rm   rn   ro   rq   rp   rr   rs   r'   rt   ru   )rx   r1   Úpxry   rz   Úoutr{   r|   s           r   Úreduced_previewr‰   ”   s+  € ô 
�‰˜œj¨Ñ0Ó	1€BÜ
×
#Ñ
# C¨4°¨t°5Ð)9Ó
:€CðØ�:‰:Œ<˜CŸH™H›J×/Ñ/°3·8±8³:×3FÑ3FÒFØˆJØ�
‰
×Ñ °ÐÔ5Ü�Z‰Z˜‹_ð 	$ Ü×(Ñ(¨Ó,ˆBØ�L‰L˜"˜b˜¤5§=¡=Ô1Ø—*‘*˜UÓ#ˆC÷	$ð �o‰o˜fÓ%ˆØ�‰�˜V¨RˆÔ0Ø�‰�CÔØˆ
÷	$ð 	$ûô ò Ü�‰Ð6¸¸SÔAÜûðús7   ¹AE Â 2E Â2A	D;Ã;?E Ä;EÅ E Å	E1ÅE,Å,E1c              ƒ   óX  K  — ddl }t        | ||«      }|€yt        j                  |t        d   «      }	 t	        j
                  || |«      ƒ d{  –—† }|�|S 	 |j                  t        ||«      ƒ d{  –—† S 7 Œ(# t        $ r"}t        j                  d| ||«       Y d}~ŒGd}~ww xY w7 Œ4­w)z^Vista previa a servir: caras protegidas si procede; si no (o si KIS falla), la vista reducida.r   Nr   uQ   [%s] ProtecciÃ³n de caras fallida para %s (%s): se sirve la vista previa reducida)Úasyncior   r†   r)   r   Úprotected_previewr'   rt   ru   Ú	to_threadr‰   )	r   r   r   r1   r‹   rx   r‡   Ú	protectedr|   s	            r   Úrender_previewr�   ª   s³   è ø€ ãÜ
˜) T¨8Ó
4€CØ
€{ØÜ	�‰˜œj¨Ñ0Ó	1€Bð1Ü,×>Ñ>¸sÀIÈrÓR×Rˆ	ØÐ ØÐð !ð
 ×"Ñ"¤?°C¸Ó>×>Ð>ð Sùô ò 1Ü�‰ÐjØ  (¨C÷	1ñ 	1ûð1úð ?úsL   ‚2B*µA: ÁA8ÁA: ÁB*Á3B(Á4B*Á8A: Á:	B%ÂB ÂB*Â B%Â%B*c                 ó*  — t        | |«      }|j                  dd«      }|j                  di «      }g }t        j                  | |«      D ]Ç  }|j	                  |j
                  |j                  t        ||j                  d«      t        ||j                  d«      t        j                  |j                  «      dk(  r|j                  |j                  d«      ndt        j                  |«      t        j                  |j                  «      dœ«       ŒÉ |S )Nr!   r   r   r   r   Úai)Úidr   ÚurlÚ	thumb_urlr!   rL   Úkind)
r0   r)   r   Úlist_family_filesÚappendÚstemÚnamer:   Ú
photo_kindÚphotographer_of)r   r   Úmetar!   Únamesrˆ   r.   s          r   Úlist_family_photosrž   ½   sá   € Ü�Y Ó%€DØ—‘˜,¨Ó+€JØ�H‰H�] BÓ'€EØ
€CÜ×,Ñ,¨Y¸Ó=ò 
ˆØ�
‰
Ø—&‘&ØŸ™Ü˜t Q§V¡V¨VÓ4Ü$ T¨1¯6©6°7Ó;ä3@×3KÑ3KÈAÏFÉFÓ3SÐW[Ò3[˜%Ÿ)™) A§F¡F¨BÔ/ÐacÜ)×9Ñ9¸!Ó<Ü!×,Ñ,¨Q¯V©VÓ4ñ	
õ 		ð
ð €Jr   )r   )0Ú__doc__r$   ÚloggingÚpathlibr   Útypingr   Úurllib.parser   ÚPILr   r   Úcorer   Úcore.securityr	   r
   Úservicesr   r   Úservices.qr_detectr   Ú	getLoggerÚ__name__rt   r†   Ústrr   r   r   Údictr0   r:   Úintr=   rC   rG   rI   rK   rf   rP   r}   r�   rƒ   r‰   r�   Úlistrž   © r   r   ú<module>r°      sœ  ðñó Û Ý Ý Ý ç å ß 0ß 6Ý &à	ˆ×	Ñ	˜8Ó	$€à SÑ)€
ð+�Sð +˜Tó +ð?˜sð ?¨#ð ?¸ð ?ÀÈ$Áó ?ð˜ð  Cð ¨Dó ñ"Z�cð Z Sð Z°ð ZÀó Zð
D #ð D°ð D¸3ð DÀSð DÈTó DðT˜3ð T¨#ð T°#ó Tð
F˜sð F só Fð
A¨3ð A°Sð A¸sð AÀtó AðI sð I°cð IÀð IÈ#ð IÐRVó Ið €ð%˜sð %°#ð %¸Sð %ÈCð %ÐTWó %ð ð °3ð ¸cð ÈSð ÐWZð Ðadð ÐiqÐrvÑiwó ðHI˜ð I 3ð I¨3ó Ið
B Cð B¨sð B¸ð BÀ3ð BÈ4ó Bñ˜ð  Sð °h¸t±nó ñ,? Cð ?¨sð ?¸cð ?Èð ?ÐZbÐcgÑZhó ?ð& #ð ¨Sð °T¸$±Zô r   