a
    h                  	   @   s  d Z ddlZddlZddlZddlZddlmZmZ ddlm	Z	m
Z
mZmZmZmZmZ ddlm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 ddlZddlZddlZddlZddlZej e!Z"ej#e"dd	Z$ej#e"dd
Z%ej#e"dZ&e	e'e$e%dZ(ee(dd e) Z*e+e* ddl,m-Z- e(.e- ddl/m0Z0 e(j.e0dd ej12dde(_3ej12ddej12ddej12ddej12dde4ej12ddddd Z5ej12d!d"Z6e4ej12d#d$Z7d%d& Z8d'd( Z9e(:d)d*d+ Z;e(j:d,d-gd.d/d0 Z<e(j:d1d-gd.d2d3 Z=d4d5 Z>d6d7 Z?e(j:d8d-gd.e?d9d: Z@e(j:d8d;gd.e?d<d= ZAe(j:d>d;gd.e?d?d@ ZBe(j:dAd;gd.e?dBdC ZCe(j:d>dDgd.e?dEdF ZDe(j:d>dGgd.e?dHdI ZEe(j:dJd-gd.e?dKdL ZFe(j:dJd;gd.e?dMdN ZGe(j:dOd;gd.e?dPdQ ZHe(j:dRd;gd.e?dSdT ZIe(j:dOdDgd.e?dUdV ZJe(j:dOdGgd.e?dWdX ZKe(j:dYd;gd.e?dZd[ ZLe(j:dYdDgd.e?d\d] ZMe(:d^d_d` ZNe(:dadbdc ZOe(:dddedf ZPe(:dgdhdi ZQe(:djdkdl ZRe(:dmdndo ZSe(j:dpd-gd.dqdr ZTe(:dsdtdu ZUe(j:dvd;gd.e?dwdx ZVddlWZWddylXmYZY ddzlZm[Z[ e(j:d{d-gd.d|d} Z\e'd~kre]d e9 re]d ne]d e4ej12ddZ^e]de^  ej12ddkZ_e(j`de^e_d dS )us   
app.py - Backend principal de Auris con Flask y MySQL
Sistema de autenticación con encriptación de contraseñas
    N)datetime	timedelta)Flaskrequestjsonifyrender_templatesend_from_directoryredirectmake_response)CORS	PdfReader)secure_filenamefrontendZ	templatesstaticZtemp)Ztemplate_folderZstatic_folderT)Zsupports_credentials)tts_bp)edge_tts_bpz/api)Z
url_prefixZ
SECRET_KEYzauris-secret-key-2025ZDB_HOSTZ	localhostZDB_USERZmyadmonZDB_PASSWORDz
Quick25$$.ZDB_NAMEZAurisZDB_PORTZ3306Zutf8mb4)hostuserZpassworddatabaseportcharsetZ
autocommitJWT_SECRET_KEYzauris-jwt-secret-2025JWT_ACCESS_TOKEN_EXPIRESZ86400c               
   C   sH   zt jjf i t} | W S  t jjyB } zW Y d}~dS d}~0 0 dS )u'   Función para obtener conexión a MySQLN)mysql	connectorZconnect	DB_CONFIGError)
connectione r    /var/www/auris/app.pyget_db_connectionE   s
    r"   c               
   C   s   d} d}zzZt  } | s6W W |r&|  | r2|   dS |  }|   W W |rV|  | rb|   dS  tjjy } z(W Y d}~W |r|  | r|   dS d}~0 0 W |r|  | r|   n|r|  | r|   0 dS )z6Inicializar base de datos y crear tablas si no existenNFT)r"   closecursorcommitr   r   r   )r   r$   r   r    r    r!   init_databaseM   sD    
r&   z/api/test-dbc               
   C   s   t  } | rzT|  }|d | }|  |   tddtd d|rP|d ndddfW S  ty } z4| rz|   td	d
