U
    ^¨j˜  ã                   @   sœ  d dl mZmZ d dlmZmZ d dlmZmZ d dlm	Z	m
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mZmZ ddlmZmZ ddlmZmZ ddgZdZdZej ddgdd�dd„ ƒZ!ej ddgd�eƒ dd„ ƒƒZ"ej ddgd�eƒ dd„ ƒƒZ#ej ddgd�eƒ d d!„ ƒƒZ$ej d"dgd�eƒ d#d$„ ƒƒZ%ej d%ddgd�d&d'„ ƒZ&ej d(dgd�d)d*„ ƒZ'd+d,„ Z(d-d.„ Z)d/d0„ Z*d1d2„ Z+dS )3é    )ÚrequestÚjsonify)Újwt_requiredÚget_jwt_identity)ÚdatetimeÚ	timedelta)ÚcredentialsÚ	messagingN)Ú
DESCENDING)ÚObjectIdé   )Únotifications_bp)Úget_dbÚSERVICES_DB_MAPÚUSER_DATABASE_NAMEÚinsert_log_in_user_history)Úsubscribe_token_to_topicÚsend_topic_notification)Úenviar_alerta_whatsappÚenviar_mensaje_prueba_waZ56976494291Z56935741906ÚITG_CHILE_WHATSAPP_SECUREZevento_centroz8/<SERVICE>/ingest_notifications/<REGION>/<AREA>/<CENTRO>ÚPOSTF)ÚmethodsÚstrict_slashesc           7      C   s*  |   ¡ }t |¡}|s.tdd| › d�iƒdfS �z®| dd¡ dd¡ ¡ }| dd¡ dd¡ ¡ }| dd¡ dd¡ ¡ }|› d|› d|› �}	tj}
|
sªtddiƒd	fW S t|
t	ƒrÀt
|
 ¡ ƒ}
