
    ˘h*>                         d dl Z d dl 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	 d dl
mZmZmZmZ d dlZd dlZ ej"                  d      Zd	Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zy)    N)web)desc)select)IntegrityError)datetime)async_sessionAgentCallSession
CallStatusserver
recordingsc           	        K   t               4 d {   }|j                  t        t                     d {   }|j	                         j                         }i }|D ]T  }|j                  |j                  |j                  |j                  |j                  |j                  d||j                  <   V t        j                  |      cd d d       d {    S 7 7 7 	# 1 d {  7  sw Y   y xY ww)N)idnamemodelvoiceinstructionsturn_detection)r   executer   r	   scalarsallr   r   r   r   r   turn_detection_settingsr   json_response)requestsessionresultagentsresponse_dataagents         /app/routes.pylist_agentsr!      s     've}55!%%'Ehh

U[[SXS^S^ % 2 2eFcFc)M%**% 
   / 5 sU   C6CC6"C!CBC!	C6CC6C!C6!C3'C*(C3/C6c                   K   	 | j                   j                  dd      }t               4 d{   }|j                  t	        t
              j                  t
        j                  |k(               d{   }|j                         }ddd      d{    st        j                  ddid      S | j                  d   }d	}d
| dd}|j                  |j                  |j                  |j                  ddid}t!        j"                         4 d{   }	|	j%                  |||      4 d{   }
|
j'                          d{   }|
j(                  dk\  r[t*        j-                  d|        t        j                  ||
j(                        cddd      d{    cddd      d{    S t*        j/                  d| d       t        j                  |      cddd      d{    cddd      d{    S 7 7 7 }# 1 d{  7  sw Y   xY w7 7 7 7 7 }7 @7 1# 1 d{  7  sw Y   nxY wddd      d{  7   y# 1 d{  7  sw Y   yxY w# t0        $ rA}t*        j3                  d       t        j                  dt5        |      id      cY d}~S d}~ww xY ww)u   Проксирует запрос к OpenAI для получения ephemeral key. НЕ СОХРАНЯЕТ СЕССИЮ В БД.r   defaultNerrorAgent not found  statusOPENAI_API_KEYz+https://api.openai.com/v1/realtime/sessionsBearer zapplication/jsonAuthorizationzContent-Typer   z	whisper-1)r   r   r   r   input_audio_transcription)headersjson  u>   Ошибка OpenAI API при создании сессии: u   Для агента u    выдан ephemeral key.u`   Ошибка при проксировании запроса на создание сессии  )querygetr   r   r   r	   wherer   scalar_one_or_noner   r   appr   r   r   r   aiohttpClientSessionpostr/   r(   loggerr$   info	Exception	exceptionstr)r   	agent_keyr   r   r   r)   urlr.   bodyhttp_sessionrespes               r    create_sessionrE      s6    @MM%%gy9	 ??g"??6%=+>+>uzzY?V+WXXF--/E #? S..9J/KTWXX %56;&-n-=$>Pbc[[5;;!..%B_B_*1;)?
 ((**l#((gD(IIT#yy{*;;#%LL#abhai!jk,,VDKKH	 JII +** 29+=WXY((0 JII +** #X #??? +I* J +I +III +****  @{|  '3q6!23??@s  K*I5 HI5 AH4H5H	I5 HI5 3K4A#I5 H*I5 I 4H-5I 8H9H/AH9I $H1%I )I5 5H36I5 :K;-H9(I 4H55I 9I5 H7I5 
KI5 HI5 H'HH'"	I5 -I /H91I 3I5 5I 7I5 9I	?I I	I I5 II5 K I2&I)'I2.I5 1K2I5 5	J?>6J:4J?5K:J??Kc                   K   	 | j                          d {   }t        |d   |j                  dd      |d   |d   |d         }t               4 d {   }|j	                  |       |j                          d {    d d d       d {    t        j                  d|d    d	       t        j                  d
|d   dd      S 7 7 x7 Q7 C# 1 d {  7  sw Y   SxY w# t        $ r# t        j                  ddd    did      cY S t        $ rA}t        j                  d       t        j                  dt        |      id      cY d }~S d }~ww xY ww)Nr   r   zgpt-4o-realtime-previewr   r   r   )r   r   r   r   r   u0   АДМИН: Создан новый агент ''createdr(   r      r'   r$   zAgent with name 'z' already existsi  u1   Ошибка при создании агентаr0   )r/   r	   r3   r   addcommitr:   r;   r   r   r   r<   r=   r>   )r   data	new_agentr   rD   s        r    create_agentrO   B   sC    @\\^#fTXXg7P%Qw-d>.B$()9$:
	
 !??gKK	"..""" #? 	FtF|nTUVW  ItF|!LUXYY $ #" #???
 ~#"3"3W@QRVW]R^Q__o>p4qz}"~~ @LM  '3q6!23??@s   E!C* C>C* CC* %C?C CC* C<C* E!C* C* CC* C'CC'#C* *)EE!E6EEE!EE!c                 (  K   | j                   d   }	 | j                          d{   }t               4 d{   }|j                  t	        t
              j                  t
        j                  |k(               d{   }|j                         }|s*t        j                  ddid      cddd      d{    S |j                  d|j                        |_        |j                  d|j                        |_        |j                  d	|j                        |_        |j                  d
|j                        |_        |j!                          d{    t"        j%                  d| d       t        j                  d|d      cddd      d{    S 7 x7 h7 %7 7 Q7 # 1 d{  7  sw Y   yxY w# t&        $ rD}t"        j)                  d|        t        j                  dt+        |      id      cY d}~S d}~ww xY ww)u6   PUT /api/agents/{name} - Обновить агентаr   Nr$   r%   r&   r'   r   r   r   r   u)   АДМИН: Обновлен агент 'rG   updatedrI   u6   Ошибка при обновлении агента r0   )
match_infor/   r   r   r   r	   r4   r   r5   r   r   r3   r   r   r   r   rL   r:   r;   r<   r=   r>   )r   
agent_namerM   r   r   r   rD   s          r    update_agentrT   T   s    ##F+J@\\^# ??g"??6%=+>+>uzzZ?W+XYYF--/E!2!2G=N3OX[!\ #?? ((7EKK8EK((7EKK8EK!%.%:L:L!ME,0HH5EuGdGd,eE).."""KKCJ<qQR$$	:%NO #?? $"Y # # #???  @QR\Q]^_  '3q6!23??@s   HG FG F!G AF-?F$ .F-.G :F';G ?H BF-F)4F-G F+G HG !G $F-'G )F-+G -F?3F64F?;G >H?G 	H9H
HH
HHc                   K   | j                   d   }|dv rt        j                  ddid      S t               4 d {   }|j	                  t        t              j                  t        j                  |k(               d {   }|j                         }|rs|j                  |       d {    |j                          d {    t        j                  d| d       t        j                  d	|d
      cd d d       d {    S t        j                  ddid      cd d d       d {    S 7 7 7 7 v7 77 # 1 d {  7  sw Y   y xY ww)Nr   )r#   salesr$   zCannot delete default agentsr0   r'   u%   АДМИН: Удален агент 'rG   deletedrI   r%   r&   )rR   r   r   r   r   r   r	   r4   r   r5   deleterL   r:   r;   )r   rS   r   r   r   s        r    delete_agentrY   k   s    ##F+J))!!7,J"KTWX	X've}':':5::;S'TUU))+..'''.."""KK?
|1MN$$	:%NO  $$g/@%A#N U (" s   ;ED7EAED9*E.D;/ED=4E;ED?EE%E1E2E9E;E=E?EEE	E
EEc                   K   	 | j                   d   }| j                          d{   }|j                  d      }|j                  d      }|st        j                  ddid      S t               4 d{   }|j                  t        t              j                  t        j                  |k(               d{   }|j                         }|sJt        j                  d	| d
       t        ||t        j                               }|j!                  |       t        j                         |_        t$        j&                  |_        ||_        |j-                          d{    |j"                  |j.                  z
  j1                         }t        j                  d| d|dd       t        j                  ddi      cddd      d{    S 7 7 c7  7 y7 # 1 d{  7  sw Y   yxY w# t2        $ rA}	t        j5                  d       t        j                  dt7        |	      id      cY d}	~	S d}	~	ww xY ww)uw   Находит сессию по ID, обновляет ее. Если не находит - создает новую.
session_idN
transcriptrS   r$   zagent_name is requiredr0   r'   u   Сессия [u>   ] не найдена, создаем новую запись.)session_id_openairS   
start_timeuA   Сохранена транскрипция для сессии [u   ]. Длительность: ~z.2fu    сек.r(   successuA   Ошибка при сохранении транскрипцииr1   )rR   r/   r3   r   r   r   r   r   r
   r4   r]   r5   r:   r;   r   utcnowrK   end_timer   	COMPLETEDr(   r\   rL   r^   total_secondsr<   r=   r>   )
r   r[   rM   transcript_textrS   r   r   call_sessiondurationrD   s
             r    save_transcriptrg   {   s    '@''5
\\^#((<0XXl+
$$g/G%HQTUU ??g"??{#))+*G*G:*UV F "446LnZL8vwx*&0)'0 
 L) %-OO$5L!","6"6L&5L#.."""$--0G0GGVVXHKK[\f[g  hF  GO  PS  FT  T\  ]  ^$$h	%:;5 #?? $ #( #- #???8  @\^  '3q6!23??@s   I"G8 GA G8 'I(G8 6G7G8 :AG#<G=B(G#%G&AG#G8 G!G8 IG8 G8 G#G#!G8 #G5)G,*G51G8 4I5G8 8	I6H=7I8I=IIc           
        K   	 t               4 d{   }|j                  t        t              j	                  t        j
                  t        j                  k(        j                  t        t        j                              j                  d             d{   }|j                         j                         }g }|D ]  }|j                  r'|j                  |j                  z
  j                         nd}|j!                  |j"                  |j$                  |j                  j'                         t)        |      |j*                  d        t-        j.                  |      cddd      d{    S 7 f7 7 