t| ddfW  Y d}~S d}~0 0 ntd	dddfS dS )u#   Probar conexión a la base de datoszSELECT 1successu   Conexión a MySQL exitosar   r   N)statusmessager   Z
test_queryresult   errorz"Error ejecutando query de prueba: r(   r)     u   Error de conexión a MySQL)	r"   r$   executefetchoner#   r   r   	Exceptionstr)r   r$   r*   r   r    r    r!   test_dba   s@    
r3   z/api/registerZPOST)methodsc               
      s^  zt d tj t fdddD s:tddidfW S  d  }  d	   } d
 }t| dk r|tddidfW S t|dk rtddidfW S d|vrtddidfW S d}d}z8zRt }|st d tddidfW W |r|	  |r|	  W S |
 }|d|| f | rdt d tddidfW W |rR|	  |r`|	  W S t|dt }|d| ||df |j}t d|  g d}|D ]\}}	|d|||	f q|  t d tdd |d!d"fW W |r|	  |r|	  W S  tjjyx }
 zFtdd#t|
 idfW  Y d}
~
W |r^|	  |rl|	  W S d}
~
0  ty }
 zFtdd$t|
 idfW  Y d}
~
W |r|	  |r|	  W S d}
~
0 0 W |r|	  |r|	  n|r|	  |r|	  0 W n@ tyX }
 z&tdd%t|
 idfW  Y d}
~
S d}
~
0 0 dS )&zRegistro de nuevos usuariosu&   📝 Procesando registro de usuario...c                 3   s   | ]}| v V  qd S Nr    .0kdatar    r!   	<genexpr>       zregister.<locals>.<genexpr>)nombre_usuariocorreo_electronico   contraseñar,   Faltan datos requeridos  r=   r>   r?      z5El nombre de usuario debe tener al menos 3 caracteres   u/   La contraseña debe tener al menos 6 caracteres@u   Correo electrónico inválidoNu"   ❌ Error de conexión en registro%   Error de conexión a la base de datosr.   zLSELECT id FROM Usuarios WHERE correo_electronico = %s OR nombre_usuario = %su   ❌ Usuario ya existezEl usuario o correo ya existei  utf-8u   
                INSERT INTO Usuarios (nombre_usuario, correo_electronico, contraseña) 
                VALUES (%s, %s, %s)
            u   ✅ Usuario creado con ID: ))tipo_vozmujer)velocidad_lecturaz1.0)u   tamaño_fuenteZmedium)contraste_altofalse)retroalimentacion_audiotrue
                    INSERT INTO Configuraciones_Usuario (usuario_id, nombre_configuracion, valor_configuracion) 
                    VALUES (%s, %s, %s)
                u$   ✅ Registro completado exitosamenter'   zUsuario registrado exitosamente)r(   r)   user_id   Error de base de datos: Error interno:    Error crítico: )printr   jsonallr   striplowerlenr"   r#   r$   r/   r0   bcryptZhashpwencodeZgensaltdecode	lastrowidr%   r   r   r   r2   r1   )r=   r>      contraseñar   r$   Zhashed_passwordrO   Zdefault_configsZconfig_nameZconfig_valuer   r    r9   r!   register   s    -
&&&
r_   z
/api/loginc               
      s  zXt j t fdddD s2tddidfW S  d   }  d }d	}d	}zzt }|stdd
idfW W |r|  |r|  W S |jdd}|	d| f |
 }|std tddidfW W |r|  |r|  W S t|d|d dsFtd tddidfW W |r4|  |rB|  W S |d t ttd d}tj|tdd}|	d|d f | }i }|D ]R}	|	d }
|	d }|
dv r| dk||
< n |
dkrt|||
< n|||
< qttdd ||d |d! |d |d" d#|d$}|jd%|d&d&d'd(d)d* |W W |rF|  |rT|  W S  tjjy } zFtdd+t| idfW  Y d	}~W |r|  |r|  W S d	}~0  ty } zFtdd,t| idfW  Y d	}~W |r|  |r|  W S d	}~0 0 W |r*|  |rX|  n|rH|  |rV|  0 W n@ ty } z&tdd-t| idfW  Y d	}~S d	}~0 0 d	S ).u   Autenticación de usuariosc                 3   s   | ]}| v V  qd S r5   r    r6   r9   r    r!   r;      r<   zlogin.<locals>.<genexpr>)r>   r?   r,   r@   rA   r>   r?   NrE   r.   TZ
dictionaryz4SELECT * FROM Usuarios WHERE correo_electronico = %su   ❌ Usuario no encontradou   Credenciales inválidas  rF   u   ❌ Contraseña incorrectaid)Zseconds)rO   ZexpHS256)	algorithmcSELECT nombre_configuracion, valor_configuracion FROM Configuraciones_Usuario WHERE usuario_id = %snombre_configuracionvalor_configuracionrJ   rL   rM   rI   r'   zLogin exitosor=   foto_perfil)rb   r=   r>   ri   )r(   r)   tokenusuarioconfiguraciones
auth_tokenFZLaxiQ /)ZhttponlyZsecureZsamesiteZmax_agepathrQ   rR   rS   )r   rU   rV   r   rW   rX   r"   r#   r$   r/   r0   rT   rZ   Zcheckpwr[   r   Zutcnowr   r   jwtr   fetchallfloatr
   Z
set_cookier   r   r   r2   r1   )r>   r^   r   r$   rk   payloadrj   configsrl   configkeyvalueresponser   r    r9   r!   login   s    ;3/


&&
ry   c                 C   s\   zt j| tdgd}|d W S  t jy:   td Y d S  t jyV   td Y d S 0 d S )Nrc   )Z
algorithmsrO   u   ❌ Token expiradou   ❌ Token inválido)rp   r\   r   ZExpiredSignatureErrorrT   ZInvalidTokenError)rj   rs   r    r    r!   verify_token&  s    
rz   c                    s    fdd} j |_ |S )Nc                     s.  d }t jd}|rD|drD|dd  }td|d d  d nndt jv r|t jd}td|rn|d d nd	 d n6d
t jv rt jd
}td|r|d d nd	 d |std t jdv rtdS t	ddidfS t
|}|std t jdv r
tdS t	ddidfS |t _ | i |S )NZAuthorizationzBearer    u   🔍 Token en Authorization:    ...rm   u   🔍 Token en cookie: Nonerj   u   🔍 Token en query: u   ❌ No se encontró token)iniciomodo_visualmodo_auditivo
bibliotecaconfiguracionrn   r,   zToken requeridora   u   ❌ Token inválido o expiradou   Token inválido)r   headersget
startswithrT   ZcookiesargsZendpointr	   r   rz   rO   )r   kwargsrj   Zauth_headerrO   fr    r!   decorated_function2  s0    
"
 
z)auth_required.<locals>.decorated_function)__name__)r   r   r    r   r!   auth_required1  s    r   z/api/documentsc            !   
      sN  t d ztj t d    s6tddidfW S t fdddD s^tdd	idfW S  d
  }  d  }t| dk rtddidfW S t| dkrtddidfW S t d|  dt| d d}d}d}d}d}d}zt }|stddidfW W S t d |jdd}|	dtj
f | }|  d}t dt| d i }	|D ]R}
|
d }|
d }|dv r| d k|	|< n |d!krt||	|< n||	|< q\|	d"d#}|	d!d$}t d%| d&|  tjd'|||d(d)d*}t d+|j  |jd,kr| }t d-|  |d.rt| }|sXd/t jdd0  }t d1}| d2| d3}tjtd4d5d6d7}tj|dd8 tj||}d9| }|d: }|d;rNtjtd4| d<}tj!|r:t"#|| zt$| W n4 t%y6 } zt d=|  W Y d}~n
d}~0 0 nt d>|  d}nvt d?|  tj|d)d@}|jd,krt&|dA}|'|j( W d   n1 s0    Y  nt dB|j  d}nt dC|d  nt dD|j dE|j)  W nz tj*j+y. } zt dF|  W Y d}~nLd}~0  t%yp } z*t dG|  dHdl,}|-  W Y d}~n
d}~0 0 d}z*z(|st }|stddidfW W |r|  t dI |r|  t dJ |r|  t dK W S | }|	dL | }t dM |D ]}t dN|  qt dO t dPtj
  t dQ|  dR t dSt| dT t dU| dR t dV| dR t dW| dR d}|rtj!|rtj.|}t dX| dY |	dZtj
| ||||f |j/}|0  t d[|  |rd\nd]}d.d^| ||du|r$|nd|r0|nd|r<|ndd_} t d`|   t| dafW W |rv|  t dI |r|  t dJ |r|  t dK W S  t1j2j3y\ } zt db|  t dc|j4  t dd|j5  tddet6| idfW  Y d}~W |r$|  t dI |r:|  t dJ |rP|  t dK W S d}~0 0 W |rv|  t dI |r|  t dJ |r|  t dK nD|r|  t dI |r|  t dJ |r|  t dK 0 W n^ t%yH } zDt df|  dHdl,}|-  tddgt6| idfW  Y d}~S d}~0 0 dS )hzGuardar documento del usuariou   🔍 Iniciando save_document...u   📝 Datos recibidos: r,   zNo se recibieron datos JSONrA   c                 3   s   | ]}| v V  qd S r5   r    r6   r9   r    r!   r;   b  r<   z save_document.<locals>.<genexpr>)titulo	contenidoz+Faltan datos requeridos: titulo y contenidor   r          El título no puede estar vacío2   )   El título no puede exceder 50 caracteresu+   ✅ Validación inicial pasada - Título: 'z', Contenido: z caracteresN
audio/mpegrE   r.   u   ✅ Conexión a BD establecidaTr`   re   u   ✅ Configuraciones obtenidas: z itemsrf   rg   rh   rM   rI   rG   rH   g      ?u   ✅ Configuración TTS - Voz: z, Velocidad: z+http://localhost:5000/api/synthesize-speech)text
voice_typespeed   )rU   timeoutu   📡 Respuesta TTS - Status: r+   u   📡 Datos TTS: r'   Z
documento_   z%Y%m%d_%H%M%S_z.mp3r   r   assetsaudioexist_okz/static/assets/audio/	audio_urlz/static/rn   u"   ⚠️ Error eliminando temporal: u$   ❌ Archivo temporal no encontrado: u*   🌐 Descargando audio desde URL externa: )r   wbu   ❌ Error descargando audio: u   ❌ Error en síntesis TTS: u   ❌ Error llamando a TTS: z - u   ❌ Error de red con TTS: u   ❌ Error generando audio: r   u   🔒 Cursor cerradou   🔒 Cursor config cerradou   🔒 Conexión cerradazDESCRIBE Documentosu!   📊 Estructura tabla Documentos:z   - u   💾 Insertando documento...z   - usuario_id: z   - titulo: ''z   - contenido: z charsz   - nombre_archivo: 'z   - tipo_mime: 'z   - archivo_audio: 'u      - tamaño_archivo: z bytesa  
                                INSERT INTO Documentos 
                                    (usuario_id, titulo, contenido, nombre_archivo, tipo_mime, archivo_audio) 
                                            VALUES (%s, %s, %s, %s, %s, %s)
                                        u    ✅ Documento insertado con ID: z	con audioz	sin audioz Documento guardado exitosamente )r(   r)   document_id	has_audioaudio_filename
audio_pathr   u   📤 Enviando respuesta: rP   u   ❌ Error de MySQL: u   ❌ Error code: u   ❌ SQL State: rQ   u$   ❌ Error general en save_document: zError interno del servidor: )7rT   r   rU   r   rV   rW   rY   r"   r$   r/   rO   rq   r#   rX   rr   r   requestsZpostZstatus_coder   uuidZuuid4hexr   nowstrftimeosro   joinproject_rootmakedirsr   lstripexistsshutilZcopy2remover1   openwriteZcontentr   Z
exceptionsZRequestException	traceback	print_excgetsizer]   r%   r   r   r   errnoZsqlstater2   )!r   r   Znombre_archivo_audioZruta_archivo_audioZruta_relativa_audio	tipo_mimer   Zcursor_configrt   rl   ru   rv   rw   r   r   Ztts_responseZtts_dataZtitulo_seguro	timestamp	audio_dirr   audio_file_pathr   Zaudio_responser   r   r$   columnscolt   tamaño_archivor   Zaudio_statusZresponse_datar    r9   r!   save_documentU  sz   


&."9

&
r   ZGETc               
   C   st  d} d}zFzt  } | sDtddidfW W |r6|  | rB|   S | jdd}|dtjf | }|D ]4}|d r|d  |d< |d	 rl|d	  |d	< qltd
|ddfW W |r|  | r|   S  t	j
jy0 } zDtddt| idfW  Y d}~W |r|  | r&|   S d}~0 0 W |rB|  | rp|   n|r`|  | rn|   0 dS )zObtener Documentos del usuarioNr,   rE   r.   Tr`   aD  
            SELECT id, titulo, contenido, 
                   CASE WHEN archivo_audio IS NOT NULL THEN TRUE ELSE FALSE END as has_audio,
                   nombre_archivo, tipo_mime, creado_en, actualizado_en 
            FROM Documentos 
            WHERE usuario_id = %s 
            ORDER BY actualizado_en DESC
        	creado_enactualizado_enr'   )r(   	documentsr+   rQ   r"   r   r#   r$   r/   r   rO   rq   	isoformatr   r   r   r2   )r   r$   r   docr   r    r    r!   get_user_documents5  s^    	&
r   z /api/documents/<int:document_id>c              
   C   s  d}d}znzt  }|sDtddidfW W |r6|  |rB|  S |jdd}|d| tjf | }|stddid	fW W |r|  |r|  S |d
 r|d
  |d
< |d r|d  |d< td|ddfW W |r|  |r|  S  t	j
jyX } zDtddt| idfW  Y d}~W |r@|  |rN|  S d}~0 0 W |rj|  |r|  n|r|  |r|  0 dS )u    Obtener un documento específicoNr,   rE   r.   Tr`   a&  
            SELECT id, titulo, contenido, 
                   CASE WHEN archivo_audio IS NOT NULL THEN TRUE ELSE FALSE END as has_audio,
                   nombre_archivo, tipo_mime, creado_en, actualizado_en 
            FROM Documentos 
            WHERE id = %s AND usuario_id = %s
        Documento no encontrado  r   r   r'   )r(   documentr+   rQ   r"   r   r#   r$   r/   r   rO   r0   r   r   r   r   r2   )r   r   r$   r   r   r    r    r!   get_documentb  sj     &
