
    qi                         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
 ddlmZmZmZmZmZmZmZmZ ddlmZ  G d	 d
e      Zy)z,Exotel Media Streams serializer for Pipecat.    N)Optional)logger)KeypadEntry)create_stream_resampler)AudioRawFrameFrameInputAudioRawFrameInputDTMFFrameInterruptionFrameOutputTransportMessageFrame!OutputTransportMessageUrgentFrame
StartFrame)FrameSerializerc                        e Zd ZdZ G d dej
                        Z	 ddedee   dee   f fdZd	e	fd
Z
d	edeez  dz  fdZdeez  dedz  fdZ xZS )ExotelFrameSerializera  Serializer for Exotel Media Streams WebSocket protocol.

    This serializer handles converting between Pipecat frames and Exotel's WebSocket
    media streams protocol. It supports audio conversion, DTMF events, and automatic
    call termination.

    Note: Ref docs for events:
        https://support.exotel.com/support/solutions/articles/3000108630-working-with-the-stream-and-voicebot-applet
    c                   4    e Zd ZU dZdZeed<   dZee   ed<   y)!ExotelFrameSerializer.InputParamsaF  Configuration parameters for ExotelFrameSerializer.

        Parameters:
            exotel_sample_rate: Sample rate used by Exotel, defaults to 8000 Hz.
            sample_rate: Optional override for pipeline input sample rate.
            ignore_rtvi_messages: Inherited from base FrameSerializer, defaults to True.
        i@  exotel_sample_rateNsample_rate)	__name__
__module____qualname____doc__r   int__annotations__r   r        L/opt/pipecat/venv/lib/python3.12/site-packages/pipecat/serializers/exotel.pyInputParamsr   )   s"    	 #'C&%)Xc])r   r   N
stream_sidcall_sidparamsc                     t         |   |xs t        j                                || _        || _        | j                  j                  | _        d| _	        t               | _        t               | _        y)a  Initialize the ExotelFrameSerializer.

        Args:
            stream_sid: The Exotel Media Stream SID.
            call_sid: The associated Exotel Call SID (optional, not used in this implementation).
            params: Configuration parameters.
        r   N)super__init__r   r   _stream_sid	_call_sid_paramsr   _exotel_sample_rate_sample_rater   _input_resampler_output_resampler)selfr    r!   r"   	__class__s       r   r%   zExotelFrameSerializer.__init__5   s`     	F#8#D#D#FG%!#'<<#B#B  7 9!8!:r   framec                 ^   K   | j                   j                  xs |j                  | _        yw)zSets up the serializer with pipeline configuration.

        Args:
            frame: The StartFrame containing pipeline configuration.
        N)r(   r   audio_in_sample_rater*   )r-   r/   s     r   setupzExotelFrameSerializer.setupJ   s%      !LL44R8R8Rs   +-returnc                 h  K   t        |t              r$d| j                  d}t        j                  |      S t        |t
              r|j                  }| j                  j                  ||j                  | j                         d{   }|t        |      dk(  ryt        j                  |      j                  d      }d| j                  d|id}t        j                  |      S t        |t        t         f      r1| j#                  |      ryt        j                  |j$                        S y7 w)	a8  Serializes a Pipecat frame to Exotel WebSocket format.

        Handles conversion of various frame types to Exotel WebSocket messages.

        Args:
            frame: The Pipecat frame to serialize.

        Returns:
            Serialized data as string or bytes, or None if the frame isn't handled.
        clear)event	streamSidNr   asciimediapayload)r6   r7   r9   )
isinstancer   r&   jsondumpsr   audior,   resampler   r)   lenbase64	b64encodedecoder   r   should_ignore_framemessage)r-   r/   answerdataserialized_datar:   s         r   	serializezExotelFrameSerializer.serializeR   s     e./&T5E5EFF::f%%}-;;D %)$:$:$C$Ce'')A)A% O &#o*>!*C&&7>>wGG !!--#W-F ::f%% ;=^_`''.::emm,,+s   BD2D0B)D2rG   c                   K   t        j                  |      }|d   dk(  r|d   d   }t        j                  |      }| j                  j                  || j                  | j                         d{   }|t        |      dk(  ryt        |d| j                        }|S |d   dk(  r6|j                  di       j                  d	      }	 t        t        |            S y7 n# t        $ r t        j                  d
|        Y yw xY ww)a<  Deserializes Exotel WebSocket data to Pipecat frames.

        Handles conversion of Exotel media events to appropriate Pipecat frames.

        Args:
            data: The raw WebSocket data from Exotel.

        Returns:
            A Pipecat frame corresponding to the Exotel event, or None if unhandled.
        r6   r9   r:   Nr      )r>   num_channelsr   dtmfdigitzInvalid DTMF digit: )r<   loadsrA   	b64decoder+   r?   r)   r*   r@   r	   getr
   r   
ValueErrorr   info)r-   rG   rE   payload_base64r:   deserialized_dataaudio_framerN   s           r   deserializez!ExotelFrameSerializer.deserialize{   s     **T"7w&$W-i8N&&~6G&*&;&;&D&D((!!' !
 !(C0A,Ba,G -' --K
 W'KK+//8E%k%&899 5!*  25':;s7   A/D	1C 2AD	C" D	"!DD	DD	)NN)r   r   r   r   r   r   strr   r%   r   r2   r   bytesrI   rW   __classcell__)r.   s   @r   r   r      s    
*o11 
* `d;;)1#;GOP[G\;*S S'U 'sU{T/A 'R+cEk +edl +r   r   )r   rA   r<   typingr   logurur   pipecat.audio.dtmf.typesr   pipecat.audio.utilsr   pipecat.frames.framesr   r   r	   r
   r   r   r   r   #pipecat.serializers.base_serializerr   r   r   r   r   <module>ra      s?    3     0 7	 	 	 @HO Hr   