# 1 d{  7  sw Y   yxY w# t0        $ rA}t2        j5                  d       t-        j.                  dt7        |      id      cY d}~S d}~ww xY ww)	uN   Возвращает 5 последних завершенных сессий.N   r   )r   rS   r^   duration_secondsr\   u@   Ошибка при получении списка сессийr$   r1   r'   )r   r   r   r
   r4   r(   r   rb   order_byr   r^   limitr   r   ra   rc   appendr   rS   	isoformatroundr\   r   r   r<   r:   r=   r>   )r   r   r   sessionsr   srf   rD   s           r    list_sessionsrr      s^    @ ??g"??{#{))Z-A-AAB${5567q	 F ~~'++-H MJK**AJJ5DDFZ[$$$$"#,,"#,,"8"8":(-h"#,,&   $$]3- #?? #???.  @[\  '3q6!23??@s   G!F E8F BE?E;C
E?&F 2E=3F 7G!8F ;E?=F ?FFFF G!F 	G6GGG!GG!c                 T  K   | j                   d   }| j                          d{   }d}d}d}	 |2 3 d{   }|j                  dk(  r)|j                          d{   }|j	                  d      }|j                  dv sPd| d|j                   d	}t
        j                  j                  t        |      }	t        |	d
      5 }
	 |j                          d{   }|sn|