r   z&/api/documents/<int:document_id>/audioc              
   C   s@  d}d}zzt  }|sFtddidfW W |r8|  |rD|  S | }|d| tjf | }|stddidfW W |r|  |r|  S |\}}}|rtj	
tdd	d
d|}tj	|rttj	
tdd	d
d||pdddW W |r|  |r|  S |rlddlm} |||p,dd|p6d dddd}	|	W W |r\|  |rj|  S tddidfW W |r|  |r|  S  tjjy }
 zDtddt|
 idfW  Y d}
~
W |r|  |r|  S d}
~
0 0 W |r|  |r<|  n|r,|  |r:|  0 dS )u,   Obtener el audio de un documento específicoNr,   rE   r.   z
            SELECT nombre_archivo, tipo_mime, archivo_audio
            FROM Documentos 
            WHERE id = %s AND usuario_id = %s AND (nombre_archivo IS NOT NULL OR archivo_audio IS NOT NULL)
        Audio no encontrador   r   r   r   r   r   F)mimetypeZas_attachmentr   Responsezinline; filename="z	audio.mp3"public, max-age=3600zContent-DispositionzCache-Controlr   r   Audio no disponiblerQ   )r"   r   r#   r$   r/   r   rO   r0   r   ro   r   r   r   r   flaskr   r   r   r   r2   )r   r   r$   r*   nombre_archivor   archivo_audior   r   rx   r   r    r    r!   get_document_audio  s    /!