t|
t
ƒsÜtd
diƒd	fW S tƒ }|| }g }|
D ]L}|	t ¡ d| ¡ › �| dd¡d| dd¡| dd¡dœdœ}| |¡ qò|�sXtd
diƒdfW S |j |¡}dd„ |jD ƒ}|d d }|d d d }|d d d }d}d}|  ¡ }d |k�sØd!|k�sØd"|k�sØd#|k�râd$}d%}nd&|k�söd'|k�rþd(}d)}|› d|› d*| ¡ › �}|› d*|› d+|› d,�}t|	||||d |	d-d.œ|d/d0œd1�}|t }|d2 }|  ¡ }|  ¡ }|  ¡ › d|  ¡ › d|  ¡ › �}|} d3|› d4|› d4|› d4| › �}!|!› d5�}"|!› d6�}#| |"d7|#d7d d8œi¡}$g }%|$D ]Þ}&zŽ|& d9i ¡}'|' |i ¡}(|( |i ¡})|) |i ¡}*|* | i ¡}+|+ d:¡},|,�rvt|,ƒ d;d¡ dd¡ ¡ }-t|-ƒd<k�rv|-|%k�rv|% |-¡ W nH tk
�rÀ }. z(td=|& d>¡› d?|.› �ƒ W Y ¢�qæW 5 d }.~.X Y nX �qæ|%�sàtd@| › dA|› �ƒ g }/g }0|%�r–|%D ]¢}1t|1tdB|	id dC�}2d }3|2 dD¡dEk�rV|2 di ¡}4dF|4k�rVt|4dF ƒdGk�rV|4dF dG d }3|1|3dHt ¡ dIœ}5|0 |5¡ |/ |1|2 dD¡|3|2 d¡dJœ¡ �qò|0�rÈ|�rÈ|jd }6|j dK|6idL|0dHdMœi¡ tdN|||/dOœƒdfW S  tk
�r$ }. z&tdP|.› �ƒ tddQiƒdRf W Y ¢S d }.~.X Y nX d S )SNÚmensajez
Servicio 'z' no soportado.é”  Ú Ú Ú-z	Sin datosé�  ÚmsgzSe espera lista o dictzAlerta Údatau   Alerta sin descripciÃ³nÚcriticalÚidZ
unknown_idÚtime)Úlocal_idÚ
local_time)Ú	centro_idÚserver_timestampÚtitleÚmessageZseverityÚraw_datazNo hay alertaséÈ   c                 S   s   g | ]}t |ƒ‘qS © )Ústr)Ú.0Úoidr-   r-   úA/var/www/itgmanager/itgmanager/blueprints/notifications/routes.pyÚ
<listcomp>I   s     z(ingest_notifications.<locals>.<listcomp>éÿÿÿÿr*   r+   r%   r&   u   âš ï¸�z#FFA500ZfalloÚerroru   crÃ­ticou   pÃ©rdidau   ðŸš¨z#FF0000ÚokZrestablecidou   âœ…z#00FF00z - z registrado a las z de hoyZFCM_PLUGIN_ACTIVITY)ÚserviceÚnotification_idr'   Zclick_actionZalerts_channel)ÚcolorZandroid_channel_id)r'   r)   ÚbodyZdata_payloadÚextra_kwargsÚusersz	permisos.Ú.z.statusz.phoneT)z$existsz$neÚpermisosÚphoneú+é   u'    Error extrayendo telÃ©fono de usuario Úusernameú: z5 Info: Nadie tiene configurado recibir WhatsApp para z en Úcentro)Znumero_destinoZnombre_plantillaZheader_varsZ	body_varsÚstatusÚsuccessÚmessagesr   Úsent)r>   ÚwamidrD   Ú	timestamp)ÚnumerorD   rH   r!   Ú_idú$set)Zwhatsapp_logZdelivery_statuszNotificaciones procesadas)r    Úinserted_idsÚpush_statusZwhatsapp_statuszError: úError internoéô  )Úlowerr   Úgetr   ÚreplaceÚ
capitalizer   ÚjsonÚ
isinstanceÚdictÚlistÚvaluesr   r   ÚnowÚupperÚappendÚnotificacionesÚinsert_manyrM   r   r   Úfindr.   ÚstripÚlenÚ	ExceptionÚprintr   ÚPLANTILLA_NANOOXÚ
update_one)7ÚSERVICEÚREGIONÚAREAÚCENTROÚservice_keyÚtarget_db_nameZr_normZa_normZc_normZcentro_id_unificadoZreceived_dataÚclientÚdbZdocs_to_insertÚitemÚdocÚresultrM   Zultimo_mensajeZid_jaulaZ
event_timeZemoji_statusZ	color_hexZ	msg_lowerZtitulo_eleganteZcuerpo_eleganterN   Údb_usersÚ	col_usersÚr_keyÚa_keyÚc_keyZs_keyZpath_to_serviceZpath_statusZ
path_phoneZusuarios_destinatariosZlista_numerosÚusuarior=   Úregion_dataÚ	area_dataZcentro_dataZservicio_dataZtelefonoZtelefono_limpioÚeZwhatsapp_resultsZwhatsapp_log_dbrJ   rD   rH   Z	data_respÚ	log_entryZlast_alert_idr-   r-   r1   Úingest_notifications   s   
 




þú(üþõ 

  þ
 ü	ü
ü
þÿþ
üûr{   z/api/notificationsÚGET)r   c               
   C   sÌ  �zzt ƒ } t| ƒ}|s.tg ddidœƒdfW S tj d¡}tj d¡}ttj dd¡ƒ}ttj d	d
¡ƒ}t ¡ }|t	|d� }d|id|idœ}|r¼||kr¨||d< ntg ddœƒdfW S t
ƒ }	g }
|rèt | ¡ ¡}|râ|gng }ntt ¡ ƒ}|D ]V}z6|	| d }| |¡ dt¡ |¡}|
 t|ƒ¡ W qø tk