j                  |       -	 ddd       |j                  dk(  r|	}|	}7 7 7 7 =# 1 sw Y   &xY w6 |r|st        j                  ddid      |r4t
        j                  j                  |      rt        j                  |       |r6t
        j                  j                  |      rt        j                  |       S S S t!        j"                         j%                  d      }| d| d}t
        j                  j                  t        |      }t'        j(                  |      }t'        j(                  |      }t'        j*                  ||gdd      }t'        j,                  ||d      j/                  d       t0        j3                  d|        t5               4 d{  7  }|j7                  t9        t:              j=                  t:        j>                  |k(               d{  7  }|jA                         }|r||_!        |jE                          d{  7   t0        j3                  d| d       t        j                  ddi      cddd      d{  7   |r4t
        j                  j                  |      rt        j                  |       |r6t
        j                  j                  |      rt        j                  |       S S S t0        jG                  d|        t        j                  ddid      cddd      d{  7   |r4t
        j                  j                  |      rt        j                  |       |r6t
        j                  j                  |      rt        j                  |       S S S # 1 d{  7  sw Y   nxY wn# tH        $ r}t0        jK                  d        t        j                  dtM        |      id!      cY d}~|r4t
        j                  j                  |      rt        j                  |       |r6t
        j                  j                  |      rt        j                  |       S S S d}~ww xY w	 |r4t
        j                  j                  |      rt        j                  |       |r6t
        j                  j                  |      rt        j                  |       yyy# |r4t
        j                  j                  |      rt        j                  |       |r6t
        j                  j                  |      rt        j                  |       w w w xY ww)"ul   Принимает два аудиофайла, объединяет их в один и сохраняет.r[   Nunknown_agentrS   zutf-8)
user_audioai_audiotemp__z.webmwbTru   r$   z/Both user_audio and ai_audio files are requiredr0   r'   z%d-%m_%H-%Mz.mp3amerge   )inputs)ac)overwrite_outputuA   Аудиофайлы объединены и сохранены: uG   Путь к объединенному аудио для сессии [u   ] обновлен.r(   audio_merged_and_savedu_   Попытка сохранить аудио для несуществующей сессии: zSession not foundr&   uK   Ошибка при обработке и объединении аудиоr1   )'rR   	multipartr   readdecodeospathjoinRECORDINGS_DIRopen
read_chunkwriter   r   existsremover   nowstrftimeffmpeginputfilteroutputrunr:   r;   r   r   r   r
   r4   r]   r5   combined_audio_pathrL   warningr<   r=   r>   )r   r[   readertemp_user_pathtemp_ai_pathrS   fieldagent_name_bytestemp_filenametemp_filepathfchunk	timestampoutput_filenameoutput_path
input_userinput_aimergedr   r   re   rD   s                         r    upload_audio_recordingsr      s    ##L1J$$&&FNL J=$! 	1%zz\)).#5 -44W=
zz77"'
|1UZZL F "^] K-.!&+&6&6&8 8$e &+ / ::-%2N#0L7 '	1 $6 !9 /. "* \$$g/`%ajmnD bggnn^<IIn%BGGNN<8IIl# 9<A LLN++M:	'L)D9ggll>?C\\.1
<<-
H5xJfka044d4KWXcWdef !??g"??6++>+D+D[EbEbfpEp+qrrrF!446L3>0nn&&&efpeq  rE  F  G(((4L)MN #??" bggnn^<IIn%BGGNN<8IIl# 9<   "A  BL  AM   N  O(('3F)GPST #??" bggnn^<IIn%BGGNN<8IIl# 9<' #???  @fg  '3q6!23?? bggnn^<IIn%BGGNN<8IIl# 9<@ #" bggnn^<IIn%BGGNN<8IIl# 9< bggnn^<IIn%BGGNN<8IIl# 9<sE  #X(D
X(R
 D'DD'#R
 D#R
 AR
 DDD6R
 X(D'R
 DD$	 $R
 A/X(3C!R
 JR
 AQ4K1Q4L4Q4R
 MR
 A/X(0Q43R
 ?P R
 A/X(4R:Q=;RR
 	V5 
	U6T=	U
V5 A/X(=UV5 A/X(5A0X%%X(c                 d  K   	 | j                   j                  dd      j                  dd      }|st        j                  ddid      S | j                          d{   }d	}d| d
d}t        j                         4 d{   }|j                  |||      4 d{   }|j                  dk\  r|j                          d{   }t        j                  d|j                   d|        t        j                  ||j                  |j                        cddd      d{    cddd      d{    S |j                          d{   }t        j                  |dd
      cddd      d{    cddd      d{    S 7 57 7 7 7 r7 c7 L7 &7 # 1 d{  7  sw Y   nxY wddd      d{  7   y# 1 d{  7  sw Y   yxY w# t        $ rA}	t        j                  d       t        j                  dt!        |	      id      cY d}	~	S d}	~	ww xY ww)u   
    Принимает SDP-offer от клиента и ephemeral_key,
    проксирует запрос в OpenAI и возвращает их ответ.
    r,    r*   r$   z3Authorization header with ephemeral key is requiredr0   r'   Nz@https://api.openai.com/v1/realtime?model=gpt-4o-realtime-previewzapplication/sdpr+   )r.   rM   u@   Ошибка проксирования в OpenAI Realtime API: z - )textr(   content_type   uD   Критическая ошибка в прокси-хэндлереr1   )r.   r3   replacer   r   r   r7   r8   r9   r(   r:   r$   Responser   r<   r=   r>   )
r   ephemeral_key	offer_sdpr@   r.   rB   rC   
error_text
answer_sdprD   s
             r    proxy_realtime_requestr     s    
@++OR@HHTVW$$g/d%enqrr!,,.(	P&}o6-

 ((**l#((gI(NNRV;;#%'+yy{!2JLL#cdhdodocppst~s  "A  B<<ZZ^ZkZkl	 ONN +** $(99;.
||CN_` ONN +** ) +N!2 O + / O +NNN +****  @_`  '3q6!23??@sh  H0AG# 
H0G# F&G# FG# 	G"F#G&#F'	F
AF'G*F+G/G# ;F<G#  H0F'F!F'0G<F#=GG# F%G# H0G# G# GF'GG# !F'#G%G# 'F9	-F0.F9	5G<G# G
G# H0G GG G# H0 G# #	H-,6H("H-#H0(H--H0c                 n   | j                   j                  dt               | j                   j                  dt               | j                   j	                  dt
               | j                   j                  dt               | j                   j	                  dt               | j                   j	                  dt               | j                   j	                  dt               | j                   j                  dt               | j                   j                  dt               t        j                  d       y )	Nz/api/agentsz/api/sessionz%/api/sessions/{session_id}/transcriptz/api/sessionsz%/api/sessions/{session_id}/recordingsz/api/realtimez/api/agents/{name}u"   Роуты API настроены.)routeradd_getr!   rE   add_postrg   rr   r   r   rO   add_putrT   
add_deleterY   r:   r;   )r6   s    r    setup_routesr   /  s    JJ}k2JJ~~6JJ?QJJ6JJ?AXYJJ)?@JJ|4JJ+\:JJ.=
KK45    )r7   r   logging
sqlalchemyr   sqlalchemy.futurer   sqlalchemy.excr   r   databaser   r	   r
   r   r   r   	getLoggerr:   r   r!   rE   rO   rT   rY   rg   rr   r   r   r    r   r    <module>r      s}        $ )  B B 	 			8	$0@F@$@.O )@V@>F$P@D6r   