&
r   ZPUTc           	   
   C   s  t j}|stddidfS d}d}zzt }|s`tddidfW W |rR|  |r^|  S | }|d| t jf | stddid	fW W |r|  |r|  S g }g }d
|v rZ|d
 	 }t
|dk rtddidfW W |r|  |r|  S t
|dkrFtddidfW W |r6|  |rD|  S |d || d|v r||d ||d  d|v r|d ||d  |stddidfW W |r|  |r|  S ||  |t j dd| d}||| |  tddddfW W |r2|  |r@|  S  tjjy } zDtddt| idfW  Y d}~W |r|  |r|  S d}~0 0 W |r|  |r|  n|r|  |r|  0 dS )z Actualizar documento del usuarior,   No se proporcionaron datosrA   NrE   r.   z;SELECT id FROM Documentos WHERE id = %s AND usuario_id = %sr   r   r   r   r   r   r   ztitulo = %sr   zcontenido = %sr   archivo_audio = %sNo hay campos para actualizarzUPDATE Documentos SET , " WHERE id = %s AND usuario_id = %sr'   "Documento actualizado exitosamenter-   r+   rQ   r   rU   r   r"   r#   r$   r/   rO   r0   rW   rY   appendr   r%   r   r   r   r2   )	r   r:   r   r$   update_fieldsvaluesr   queryr   r    r    r!   update_document  s    1)
 






&
r   ZDELETEc              
   C   sn  d}d}z@zt  }|sDtddidfW W |r6|  |rB|  S | }|d| tjf |jdkrtddidfW W |r|  |r|  S |  td	d
ddfW W |r|  |r|  S  t	j
jy* } zDtddt| idfW  Y d}~W |r|  |r |  S d}~0 0 W |r<|  |rj|  n|rZ|  |rh|  0 dS )zEliminar documento del usuarioNr,   rE   r.   z8DELETE FROM Documentos WHERE id = %s AND usuario_id = %sr   r   r   r'   z Documento eliminado exitosamenter-   r+   rQ   r"   r   r#   r$   r/   r   rO   Zrowcountr%   r   r   r   r2   )r   r   r$   r   r    r    r!   delete_document  sb    
&
r   z/api/audio-transcriptionsc            	   
   C   s  t d tjd} tjd}tjd}t d t d|   t d|d d  d	 t d
|rfdnd  | rx|st d tddidfS |  } | }t| dk rt d tddidfS t| dkrt d tddidfS d }|rzbt|  d}t	j
tdddd|}t	j
|}t	j|dd t d|  || t d W nZ ty } z@t d t|j d!|  tdd"t| id#fW  Y d }~S d }~0 0 d }d }zzt }|st d$ tdd%id#fW W |r|  |r |  S | }t d& |d'tj||| f |  t d( td)d*d+d,fW W |rZ|  |rh|  S  tjjy } zRt d-|  tdd.t| id#fW  Y d }~W |r|  |r|  S d }~0  tyB } zRt d/|  tdd0t| id#fW  Y d }~W |r*|  |r8|  S d }~0 0 W |rT|  |r|  n|rr|  |r|  0 d S )1Nu5   🔧 Iniciando guardado de transcripción de audio...r   texto_transcritor   u   📄 Datos recibidos:u      - Título: z   - Texto: r   r}   z   - Archivo de audio: u   SíZNou   ❌ Faltan datos requeridosr,   u3   Faltan datos requeridos: título o texto transcritorA   r   u   ❌ Título vacíor      u   ❌ Título demasiado largou*   El título no puede exceder 255 caracteresz.webmr   r   r   r   Tr   u   💾 Guardando audio en: u   ✅ Audio guardado exitosamenteu*   ❌ Error al guardar el archivo de audio: z: zNo se pudo guardar el audio: r.   u)   ❌ Error de conexión a la base de datosrE   u&   🗄️ Insertando en base de datos...z
            INSERT INTO Audio_a_Texto (usuario_id, archivo_audio, texto_transcrito, nombre_transcripcion)
            VALUES (%s, %s, %s, %s)
        u!   ✅ Transcripción guardada en BDr'   u$   Transcripción guardada exitosamenter-   rP   u   ❌ Error en base de datos: rQ   u   ❌ Error inesperado: rR   )rT   r   Zformr   filesr   rW   rY   r   r   ro   r   r   dirnamer   saver1   typer   r2   r"   r#   r$   r/   rO   r%   r   r   r   )	r   r   Z
audio_filer   r   r   r   r   r$   r    r    r!   save_audio_transcription5  s    
0&
&
r   c               
   C   st  d} d}zFzt  } | sDtddidfW W |r6|  | rB|   S | jdd}|dtjf | }|D ]4}|d r|d  |d< |d	 rl|d	  |d	< qltd
|ddfW W |r|  | r|   S  t	j
jy0 } zDtddt| idfW  Y d}~W |r|  | r&|   S d}~0 0 W |rB|  | rp|   n|r`|  | rn|   0 dS )z,Obtener transcripciones de audio del usuarioNr,   rE   r.   Tr`   z
            SELECT id, nombre_transcripcion, creado_en, actualizado_en
            FROM Audio_a_Texto
            WHERE usuario_id = %s
            ORDER BY actualizado_en DESC
        r   r   r'   )r(   transcriptionsr+   rQ   r   )r   r$   r   transr   r    r    r!   get_user_audio_transcriptions  s^    &
r   z0/api/audio-transcriptions/<int:transcription_id>c              
   C   s  d}d}znzt  }|sDtddidfW W |r6|  |rB|  S |jdd}|d| tjf | }|stddid	fW W |r|  |r|  S |d
 r|d
  |d
< |d r|d  |d< td|ddfW W |r|  |r|  S  t	j
jyX } zDtddt| idfW  Y d}~W |r@|  |rN|  S d}~0 0 W |rj|  |r|  n|r|  |r|  0 dS )u&   Obtener una transcripción específicaNr,   rE   r.   Tr`   z
            SELECT id, nombre_transcripcion, texto_transcrito, creado_en, actualizado_en
            FROM Audio_a_Texto
            WHERE id = %s AND usuario_id = %s
           Transcripción no encontradar   r   r   r'   )r(   transcriptionr+   rQ   r   )transcription_idr   r$   r   r   r    r    r!   get_audio_transcription  sj    &