�rL   Y qøY qøX qø|
jdd„ dd� |
d |… }dd„ |D ƒ}t| ¡ ƒ}tƒ }|D ]Z}z@|	| d  d|i| dœddi¡}|D ]}| |d ¡ �q¾W n   Y �q’Y nX �q’g }|D ]h}|d }t|ƒ|d< | d i ¡}t|tƒ�r8| d!d ¡|d!< nd |d!< |d= ||k|d"< | |¡ �qöt|| t|ƒd#œdœƒdfW S  tk
�rÆ } z*td$|› �ƒ td%t|ƒiƒd&f W Y ¢S d }~X Y nX d S )'NÚcountr   )r!   Z
query_infor,   r'   r6   Úlimité2   Úhoursé   )r€   z$gtez$in)r(   r'   z$Acceso denegado al centro solicitado)r!   r    é“  r]   r(   c                 S   s   |   dd¡S )Nr(   r   )rR   )Úxr-   r-   r1   Ú<lambda>:  ó    z#get_notifications.<locals>.<lambda>T)ÚkeyÚreversec                 S   s   i | ]}|d  |“qS )rK   r-   )r/   ro   r-   r-   r1   Ú
<dictcomp>>  s      z%get_notifications.<locals>.<dictcomp>Únotificaciones_lecturas©r7   Ú
user_emailr7   r   rK   r#   r+   r%   Úread)Úuserr}   zError en GET: r4   rP   )r   Ú"obtener_centros_permitidos_usuarior   r   ÚargsrR   Úintr   rZ   r   r   r   rQ   rX   rY   r_   Úsortr
   r~   Úextendrb   ÚkeysÚsetÚaddr.   rV   rW   r\   ra   rc   )Úcurrent_usernameZallowed_centersZreq_centro_idZservice_reqr~   Zhours_lookbackZutc_nowZcutoff_timeÚqueryrl   Zraw_resultsZ	target_dbZdbs_to_searchÚdb_nameÚcolÚcursorZfinal_sliceZnotif_ids_mapZlist_of_idsZread_setZreads_cursorÚrÚresponse_dataro   Zdoc_oidr+   ry   r-   r-   r1   Úget_notifications   sŒ    þ
 þû þþúr�   z/api/notifications/subscribec               
   C   sV  �zt ƒ } t ¡ }| d¡}|s2tddiƒdfW S tƒ }|t d  d| idd|ii¡ g }tƒ }|t d  	d| i¡}|D ]}t
||ƒr|| |¡ q|d}|ròz"|D ]}	t|g|	ƒ q¤t|ƒ}W n0 tk
rð }
 ztd	|
› �ƒ W 5 d
}
~
X Y nX tdd| › d|› d�|dœƒdfW S  tk
�rP }
 ztdt|
ƒiƒdf W Y ¢S d
}
~
X Y nX d
S )u/  
    VÃ­a Correcta: 
    1. Recibe un token (que asumimos es NUEVO o VÃ�LIDO para este usuario).
    2. Calcula permisos reales en DB.
    3. Suscribe SOLO a los permisos reales.
    NO intenta desuscribir de lo prohibido, porque confiamos en que el token
    es fresco o exclusivo de este usuario.
    Ú	fcm_tokenr    zFalta tokenr   r;   rA   rL   r   zError suscribiendo: NrE   úUsuario z suscrito a z	 centros.)rD   r    Ztopicsr,   r4   rP   )r   r   Úget_jsonrR   r   r   r   re   Ú%obtener_todos_los_topicos_del_sistemaÚfind_oneÚverificar_permiso_inversor\   r   ra   rb   rc   r.   )r–   r!   rž   rl   Útopicos_permitidosZset_universoÚuser_docZtopicZ	suscritosÚtry   r-   r-   r1   Úsubscribe_devicen  sD    

þ
 ýür§   z/api/logout_pushc            	   
   C   s  zÎt ƒ } t ¡ }| d¡}|s0tddiƒdfW S td| › �ƒ tƒ }d}|rˆ|D ]6}z$t |g|¡}|j	dkrv|d7 }W qP   Y qPX qPt
