
    g3                        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mZ d dl	m
Z
 d dlmZmZmZ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mZmZ ddlm Z  ddl!m"Z"m#Z#  ejH                  e%      Z&defdZ' G d d      Z(y)    N)	b64decode)datetime)wraps)floor)AnyCallableDictListOptional   )NotConnectedError)Message)http_endpoint_url)DEFAULT_TIMEOUTPHOENIX_CHANNELCallbackChannelEventsT_ParamSpecT_Retval)	is_ws_url   )AsyncRealtimeChannelRealtimeChannelOptionsfuncc                 |     t               dt        j                  dt        j                  dt        f fd       }|S )Nargskwargsreturnc                  \    | d   j                   st        j                         | i |S Nr   )is_connectedr   __name__)r   r   r   s     K/var/www/openai/venv/lib/python3.12/site-packages/realtime/_async/client.pywrapperz"ensure_connection.<locals>.wrapper   s/    Aw###DMM22T$V$$    )r   r   r   r   r   )r   r$   s   ` r#   ensure_connectionr&      sA    
4[%{'' %;3E3E %( % % Nr%   c                   .   e Zd Z	 	 	 	 	 ddedededeeeef      dedede	d	dfd
Z
ddZddZd Zd Zd Zedd       ZddZe	 d dedee   d	efd       Zd	ee   fdZded	dfdZddZddZdee   d	dfdZd	efdZdeeef   d	dfdZdefdZy)!AsyncRealtimeClientNurltokenauto_reconnectparamshb_intervalmax_retriesinitial_backoffr   c           
         t        |      st        d       t        j                  ddt        j                  dd|t        j                        t        j                         d| | _        t        |      | _        d| _        |xs i | _	        || _
        || _        g | _        || _        d	| _        d
| _        || _        i | _        || _        || _        t(        | _        y	)aY  
        Initialize a RealtimeClient instance for WebSocket communication.

        :param url: WebSocket URL of the Realtime server. Starts with `ws://` or `wss://`.
                    Also accepts default Supabase URL: `http://` or `https://`.
        :param token: Authentication token for the WebSocket connection.
        :param auto_reconnect: If True, automatically attempt to reconnect on disconnection. Defaults to False.
        :param params: Optional parameters for the connection. Defaults to an empty dictionary.
        :param hb_interval: Interval (in seconds) for sending heartbeat messages to keep the connection alive. Defaults to 30.
        :param max_retries: Maximum number of reconnection attempts. Defaults to 5.
        :param initial_backoff: Initial backoff time (in seconds) for reconnection attempts. Defaults to 1.0.
        z4url must be a valid WebSocket URL or HTTP URL stringzhttps://zwss://zhttp://zws://)flagsz/websocket?apikey=FNr   )r   
ValueErrorresub
IGNORECASEr)   r   http_endpointr!   r,   apikeyaccess_tokensend_bufferr-   ws_connectionrefr+   channelsr.   r/   r   timeout)selfr)   r*   r+   r,   r-   r.   r/   s           r#   __init__zAsyncRealtimeClient.__init__*   s    , ~MNff[(BFF:wPS[][h[h4iqsq~q~  A  AS  TY  SZ  [.s3!l!+-&RV,9;&.&r%   c                   K   	 	 | j                   j                          d{   }t        j                  d|        t	        di t        j                  |      }| j                  j                  |j                        }|r2|j                  |j                  |j                  |j                         n#t        j                  d|j                   d       7 # t        j                  j                   $ r | j"                  rjt        j                  d       | j%                          d{  7   | j                  j'                         D ]  \  }}|j)                          d{  7     nt        j+                  d       Y yY w xY ww)zN
        An infinite loop that keeps listening.
        :return: None
        Nz	receive: zChannel z
 not found5Connection with server closed, trying to reconnect..."Connection with the server closed. )r:   recvloggerinfor   jsonloadsr<   gettopic_triggereventpayloadr;   
websockets
exceptionsConnectionClosedr+   connectitemsjoin	exception)r>   msgchannelrJ   s       r#   _listenzAsyncRealtimeClient._listenR   s/    
  ..3355iu-.0