r   z6/api/audio-transcriptions/<int:transcription_id>/audioc              
   C   s  d}d}zzt  }|sFtddidfW W |r8|  |rD|  S | }|d| tjf | }|stddidfW W |r|  |r|  S |d }|rdd	lm	} ||d
d|  dddd}|W W |r|  |r|  S tddidfW W |r|  |r|  S  t
jjy| } zDtddt| idfW  Y d}~W |rd|  |rr|  S d}~0 0 W |r|  |r|  n|r|  |r|  0 dS )u2   Obtener el audio de una transcripción específicaNr,   rE   r.   zw
            SELECT archivo_audio
            FROM Audio_a_Texto
            WHERE id = %s AND usuario_id = %s
        r   r   r   r   r   zinline; filename="audio_z.mp3"r   r   r   r   rQ   )r"   r   r#   r$   r/   r   rO   r0   r   r   r   r   r   r2   )r   r   r$   r*   r   r   rx   r   r    r    r!   get_audio_transcription_audio  sx    #
&
r   c           	   
   C   s  t j}|stddidfS d}d}zzt }|s`tddidfW W |rR|  |r^|  S | }|d| t jf | stddid	fW W |r|  |r|  S g }g }d
|v rZ|d
 	 }t
|dk rtddidfW W |r|  |r|  S t
|dkrFtddidfW W |r6|  |rD|  S |d || d|v r||d ||d  d|v r|d ||d  |stddidfW W |r|  |r|  S ||  |t j dd| d}||| |  tddddfW W |r2|  |r@|  S  tjjy } zDtddt| idfW  Y d}~W |r|  |r|  S d}~0 0 W |r|  |r|  n|r|  |r|  0 dS )u.   Actualizar transcripción de audio del usuarior,   r   rA   NrE   r.   z>SELECT id FROM Audio_a_Texto WHERE id = %s AND usuario_id = %sr   r   nombre_transcripcionr   u4   El nombre de la transcripción no puede estar vacíor   u=   El nombre de la transcripción no puede exceder 50 caracteresznombre_transcripcion = %sr   ztexto_transcrito = %sr   r   r   zUPDATE Audio_a_Texto SET r   r   r'   r   r-   r+   rQ   r   )	r   r:   r   r$   r   r   r   r   r   r    r    r!   update_audio_transcription  s    1)
 






&
r   c              
   C   sn  d}d}z@zt  }|sDtddidfW W |r6|  |rB|  S | }|d| tjf |jdkrtddidfW W |r|  |r|  S |  td	d
ddfW W |r|  |r|  S  t	j
jy* } zDtddt| idfW  Y d}~W |r|  |r |  S d}~0 0 W |r<|  |rj|  n|rZ|  |rh|  0 dS )u'   Eliminar una transcripción del usuarioNr,   rE   r.   z;DELETE FROM Audio_a_Texto WHERE id = %s AND usuario_id = %sr   r   r   r'   u%   Transcripción eliminada exitosamenter-   r+   rQ   r   )r   r   r$   r   r    r    r!   delete_audio_transcriptionY  sb    
&
r   z/api/user/configc            	   
   C   s  d} d}z~zt  } | sDtddidfW W |r6|  | rB|   S | jdd}|dtjf | }|dtjf | }i }|D ]L}|d	 }|d
 }|dv r|	 dk||< q|dkrt
|||< q|||< qtd||ddfW W |r|  | r|   S  tjjyh } zDtddt| idfW  Y d}~W |rP|  | r^|   S d}~0 0 W |rz|  | r|   n|r|  | r|   0 dS )u"   Obtener configuración del usuarioNr,   rE   r.   Tr`   zVSELECT id, nombre_usuario, correo_electronico, foto_perfil FROM Usuarios WHERE id = %sre   rf   rg   rh   rM   rI   r'   )r(   rk   rl   r+   rQ   )r"   r   r#   r$   r/   r   rO   r0   rq   rX   rr   r   r   r   r2   )	r   r$   rk   rt   rl   ru   rv   rw   r   r    r    r!   get_user_config~  sh    #
	&