ƒ }|t d  d	| id
ddii¡ td|› d�ƒ tddiƒdfW S  tk
�r } z*td|› �ƒ tdt|ƒiƒdf W Y ¢S d}~X Y nX dS )u‚   
    Ruta de LIMPIEZA: Recibe el token que se va a destruir y
    fuerza la desuscripciÃ³n de todos los tÃ³picos del sistema.
    rž   r    zToken requeridor   u.   ðŸ‘‹ [LOGOUT] Iniciando limpieza para usuario r   r   r;   rA   z$unsetr   u   âœ… [LOGOUT] Token limpiado de z temas y eliminado de DB.zToken limpiador,   zError en logout_push: r4   rP   N)r   r   r    rR   r   rc   r¡   r	   Zunsubscribe_from_topicZsuccess_countr   r   re   rb   r.   )	r–   r!   rž   Ztodos_los_temasr}   ZtemaÚresponserl   ry   r-   r-   r1   Úlogout_push_device¯  s6    

 
þr©   z /ack/<SERVICE>/<NOTIFICATION_ID>c              
   C   s  �zÈt  |¡s tddiƒdfW S |  ¡ }t |¡}|sHtddiƒdfW S tƒ }|sdtddiƒdfW S tƒ }|| }|j 	dt |ƒiddd	œ¡}|s¤tdd
iƒdfW S |j
jt |ƒ|dœdt |ƒ|| d¡t ¡ dœidd�}|jrædnd}	td|› d|› d|	› d�ƒ |j�r¶zt|t }
|
d }|
j 	d|iddi¡}|�rNd|k�rN|d n|}| ¡ | dd¡| dd¡dœ}t|||dƒ W n2 tk
�r´ } ztd|› �ƒ W 5 d }~X Y nX td!d"|	d#œƒd$fW S  tk
�r } z,td%|› �ƒ td&t|ƒd'œƒd(f W Y ¢S d }~X Y nX d S ))u…   
    Registra la lectura ('firma') de un usuario sobre una notificaciÃ³n.
    Simula el evento "Usuario hizo clic en la alerta".
    r    u   ID de notificaciÃ³n invÃ¡lidor   u   Servicio no vÃ¡lidor   u   Falta el parÃ¡metro user_emailrK   r   )r'   r*   u(   La notificaciÃ³n ha expirado o no existerŠ   rL   r'   )r7   r‹   r'   Zread_atT)ÚupsertÚCreatedZUpdatedz[ACK] z
 -> Notif z (ú)Úhistorial_usersÚemailrA   ÚDesconocidor*   zAlerta sin texto)r6   rC   r*   Úread_notificationz%Error escribiendo historial usuario: NrE   z Lectura registrada correctamente)rD   r    Úactionr,   zError en ACK: zError interno del servidor)r    r4   rP   )r   Úis_validr   rQ   r   rR   r   r   r]   r¢   r‰   re   r   rZ   Úupserted_idrc   r   r;   r[   r   rb   r.   )rf   ZNOTIFICATION_IDrj   rk   r‹   rl   rm   Znotif_existsrp   r±   rq   Úcol_historyr¥   Úreal_usernameÚlog_datary   r-   r-   r1   Úacknowledge_notificationà  sz    

þüÿóþ

ýü ýür·   z/whatsapp/webhookc               
      sx  t jdkrltj dd¡} t j d¡}t j d¡}t j d¡}|dkr\|| kr\tdƒ |d	fS td
ƒ dS �nt jdk�rtt j}�z¼| di g¡d }| di g¡d }| di ¡}d|k�r:tƒ }|d D �]l}	|	d }
|	d }|	d }|	 d¡}td|› d|
› �ƒ t	t
 ¡ ƒ}|D ]R}|| }|j}| d|id|