30--++CII6$$SYYSWWEKK(399+Z @A 5 ((99 &&KK WX,,.((*.--*=*=*?w%lln,, +@ $$%IJ	 +@	sR   FC CB6C FC AF	-D0.8F	&E)'F	FF		Fc                   K   d}| j                   }|| j                  k  r{	 t        j                  | j                         d{   | _        | j
                  j                  r-t        j                  d       | j                          d{   S t        d      t        d| j                   d      7 p7 *# t        $ r}|dz  }|| j                  k\  s| j                  st        j                  d| d|         |d|dz
  z  z  }t        j                  d	| d
|dd       t        j                  |       d{  7   t        |dz  d      }Y d}~nd}~ww xY w|| j                  k  rP֭w)a{  
        Establishes a WebSocket connection with exponential backoff retry mechanism.

        This method attempts to connect to the WebSocket server. If the connection fails,
        it will retry with an exponential backoff strategy up to a maximum number of retries.

        Returns:
            None

        Raises:
            Exception: If unable to establish a connection after max_retries attempts.

        Note:
            - The initial backoff time and maximum retries are set during RealtimeClient initialization.
            - The backoff time doubles after each failed attempt, up to a maximum of 60 seconds.
        r   NzConnection was successfulz#Failed to open WebSocket connectionr   z/Failed to establish WebSocket connection after z attempts: r   zConnection attempt z failed. Retrying in z.2fz seconds...<   z	 attempts)r/   r.   rN   rQ   r)   r:   openrE   rF   _on_connect	Exceptionr+   errorasynciosleepmin)r>   retriesbackoffe	wait_times        r#   rQ   zAsyncRealtimeClient.connectn   sl    " &&(((3+5+=+=dhh+G%G"%%**KK ;<!%!1!1!333#$IJJ  =d>N>N=OyY
 	
+ &H 4  31d...d6I6ILLI'R]^_]`a  '11+= >IKK-gY6KIVY?Zef "--	222!'A+r2G3 (((sl   E1"B8 B4AB8 B6B8 E1B8 E14B8 6B8 8	EA<E=E >EE1EE1c                    K   t        j                  | j                         | j                                d {    y 7 wN)r^   gatherrW   
_heartbeatr>   s    r#   listenzAsyncRealtimeClient.listen   s'     nnT\\^T__->???s   6A >A c                 N   K   d| _         | j                          d {    y 7 w)NT)r!   _flush_send_bufferri   s    r#   r[   zAsyncRealtimeClient._on_connect   s       %%'''s   %#%c                    K   | j                   rAt        | j                        dkD  r(| j                  D ]  } |        d {     g | _        y y y 7 wr    )r!   lenr9   )r>   callbacks     r#   rl   z&AsyncRealtimeClient._flush_send_buffer   sO     T%5%5!6!: ,,j   -!D "; s   >A AAc                 b   K   | j                   j                          d{    d| _        y7 w)z
        Close the WebSocket connection.

        Returns:
            None

        Raises:
            NotConnectedError: If the connection is not established when this method is called.
        NF)r:   closer!   ri   s    r#   rq   zAsyncRealtimeClient.close   s-        &&(((! 	)s   /-/c                 \  K   | j                   r	 t        t        t        j                  i d       }| j                  |       d {    t        j                  t        | j                  d             d {    d| _         | j                   ry y 7 K7 # t        j                  j                  $ r d| _         | j                  rt        j                  d       | j!                          d {  7   d| _         | j"                  j%                         D ]o  \  }}t        j                  d|        | |_        |j)                          d {  7   t        j                  t        | j                  d             d {  7   q nd| _         t        j+                  d       Y y Y &w xY ww)N)rJ   rL   rM   r;      TFrA   zRejoining to: rB   )r!   dictr   r   	heartbeatsendr^   r_   maxr-   rN   rO   rP   r+   rE   rF   rQ   r<   rR   socket_rejoinrT   )r>   datarJ   rV   s       r#   rh   zAsyncRealtimeClient._heartbeat   s[    $))'11	 iio%%mmC(8(8"$=>>>6 %)!K  &>((99 $)!&&KK WX,,.(((,D% +/--*=*=*?wnUG$<=)-%oo/// &mmC0@0@",EFFF +@ ).D%$$%IJ +@sx   F,5B B0B 6B7B ;F,F,B B AF)-C0.AF)E1F)>F?$F)#F,(F))F,rJ   c                 H    d| }t        | ||      }|| j                  |<   |S )z
        :param topic: Initializes a channel and creates a two-way association with the socket
        :return: Channel
        z	realtime:)r   r<   )r>   rJ   r,   chans       r#   rV   zAsyncRealtimeClient.channel   s1     E7##D%8#er%   c                 H    t        | j                  j                               S rf   )listr<   valuesri   s    r#   get_channelsz AsyncRealtimeClient.get_channels   s    DMM((*++r%   rV   c                 2  K   |j                   | j                  v rF| j                  |j                      j                          d{    | j                  |j                   = t        | j                        dk(  r| j	                          d{    yy7 M7 w)z
        Unsubscribes and removes a channel from the socket
        :param channel: Channel to remove
        :return: None
        Nr   )rJ   r<   unsubscribern   rq   )r>   rV   s     r#   remove_channelz"AsyncRealtimeClient.remove_channel   sw      ==DMM)--.::<<<gmm,t}}"**, # = s%   ABBABBBBc                    K   | j                   j                         D ]  \  }}|j                          d{     | j                          d{    y7 7 w)z]
        Unsubscribes and removes all channels from the socket
        :return: None
        N)r<   rR   r   rq   )r>   _rV   s      r#   remove_all_channelsz'AsyncRealtimeClient.remove_all_channels   sO     
 ----/JAw%%''' 0 jjl (s!   4AAAAAAc                     | j                   j                         D ]4  \  }}t        d| d|j                  D cg c]  \  }}|	 c}} d       6 yc c}}w )zd
        Prints a list of topics and event the socket is listening to
        :return: None
        zTopic: z | Events: ]N)r<   rR   print	listeners)r>   rJ   rV   rc   r   s        r#   summaryzAsyncRealtimeClient.summary	  sV    
 #mm113NE7GE7+W=N=N.O=NTQq=N.O-PPQRS 4.Os   Ac                   K   t        |t              r't        |j                               dk(  rt	        d      |rd}	 |j                  d      d   dz   }t        j                  t        |      j                  d            }|rXd	|v rIt        t        j                         j                               }||d	   z
  dk  }|st	        d
|d	          t	        d      || _        | j                   j#                         D ]I  \  }}|j$                  s|j&                  s |j)                  t*        j                  d|i       d{    K y# t        $ r t	        d      w xY w7 w)a  
        Set the authentication token for the connection and update all joined channels.

        This method updates the access token for the current connection and sends the new token
        to all joined channels. This is useful for refreshing authentication or changing users.

        Args:
            token (Optional[str]): The new authentication token. Can be None to remove authentication.

        Returns:
            None
        r   zProvide a valid jwt tokenN.r   z==zutf-8InvalidJWTTokenexpz>InvalidJWTToken: Invalid value for JWT claim 'exp' with value z%InvalidJWTToken: expected claim 'exp'r8   )
isinstancestrrn   stripr2   splitrG   rH   r   decoder\   r   r   now	timestampr8   r<   rR   _joined_once	is_joinedpushr   )r>   r*   parsedrM   r   validr   rV   s           r#   set_authzAsyncRealtimeClient.set_auth  sR     eS!c%++-&8A&=899F4++c*1-4Ig$6$=$=g$FG F? 8 8 :;C&-/!3E (\^dej^k\mn  %%LMM!----/JAw##(9(9ll=#=#=PU?VWWW 0#  4 !2334& Xs6   <E%AE BE%E%%E%E#E%E  E%c                 F    | xj                   dz  c_         | j                    S )Nr   )r;   ri   s    r#   	_make_refzAsyncRealtimeClient._make_ref<  s    A((r%   messagec                     K   t        j                        t        j                  d         fd} j                  r |        d{    y j
                  j                  |       y7 !w)a=  
        Send a message through the WebSocket connection.

        This method serializes the given message dictionary to JSON,
        and sends it through the WebSocket connection. If the connection
        is not currently established, the message will be buffered and sent
        once the connection is re-established.

        Args:
            message (Dict[str, Any]): The message to be sent, as a dictionary.

        Returns:
            None

        Raises:
            websockets.exceptions.WebSocketException: If there's an error sending the message.
        zsend: c                  X   K   j                   j                          d {    y 7 wrf   )r:   rv   )r   r>   s   r#   send_messagez.AsyncRealtimeClient.send.<locals>.send_messageV  s!     $$))'222s   *(*N)rG   dumpsrE   rF   r!   r9   append)r>   r   r   s   `` r#   rv   zAsyncRealtimeClient.send@  s^     & **W%fWI&'	3 .  ##L1 !s   A
A2A0"A2c                    K   | j                   j                         D cg c]+  }|j                  |k(  r|j                  s|j                  r|- }}|D ]  }|j                          d {     y c c}w 7 wrf   )r<   r   rJ   r   
is_joiningr   )r>   rJ   chdup_channelss       r#   _leave_open_topicz%AsyncRealtimeClient._leave_open_topic^  ss      mm**,
,xx5 bllbmm , 	 
 B..""" 
 #s   A80A1A8)A6*A8)TN      g      ?)r   Nrf   )r"   
__module____qualname__r   boolr   r	   r   intfloatr?   rW   rQ   rj   r[   rl   r&   rq   rh   r   r   rV   r
   r   r   r   r   r   r   rv   r   rC   r%   r#   r(   r(   )   s]   
  $+/!$&'&' &' 	&'
 c3h(&' &' &' &' 
&'P8-
^@(" " "&)P EI"*+A"B	 ,d#78 ,,@ T T)XHSM )Xd )XV3 2$sCx. 2T 2<#S #r%   r(   ))r^   rG   loggingr3   base64r   r   	functoolsr   mathr   typingr   r   r	   r
   r   rN   rO   r   r   r   transformersr   typesr   r   r   r   r   r   utilsr   rV   r   r   	getLoggerr"   rE   r&   r(   rC   r%   r#   <module>r      sk       	     6 6  *  ,   A			8	$H }# }#r%   