r   c               
   C   s  t j} d}d}znzt }|sJtddidfW W |r<|  |rH|  S | }|  D ]l\}}t|trz|rtdnd}nt	|}|
dt j|f | r|
d|t j|f qZ|
d	t j||f qZ|  td
dddfW W |r|  |r|  S  tjjy^ } zDtddt	| idfW  Y d}~W |rF|  |rT|  S d}~0 0 W |rp|  |r|  n|r|  |r|  0 dS )u%   Actualizar configuración del usuarioNr,   rE   r.   rM   rK   zZSELECT id FROM Configuraciones_Usuario WHERE usuario_id = %s AND nombre_configuracion = %sz
                    UPDATE Configuraciones_Usuario 
                    SET valor_configuracion = %s 
                    WHERE usuario_id = %s AND nombre_configuracion = %s
                rN   r'   u'   Configuración actualizada exitosamenter-   r+   rQ   )r   rU   r"   r   r#   r$   items
isinstanceboolr2   r/   rO   r0   r%   r   r   r   )r:   r   r$   rv   rw   Z	str_valuer   r    r    r!   update_user_config  sl    (


&
r   rn   c                   C   s   t dS )u   Página de loginz
login.htmlr   r    r    r    r!   index  s    r   z/modo_visualc                   C   s   t dS )u$   Página del asistente en modo visualzModo_Visual.htmlr   r    r    r    r!   r     s    r   z/modo_auditivoc                   C   s   t dS )u&   Página del asistente en modo auditivozModo_Auditivo.htmlr   r    r    r    r!   r     s    r   z/bibliotecac                   C   s   t dS )u$   Página de la biblioteca de recursoszlibrary.htmlr   r    r    r    r!   r     s    r   z/configuracionc                   C   s   t dS )u   Página de configuraciónzconfig.htmlr   r    r    r    r!   r     s    r   z/inicioc                   C   s   t dS )u$   Página principal después del loginz
index.htmlr   r    r    r    r!   r     s    r   z/leer-archivoc            
   
   C   s  dt jvrtddidfS t jd } | jdkr>tddidfS | j }d}z|drh|  d	}n|d