t ¡ dœi¡}|jdk�rtd|› �ƒ  �qj�q|
dkrÊ|t }|d }|d }‡ fdd „‰ | i d!d!d!d"œ¡}d }|D ],}| d#¡}|�r²ˆ ||ƒ�r²|} �qà�q²|�r(| d$d%¡}d&d'd(|d)|› d*�d+œ}t|||d,ƒ td-|› �ƒ qÊtd.|› d/�ƒ qÊW n2 tk
�rn } ztd0|› �ƒ W 5 d }~X Y nX d1S d S )2Nr|   r   Ztu_token_aquizhub.modezhub.verify_tokenzhub.challengeZ	subscribez1[WEBHOOK] Meta ha verificado la URL exitosamente.r,   u+   [WEBHOOK] Intento de verificaciÃ³n fallido.)Ú	Forbiddenr‚   r   Úentryr   ÚchangesÚvalueZstatusesrD   r#   Zrecipient_idrI   z [WHATSAPP] z -> Estado: zwhatsapp_log.wamidrL   )zwhatsapp_log.$.statuszwhatsapp_log.$.updated_atz# [DB UPDATE] Alerta actualizada en rŒ   r;   r­   c                    s¦   t |ƒ ¡ }t| tƒr~|  ¡ D ]\\}}|dkr\|r\t |ƒ dd¡ dd¡ ¡ }||kr\ dS t|ttfƒrˆ ||ƒr dS qn$t| tƒr¢| D ]}ˆ ||ƒrŒ dS qŒdS )Nr>   r?   r   r   TF)r.   r`   rV   rW   ÚitemsrS   rX   )r!   Ztarget_phoneÚkÚvZdb_phonern   ©Úexiste_telefono_en_estructurar-   r1   rÀ   ‡  s    




z7whatsapp_webhook.<locals>.existe_telefono_en_estructurar   )rA   r>   r=   r=   rA   r¯   ZWHATSAPPu   NotificaciÃ³n ExternaZmessage_readrŸ   u    leyÃ³ la alerta.)r6   rC   r±   Z
message_idÚdetailsr°   u,   [HISTORIAL] Ã‰XITO: Registrado 'Visto' para u    [HISTORIAL] TelÃ©fono u4    reportÃ³ lectura pero no se encontrÃ³ dueÃ±o en DB.z [WEBHOOK ERROR] Procesando: )ZEVENT_RECEIVEDr,   )r   ÚmethodÚosÚenvironrR   r�   rc   rU   r   rX   r   rY   r]   re   r   rZ   Úmodified_countr   r_   r   rb   )ZVERIFY_TOKENÚmodeÚtokenÚ	challenger!   r¹   rº   r»   rl   rD   Z
new_statusZwa_idZnumero_metarI   Z
target_dbsr˜   rm   Z	col_notifrp   rq   rr   r´   Zcursor_usersZusuario_encontradoÚur=   rµ   r¶   ry   r-   r¿   r1   Úwhatsapp_webhookB  sŒ    


þÿþ	



ûü rÊ   z/test-whatsapp/<numero>c              
   C   s~   z4t | ƒ}|d dkr$t|ƒdfW S t|ƒdfW S W nD tk
rx } z&td|› �ƒ tddiƒdf W Y ¢S d	}~X Y nX d	S )
uÌ   
    Ruta de prueba. Se usa GET para poder ejecutarla fÃ¡cilmente 
    desde la barra de direcciones del navegador.
    Ejemplo: https://test.itgchile.com/itg_7xR9L2m_secure/test-whatsapp/56912345678
    rD   rE   r,   r   zError en ruta de WhatsApp: r    rO   rP   N)r   r   rb   rc   )rJ   Ú	resultadory   r-   r-   r1   Útrigger_whatsapp_testÈ  s    rÌ   c              	   C   s  t ƒ }|t j}| d| i¡}|r*d|kr.g S g }| di ¡}| ¡ D ]Ò\}}| ¡ D ]À\}}	|	 ¡ D ]®\}
}d}| ¡ D ](\}}t|tƒrz| d¡dkrzd} q¤qz|rfz^|
 d¡}t	|ƒdk�r|d  
¡ }|d	  
¡ }|d
  
¡ }|› d|› d|› �}| |¡ W qf   Y qfX qfqVqF|S )z—
    Retorna una lista de IDs de centros (formato Topic) permitidos para el usuario.
    Ej: ['Loslagos-Puertomontt-Itg', 'Aysen-Aysen-Puntacola']
    rA   r=   FrD   Tr   é   r   r   r�   )r   r   r;   r¢   rR   r¼   rV   rW   Úsplitra   rT   r\   )rA   rl   Ú	users_colr�   Zcentros_permitidosr=   ÚregionÚareasÚareaÚcentros_dictÚ