rtj	
td}| | ddlm} ||}d}|jD ]}| }|r||7 }qnH|drtj	
td}| | ddl}||}ntddidfW S |r*tj	|r*t| td| j| ddfW S  ty }	 zh|rtj	|rzt| W n   Y n0 tdt|	  tddt|	 idfW  Y d}	~	S d}	~	0 0 dS )z"Leer contenido de archivos subidosfiler,   u%   No se ha seleccionado ningún archivorA    u   Archivo vacíoNz.txtrF   z.pdfztemp.pdfr   r   z.docxz	temp.docxz,Formato no soportado. Usa .txt, .pdf o .docxr'   )r(   nombreZtextor+   u   ❌ Error procesando archivo: zError al leer el archivo: r.   )r   r   r   filenamerX   endswithreadr\   r   ro   r   TEMP_DIRr   PyPDF2r   ZpagesZextract_textdocx2txtprocessr   r   rW   r1   rT   r2   )
Zarchivor  Z	temp_pathr   r   readerZpager   r	  r   r    r    r!   leer_archivo	  sV    










r  z/healthc                  C   s:   t  } | rdnd}| r|   tdt  |ddfS )zHealth check endpointZ	connectedZdisconnectedZhealthy)r(   r   r   r+   )r"   r#   r   r   r   r   )r   Z	db_statusr    r    r!   health_checkD  s    
r  z/api/library-itemsc            	      C   s&  t tdrtjs(td tddidfS d } d }zАz6t } | sntddidfW W |r`|  | rl|   S | jdd	}z.|d
tjf |	 }tdt
|  W n6 ty } ztd|  g }W Y d }~n
d }~0 0 z.|dtjf |	 }tdt
|  W n8 tyF } ztd|  g }W Y d }~n
d }~0 0 g }|D ]f}||d |d |d dt|d |d r|d  nd |d r|d  nd |d d qP|D ]l}||d |d pd|d dt|d |d r|d  nd |d r|d  nd |d d q|jdd dd td|d d!fW W |r^|  | rl|   S  ty } z\td"t|  d#d l}|  tdd$idfW  Y d }~W |r|  | r|   S d }~0 0 W |r|  | r"|   n|r|  | r |   0 d S )%NrO   u3   ❌ Error: request.user_id no está definido o es 0r,   z$Usuario no autenticado correctamentera   rE   r.   Tr`   a  
                SELECT 
                    id, 
                    titulo, 
                    contenido, 
                    creado_en, 
                    actualizado_en,
                    archivo_audio IS NOT NULL as has_audio,
                    nombre_archivo
                FROM Documentos
                WHERE usuario_id = %s
                ORDER BY actualizado_en DESC
            u   📄 Documentos encontrados: u"   ❌ Error en consulta Documentos: a  
                SELECT 
                    id, 
                    nombre_transcripcion as titulo, 
                    texto_transcrito as contenido, 
                    creado_en, 
                    actualizado_en, 
                    archivo_audio
                FROM Audio_a_Texto
                WHERE usuario_id = %s
                ORDER BY actualizado_en DESC
            u"   🎧 Transcripciones encontradas: u%   ❌ Error en consulta Audio_a_Texto: rb   r   r   Z	documentor   r   r   r   )rb   r   r   Ztipor   r   r   r   u   Sin títuloZtranscripcionr   c                 S   s   | d p