centro_rawÚ	serviciosÚtiene_accesoÚsrvr!   ÚpartsÚc_nameÚa_nameÚr_nameZformatted_idr-   r-   r1   rŽ   Ü  s6    

 rŽ   c              
   C   sp  �z(t ƒ }|t d }| d| i¡}|r0d|kr6g W S g }| di ¡}| ¡ D ]Ö\}}| ¡ D ]Ä\}}	|	 ¡ D ]²\}
}d}| ¡ D ](\}}t|tƒr‚| d¡dkr‚d} q¬q‚|rnz^|
 d¡}t|ƒdk�r|d	  	¡ }|d
  	¡ }|d  	¡ }|› d|› d|› �}| 
|¡ W qn   Y qnY qnX qnq^qN|W S  tk
�rj } z td| › d|› �ƒ g  W Y ¢S d}~X Y nX dS )u¹   
    Consulta la DB y retorna una lista de los tÃ³picos (Centros) 
    a los que el usuario tiene acceso real.
    Retorna ej: ['Loslagos-Puertomontt-Itg', 'Aysen-Aysen-Puntacola']
    r;   rA   r=   FrD   Tr   rÍ   r   r   r�   zError obteniendo permisos para rB   N)r   r   r¢   rR   r¼   rV   rW   rÎ   ra   rT   r\   rb   rc   )rA   rl   rÏ   r�   r¤   r=   rÐ   rÑ   rÒ   rÓ   rÔ   rÕ   rÖ   r×   r!   rØ   rÙ   rÚ   rÛ   Z	topic_fmtry   r-   r-   r1   Úobtener_topicos_permitidos  s>    
rÜ   c                  C   sÞ   t ƒ } | t d }tƒ }| i ddi¡}|D ]¬}| di ¡}| ¡ D ]’\}}| ¡ D ]€\}}	|	 ¡ D ]n\}
}zX|
 d¡}t|ƒdkrÂ|d  ¡ }|d  ¡ }|d  ¡ }| 	|› d|› d|› �¡ W qd   Y qdX qdqTqDq,|S )u¤   
    Escanea la colecciÃ³n de usuarios para descubrir TODOS los centros (tÃ³picos) que existen.
    Retorna un SET con strings tipo 'Loslagos-Puertomontt-Itg'.
    r;   r=   r   r   rÍ   r   r�   )
r   r   r”   r_   rR   r¼   rÎ   ra   rT   r•   )rl   rÏ   Ztodos_los_topicosrš   r�   r=   rÐ   rÑ   rÒ   ÚcentrosrÔ   Ú_rØ   ÚcÚar›   r-   r-   r1   r¡   :  s&    
 r¡   c              
   C   sü   zº|  d¡}t|ƒdkrW dS |\}}}| ¡ }| ¡ }| ¡ }|› d|› d|› �}	|  di ¡}
|
 |i ¡ |i ¡ |	¡}|s„W dS | ¡ D ](\}}t|tƒrŒ| d¡dkrŒ W dS qŒW dS  tk
rö } ztd|› d|› �ƒ W Y ¢dS d	}~X Y nX d	S )
u¾   
    Recibe un TÃ³pico: "Loslagos-Puertomontt-Itg"
    Lo transforma a Key DB: "itg-puertomontt-loslagos" (Al revÃ©s y minÃºsculas)
    Y verifica si existe en los permisos del usuario.
    r   rÍ   Fr=   rD   Tz'Error verificando permiso inverso para rB   N)	rÎ   ra   rQ   rR   r¼   rV   rW   rb   rc   )r¥   Z	topic_strrØ   Zr_topicZa_topicZc_topicrs   rt   ru   Zdb_centro_key_reversedr=   Údatos_centroÚservicioÚinfory   r-   r-   r1   r£   W  s(    


r£   ),Úflaskr   r   Úflask_jwt_extendedr   r   r   r   Zfirebase_adminr   r	   ZpytzÚpymongor
   Úbsonr   r   r   Úshared_db_utilsr   r   r   r   Zpush_servicer   r   Zwhatsapp_servicer   r   ZPHONE_TO_SENDr   rd   Úrouter{   r�   r§   r©   r·   rÊ   rÌ   rŽ   rÜ   r¡   r£   r-   r-   r-   r1   Ú<module>   sJ   
 jl?/`
 
)5