dS )Nr   r  r    )xr    r    r!   <lambda>  r<   z#get_library_items.<locals>.<lambda>)rv   reverser'   )r(   r   r+   u)   ❌ Error general en /api/library-items: r   zError interno del servidor)hasattrr   rO   rT   r   r"   r#   r$   r/   rq   rY   r1   r   r   r   sortr2   r   r   )	r   r$   Z
documentosr   Ztranscripcionesr   r   r   r   r    r    r!   get_library_itemsS  s    W


r  )MIMEText)MIMEMultipartz/enviar-soportec               
   C   s  t  } d}d}d}d}d}t }||d< ||d< d| d  |d	< d
| d  d| d  d| d  d| d  d	}|t|d zHt||}||| | }	|	|||	 |
  tddidfW S  ty }
 z0tdt|
 tdt|
ddfW  Y d }
~
S d }
~
0 0 d S )Nzwebmaster@asistenteauris.com.coz	Auris25$$zsmtp.mi.com.coi  ZFromZToz[Soporte Auris] ZasuntoZSubjectz?
    Nuevo mensaje de soporte desde la app Auris:

    Nombre: r  z
    Email: Zemailz
    Asunto: z

    Mensaje:
    Zmensajez
    Zplainr'   Tr+   zError al enviar:F)r'   r,   r.   )r   Zget_jsonr  Zattachr  smtplibZSMTP_SSLry   Z	as_stringZsendmailquitr   r1   rT   r2   )r:   Zsender_emailZsender_passwordZrecipient_emailZsmtp_serverZ	smtp_portmsgbodyZserverr   r   r    r    r!   enviar_soporte  s<    r  __main__u#   🚀 Iniciando aplicación Auris...u,   ✅ Base de datos inicializada correctamenteu)   ⚠️ Error al inicializar base de datosZPORTi  u&   🌐 Servidor ejecutándose en puerto Z	FLASK_ENVZdevelopmentz0.0.0.0)r   r   debug)a__doc__r   sysrU   Zmysql.connectorr   r   r   r   r   r   r   r   r   r	   r
   Z
flask_corsr   rZ   rp   r	  Ztempfiler  r   Zwerkzeug.utilsr   base64r   r   r   Zasyncioro   r   __file__r   r   Ztemplate_dirZ
static_dirr  r   appZnew_event_loopZloopZset_event_loopZbackend.routes.tts_routesr   Zregister_blueprintZbackend.routes.edge_tts_routesr   environr   Z
secret_keyintr   r   r   r"   r&   Zrouter3   r_   ry   rz   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  Zemail.mime.textr  Zemail.mime.multipartr  r  rT   r   Z
debug_moderunr    r    r    r!   <module>   s  $



O
T$ _+,;B"V)*/B#/8






:
g
-

