
    cjhԄ                       U d 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ddlZddl	Z	ddl
mZmZmZmZmZ ddlmZmZ ddlmZ ddlmZmZ dd	l dd
lmZmZ ddlmZmZmZ ddlm Z  er6ddlm!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+ ddl)m,Z, ddl)m-Z. ddl/m0Z0 de1d<   	 ddl2Z3dZ4dZ6 ejn                  e8      Z9 G d d      Z: G d de:      Z;y# e5$ r dZ4Y 3w xY w)av  
The MIT License (MIT)

Copyright (c) 2015-2021 Rapptz
Copyright (c) 2021-present Pycord Development

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

Some documentation to refer to:

- Our main web socket (mWS) sends opcode 4 with a guild ID and channel ID.
- The mWS receives VOICE_STATE_UPDATE and VOICE_SERVER_UPDATE.
- We pull the session_id from VOICE_STATE_UPDATE.
- We pull the token, endpoint and server_id from VOICE_SERVER_UPDATE.
- Then we initiate the voice web socket (vWS) pointing to the endpoint.
- We send opcode 0 with the user_id, server_id, session_id and token using the vWS.
- The vWS sends back opcode 2 with an ssrc, port, modes(array) and heartbeat_interval.
- We send a UDP discovery packet to endpoint:port and receive our IP and our port in LE.
- Then we send our IP and port via vWS with opcode 1.
- When that's all done, we receive opcode 4 from the vWS.
- Finally we can transmit data to endpoint:port.
    )annotationsN)TYPE_CHECKINGAnyCallableLiteraloverload   )opusutils)ExponentialBackoff)ClientExceptionConnectionClosed)*)AudioPlayerAudioSource)RawDataRecordingExceptionSink)MISSING)abc)Client)Guild)Encoder)ConnectionState)GuildVoiceState)SupportedModes)VoiceServerUpdate)
ClientUserboolhas_naclTF)VoiceProtocolVoiceClientc                  @    e Zd ZdZd	dZd
dZddZddZddZddZ	y)r!   a  A class that represents the Discord voice protocol.

    This is an abstract class. The library provides a concrete implementation
    under :class:`VoiceClient`.

    This class allows you to implement a protocol to allow for an external
    method of sending voice, such as Lavalink_ or a native library implementation.

    These classes are passed to :meth:`abc.Connectable.connect <VoiceChannel.connect>`.

    .. _Lavalink: https://github.com/freyacodes/Lavalink

    Parameters
    ----------
    client: :class:`Client`
        The client (or its subclasses) that started the connection request.
    channel: :class:`abc.Connectable`
        The voice channel that is being connected to.
    c                     || _         || _        y N)clientchannel)selfr&   r'   s      G/var/www/html/venv/lib/python3.12/site-packages/discord/voice_client.py__init__zVoiceProtocol.__init__n   s    $(/    c                   K   t         w)a  |coro|

        An abstract method that is called when the client's voice state
        has changed. This corresponds to ``VOICE_STATE_UPDATE``.

        Parameters
        ----------
        data: :class:`dict`
            The raw `voice state payload`__.

            .. _voice_state_update_payload: https://discord.com/developers/docs/resources/voice#voice-state-object

            __ voice_state_update_payload_
        NotImplementedErrorr(   datas     r)   on_voice_state_updatez#VoiceProtocol.on_voice_state_updater         "!   	c                   K   t         w)a  |coro|

        An abstract method that is called when initially connecting to voice.
        This corresponds to ``VOICE_SERVER_UPDATE``.

        Parameters
        ----------
        data: :class:`dict`
            The raw `voice server update payload`__.

            .. _voice_server_update_payload: https://discord.com/developers/docs/topics/gateway#voice-server-update-voice-server-update-event-fields

            __ voice_server_update_payload_
        r-   r/   s     r)   on_voice_server_updatez$VoiceProtocol.on_voice_server_update   r2   r3   c                  K   t         w)a?  |coro|

        An abstract method called when the client initiates the connection request.

        When a connection is requested initially, the library calls the constructor
        under ``__init__`` and then calls :meth:`connect`. If :meth:`connect` fails at
        some point then :meth:`disconnect` is called.

        Within this method, to start the voice connection flow it is recommended to
        use :meth:`Guild.change_voice_state` to start the flow. After which,
        :meth:`on_voice_server_update` and :meth:`on_voice_state_update` will be called.
        The order that these two are called is unspecified.

        Parameters
        ----------
        timeout: :class:`float`
            The timeout for the connection.
        reconnect: :class:`bool`
            Whether reconnection is expected.
        r-   )r(   timeout	reconnects      r)   connectzVoiceProtocol.connect   s     * "!r3   c                  K   t         w)z|coro|

        An abstract method called when the client terminates the connection.

        See :meth:`cleanup`.

        Parameters
        ----------
        force: :class:`bool`
            Whether the disconnection was forced.
        r-   r(   forces     r)   
disconnectzVoiceProtocol.disconnect   s      "!r3   c                    | j                   j                         \  }}| j                  j                  j	                  |       y)a  This method *must* be called to ensure proper clean-up during a disconnect.

        It is advisable to call this from within :meth:`disconnect` when you are
        completely done with the voice protocol instance.

        This method removes it from the internal state cache that keeps track of
        currently alive voice clients. Failure to clean-up will cause subsequent
        connections to report that it's still connected.
        N)r'   _get_voice_client_keyr&   _connection_remove_voice_client)r(   key_id_s      r)   cleanupzVoiceProtocol.cleanup   s2     LL668	44V<r+   N)r&   r   r'   abc.ConnectablereturnNoner0   GuildVoiceStatePayloadrF   rG   r0   VoiceServerUpdatePayloadrF   rG   )r7   floatr8   r   rF   rG   r<   r   rF   rG   rF   rG   )
__name__
__module____qualname____doc__r*   r1   r5   r9   r=   rD    r+   r)   r!   r!   Y   s%    (0"""""."=r+   r!   c                  r    e Zd ZU dZded<   ded<   ded<   ded<   dB fd	Ze Zd
Zded<   e	dCd       Z
e	dDd       Zd ZdEdZdFdZdGdZdGdZdGdZdGdZdHdZdIdZdJdZe	dKd       Ze	dKd       ZdLdZdddMdZdNdZdJd Zd! ZdOd"ZdOd#ZdOd$Zd% Z d& Z!d' Z"e#d(        Z$d) Z%e&d*dd+	 	 	 	 	 	 	 dPd,       Z'e&d*d-	 	 	 	 	 	 	 dQd.       Z'd*dd+	 	 	 	 	 	 	 dRd/Z'd0 Z(dd1dSd2Z)d3 Z*d4 Z+d5 Z,d6 Z-dTd7Z.dJd8Z/dJd9Z0dGd:Z1dGd;Z2dGd<Z3e	dUd=       Z4e4jj                  dVd>       Z4d?d@dWdAZ6 xZ7S )Xr"   ai  Represents a Discord voice connection.

    You do not create these, you typically get them from
    e.g. :meth:`VoiceChannel.connect`.

    Attributes
    ----------
    session_id: :class:`str`
        The voice connection session ID.
    token: :class:`str`
        The voice connection token.
    endpoint: :class:`str`
        The endpoint we are connecting to.
    channel: :class:`abc.Connectable`
        The voice channel connected to.
    loop: :class:`asyncio.AbstractEventLoop`
        The event loop that the voice client is running on.

    Warning
    -------
    In order to use PCM based AudioSources, you must have the opus library
    installed on your system and loaded through :func:`opus.load_opus`.
    Otherwise, your AudioSources must be opus encoded (e.g. using :class:`FFmpegOpusAudio`)
    or the library will not be able to transmit audio.
    strendpoint_ipint
voice_portz	list[int]
secret_keyssrcc                |   t         st        d      t        |   ||       |j                  }t
        | _        t
        | _        |j                  | _        || _	        t        j                         | _        d| _        d| _        t        j                         | _        t        j                         | _        t
        | _        d| _        d| _        d| _        d| _        t
        | _        d | _        t
        | _        d | _        d| _        t
        | _        d| _        d| _        i | _        d | _         d | _!        d | _"        y )Nz+PyNaCl library needed in order to use voiceFr   )#r    RuntimeErrorsuperr*   r@   r   tokensocketloop_state	threadingEvent
_connected_handshaking_potentially_reconnectingasyncio_voice_state_complete_voice_server_completemode_connectionssequence	timestampr7   _runner_playerencoderdecoder_lite_noncewspaused	recordinguser_timestampssinkstarting_timestopping_time)r(   r&   r'   state	__class__s       r)   r*   zVoiceClient.__init__   s   LMM)""!
/4zz	',+4??+<"'/4&4;MMO"5<]]_# 	!"%,+/ ' !)0!	!!r+   )xsalsa20_poly1305_litexsalsa20_poly1305_suffixxsalsa20_poly1305ztuple[SupportedModes, ...]supported_modesc                0    t        | j                  dd      S )z,The guild we're connected to, if applicable.guildN)getattrr'   r(   s    r)   r   zVoiceClient.guild  s     t||Wd33r+   c                .    | j                   j                  S )z-The user connected to voice (i.e. ourselves).)ra   userr   s    r)   r   zVoiceClient.user  s     {{r+   c                h    t        | |      }||z   |kD  rt        | |d       y t        | |||z          y )Nr   )r   setattr)r(   attrvaluelimitvals        r)   checked_addzVoiceClient.checked_add  s6    dD!;D$"D$e,r+   c                0  K   |d   | _         |d   }| j                  r| j                  rO|| j                          d {    y | j                  }|xr |xr |j                  t        |            | _        y | j                  j                          y 7 Tw)N
session_id
channel_id)
r   re   rf   r=   r   get_channelrW   r'   rh   set)r(   r0   r   r   s       r)   r1   z!VoiceClient.on_voice_state_update&  s     |,,'
  D$B$B !oo'''

)ZeZ8I8I#j/8Z&&**, (s   =BB ABc                  K   | j                   j                         rt        j                  d       y |j	                  d      | _        t        |d         | _        |j	                  d      }|| j
                  t        j                  d       y |j                  d      \  | _
        }}| j                  j                  d      r| j                  dd  | _
        t        | _        t        j                  t        j                  t        j                         | _        | j                  j#                  d	       | j$                  s$| j&                  j)                  d
       d {    y | j                   j+                          y 7  w)Nz(Ignoring extraneous voice server update.r^   guild_idendpointzqAwaiting endpoint... This requires waiting. If timeout occurred considering raising the timeout and reconnecting.:zwss://   Fi  )ri   is_set_loginfogetr^   rW   	server_idwarning
rpartitionr   
startswithr   rV   r_   AF_INET
SOCK_DGRAMsetblockingre   rs   closer   )r(   r0   r   rC   s       r)   r5   z"VoiceClient.on_voice_server_update7  s+    &&--/II@AXXg&
T*-.88J'tzz1LLX &11#6q!==##H- MM!"-DM #mmFNNF4E4EF&  ''--%%%##'') &s   EF!F"!Fc                   K   | j                   j                  j                  | j                          d {    y 7 w)Nr'   r'   r   change_voice_stater   s    r)   voice_connectzVoiceClient.voice_connectY  s+     ll  33DLL3IIIs   4><>c                   K   t         j                  d| j                  j                  | j                  j                         | j                  j                  j                  d        d {    y 7 w)NzGThe voice handshake is being terminated for Channel ID %s (Guild ID %s)r   )r   r   r'   idr   r   r   s    r)   voice_disconnectzVoiceClient.voice_disconnect\  sN     		ULLOOJJMM	

 ll  33D3AAAs   A)A3+A1,A3c                    | j                   j                          | j                  j                          d| _        t        j                  d| j                  dz          | xj                  dz  c_        y )NTz3Starting voice handshake... (connection attempt %d)r	   )rh   clearri   re   r   r   rk   r   s    r)   prepare_handshakezVoiceClient.prepare_handshaked  s^    ""((*##))+ 		A4CTCTWXCX	
 	Qr+   c                    t         j                  d| j                         d| _        | j                  j                          | j                  j                          y )Nz+Voice handshake complete. Endpoint found %sF)r   r   r   re   ri   r   rh   r   s    r)   finish_handshakezVoiceClient.finish_handshakem  sA    		?O!##))+""((*r+   c                  K   t         j                  |        d {   }| j                  j                          |j                  %|j                          d {    |j                  %| j                  j                          |S 7 k7 /wr%   )DiscordVoiceWebSocketfrom_clientrd   r   rY   
poll_eventr   r(   rs   s     r)   connect_websocketzVoiceClient.connect_websockets  sn     (44T::mm#--/!! mm#	 ; "s'   BB=BB	B+B	Bc                 K   t         j                  d       || _        t        d      D ]  }| j	                          | j
                  j                         | j                  j                         g}| j                          d {    	 t        j                  ||       d {    | j                          	 | j                          d {   | _         n | j*                  t,        u r0| j.                  j1                  | j3                  |            | _        y y 7 7 z# t        j                  $ r | j                  d       d {  7    w xY w7 # t"        t        j                  f$ rY |rUt         j%                  d       t        j&                  d|dz  z          d {  7   | j)                          d {  7   Y  w xY ww)	NzConnecting to voice...   r7   Tr<   z)Failed to connect to voice... Retrying...r	   g       @)r   r   r7   ranger   rh   waitri   r   r   sane_wait_forrg   TimeoutErrorr=   r   r   rs   r   	exceptionsleepr   rn   r   r`   create_taskpoll_voice_ws)r(   r8   r7   ifuturess        r)   r9   zVoiceClient.connect{  s    		*+q 	A""$ **//1++002G $$&&&))'7CCC
 !!#
 $ 6 6 88-	@ <<7"99001C1CI1NODL #- ' D'' ooDo111 9$g&:&:; NN#NO!--AG444//111s   BGDG
D!$D%D!)G:EE	EAGD!!(E	E
EGEAG$F'%G=G >GGGGc                  K   | j                   j                          | j                          d| _        	 t	        j
                  | j                  j                         | j                         d {    | j                          d| _        	 | j                          d {   | _        y7 :# t        j                  $ r% d| _        | j                  d       d {  7   Y yw xY w7 G# t        t        j                  f$ r Y yw xY ww)NTr   Fr   )rd   r   r   rf   rg   wait_forri   r   r7   r   r=   r   r   rs   r   r   s    r)   potential_reconnectzVoiceClient.potential_reconnect  s      )-&	""++002DLL   	).&	 2244DG  ## 	-2D*///---	 5 '"6"67 		s|   2D
<B. 1B,2B. 6D
C+ !C)"	C+ +D
,B. ./C&C C&#D
%C&&D
)C+ +DD
DD
c                L    | j                   }|st        d      S |j                  S )a  Latency between a HEARTBEAT and a HEARTBEAT_ACK in seconds.

        This could be referred to as the Discord Voice WebSocket latency and is
        an analogue of user's voice latencies as seen in the Discord client.

        .. versionadded:: 1.4
        inf)rs   rL   latencyr   s     r)   r   zVoiceClient.latency  s"     WW#%uU|52::5r+   c                L    | j                   }|st        d      S |j                  S )zaAverage of most recent 20 HEARTBEAT latencies in seconds.

        .. versionadded:: 1.4
        r   )rs   rL   average_latencyr   s     r)   r   zVoiceClient.average_latency  s$     WW#%uU|=2+=+==r+   c                >  K   t               }	 	 | j                  j                          d {    $7 # t        t        j
                  f$ r}t        |t              r|j                  dv r>t        j                  d|j                         | j                          d {  7   Y d }~y |j                  dk(  rht        j                  d       | j                          d {  7  }|rY d }~t        j                  d       | j                          d {  7   Y d }~y |s| j                          d {  7    |j                         }t        j                  d|       | j                  j                          t	        j                   |       d {  7   | j#                          d {  7   	 | j%                  d| j&                         d {  7   n3# t        j
                  $ r t        j)                  d	       Y Y d }~w xY wY d }~d }~ww xY ww)
NT)i  i  z1Disconnecting from voice normally, close code %d.i  z=Disconnected from voice by force... potentially reconnecting.z@Reconnect was unsuccessful, disconnecting from voice normally...z1Disconnected from voice... Reconnecting in %.2fs.)r8   r7   z)Could not connect to voice... Retrying...)r   rs   r   r   rg   r   
isinstancecoder   r   r=   r   delayr   rd   r   r   r   r9   r7   r   )r(   r8   backoffexc
successfulretrys         r)   r   zVoiceClient.poll_voice_ws  s    $&.gg((*** *$g&:&:; ,c#34
 xx</		OHH #oo///xx4'		- ,0+C+C+E%E%E
%$		+ #oo/// //+++G %%'mmE***++---,,t||,LLL++ LL!LM MQ,s   H4 24 H4 HAHB" H%H*7H!C$"H)H.(HDHH!H6D97AHFH.F1/H5 GGGH(HHHHHHHHFr   c                 K   |s| j                         sy| j                          | j                  j                          	 | j                  r"| j                  j                          d{    | j                          d{    | j                          | j                  r| j                  j                          yy7 T7 ># | j                          | j                  r| j                  j                          w w xY ww)zB|coro|

        Disconnects this voice client from voice.
        N)	is_connectedstoprd   r   rs   r   r   rD   r_   r;   s     r)   r=   zVoiceClient.disconnect  s     
 T..0			$wwggmmo%%'')))LLN{{!!#  &)LLN{{!!# sA   >C?)C *B?+C CC 8C??C C 9C<<C?c                l   K   | j                   j                  j                  |       d{    y7 w)z|coro|

        Moves you to a different voice channel.

        Parameters
        ----------
        channel: :class:`abc.Connectable`
            The channel to move to. Must be a voice channel.
        r   Nr   )r(   r'   s     r)   move_tozVoiceClient.move_to  s)      ll  33G3DDDs   *424c                6    | j                   j                         S )z4Indicates if the voice client is connected to voice.)rd   r   r   s    r)   r   zVoiceClient.is_connected#  s    %%''r+   c                <   t        d      }d|d<   d|d<   t        j                  d|d| j                         t        j                  d|d	| j                         t        j                  d|d
| j
                         t        | d| j                         } |||      S )N      r   x   r	   z>H   >I      	_encrypt_)	bytearraystruct	pack_intorl   rm   rZ   r   rj   )r(   r0   headerencrypt_packets       r)   _get_voice_packetzVoiceClient._get_voice_packet)  s    2 q	q	vq$--8vq$..9vq$))4 499+'>?fd++r+   c                    t         j                  j                  t        | j                              }t        d      }||d d ||j                  t        |      t        |            j                  z   S N   r   )naclsecret	SecretBoxbytesrY   r   encrypt
ciphertextr(   r   r0   boxnonces        r)   _encrypt_xsalsa20_poly1305z&VoiceClient._encrypt_xsalsa20_poly13056  sW    kk##E$//$:;"cr
E$Ku>IIIIr+   c                >   t         j                  j                  t        | j                              }t         j
                  j                  t         j                  j                  j                        }||j                  t        |      |      j                  z   |z   S r%   )
r   r   r   r   rY   r   random
NONCE_SIZEr   r   r   s        r)   !_encrypt_xsalsa20_poly1305_suffixz-VoiceClient._encrypt_xsalsa20_poly1305_suffix=  sh    kk##E$//$:;

!!$++"7"7"B"BCE$K7BBBUJJr+   c                V   t         j                  j                  t        | j                              }t        d      }t        j                  d| j                        |d d | j                  ddd       ||j                  t        |      t        |            j                  z   |d d z   S )Nr   r   r   rr   r	       )r   r   r   r   rY   r   r   packrr   r   r   r   r   s        r)   _encrypt_xsalsa20_poly1305_litez+VoiceClient._encrypt_xsalsa20_poly1305_liteC  s    kk##E$//$:;"KKd&6&67bq	:6E$Ku>IIIERTSTIUUr+   c                    t         j                  j                  t        | j                              }t        d      }||d d | j                  |j                  t        |      t        |                  S r   r   r   r   r   rY   r   strip_header_extdecryptr   s        r)   _decrypt_xsalsa20_poly1305z&VoiceClient._decrypt_xsalsa20_poly1305L  sW    kk##E$//$:;"cr
$$S[[teEl%KLLr+   c           	        t         j                  j                  t        | j                              }t         j                  j                  j
                  }|| d  }| j                  |j                  t        |d |        |            S r%   )r   r   r   r   rY   r   r   r  )r(   r   r0   r   
nonce_sizer   s         r)   !_decrypt_xsalsa20_poly1305_suffixz-VoiceClient._decrypt_xsalsa20_poly1305_suffixT  sl    kk##E$//$:;[[**55
j[\"$$S[[tLj[7I1JE%RSSr+   c                    t         j                  j                  t        | j                              }t        d      }|dd  |d d |d d }| j                  |j                  t        |      t        |                  S )Nr   r   r   r   s        r)   _decrypt_xsalsa20_poly1305_litez+VoiceClient._decrypt_xsalsa20_poly1305_lite\  sh    kk##E$//$:;"Ibq	CRy$$S[[teEl%KLLr+   c                    | d   dk(  r<| d   dk(  r4t        |       dkD  r&t        j                  d|       \  }}d|dz  z   }| |d  } | S )Nr      r	      r   z>HH)lenr   unpack_from)r0   rC   lengthoffsets       r)   r   zVoiceClient.strip_header_exte  sT    7d?tAw$3t9q=**5$7IAv!^F=Dr+   c                    | j                   j                  j                         D ci c]  \  }}|d   | c}}|   S c c}}w )Nuser_id)rs   ssrc_mapitems)r(   r  rZ   r   s       r)   get_ssrczVoiceClient.get_ssrcm  s@    8<8H8H8N8N8PQ*$Y%Q
 	
Qs   ?N)afterwait_finishc                    y r%   rS   r(   sourcer  r  s       r)   playzVoiceClient.playr  s     r+   r  c                    y r%   rS   r  s       r)   r  zVoiceClient.play{  s     r+   c                  | j                         st        d      | j                         rt        d      t        |t              s"t        d|j                  j                         | j                  s)|j                         st        j                         | _        d|rt        j                         |dfd}|}t        || |      | _        | j                  j!                          S )a  Plays an :class:`AudioSource`.

        The finalizer, ``after`` is called after the source has been exhausted
        or an error occurred.

        If an error happens while the audio player is running, the exception is
        caught and the audio player is then stopped. If no after callback is
        passed, any caught exception will be displayed as if it were raised.

        Parameters
        ----------
        source: :class:`AudioSource`
            The audio source we're reading from.
        after: Callable[[Optional[:class:`Exception`]], Any]
            The finalizer that is called after the stream is exhausted.
            This function must have a single parameter, ``error``, that
            denotes an optional exception that was raised during playing.
        wait_finish: bool
            If True, an awaitable will be returned, which can be used to wait for
            audio to stop playing. This awaitable will return an exception if raised,
            or None when no exception is raised.

            If False, None is returned and the function does not block.

            .. versionadded:: v2.5

        Raises
        ------
        ClientException
            Already playing audio or not connected.
        TypeError
            Source is not a :class:`AudioSource` or after is not a callable.
        OpusNotLoaded
            Source is not opus encoded and opus is not loaded.
        zNot connected to voice.zAlready playing audio.z"source must be an AudioSource not Nc                N    t              r |        j                  |        y r%   )callable
set_result)r   after_callbackfutures    r)   _afterz VoiceClient.play.<locals>._after  s!    N+"3'!!#&r+   r  )r   zException | None)r   r   
is_playingr   r   	TypeErrorr{   rO   rp   is_opusr
   r   rg   Futurer   ro   start)r(   r  r  r  r#  r!  r"  s        @@r)   r  zVoiceClient.play  s    V   "!";<<??!":;;&+.4V5E5E5N5N4OP  ||FNN$4<<>DL^^%F"N' E"64u=r+   c                    d|d   cxk  rdk  ry | j                   ryt        ||       }|j                  dk(  ry| j                  j	                  |       y)a  Takes an audio packet received from Discord and decodes it into pcm audio data.
        If there are no users talking in the channel, `None` will be returned.

        You must be connected to receive audio.

        .. versionadded:: 2.0

        Parameters
        ----------
        data: :class:`bytes`
            Bytes received by Discord via the UDP connection used for sending and receiving voice data.
           r	      Ns   )rt   r   decrypted_datarq   decoder/   s     r)   unpack_audiozVoiceClient.unpack_audio  sZ     $q' S 
  ! ;;tT"/1D!r+   )
sync_startc                  | j                         st        d      | j                  rt        d      t        |t              st        d      | j                          t        j                  |       | _        | j                  j                          d| _        || _
        || _        |j                  |        t        j                  | j                  ||g|      }|j                          y)a  The bot will begin recording audio from the current voice channel it is in.
        This function uses a thread so the current code line will not be stopped.
        Must be in a voice channel to use.
        Must not be already recording.

        .. versionadded:: 2.0

        Parameters
        ----------
        sink: :class:`.Sink`
            A Sink which will "store" all the audio data.
        callback: :ref:`coroutine <coroutine>`
            A function which is called after the bot has stopped recording.
        *args:
            Args which will be passed to the callback function.
        sync_start: :class:`bool`
            If True, the recordings of subsequent users will start with silence.
            This is useful for recording audio just as it was heard.

        Raises
        ------
        RecordingException
            Not connected to a voice channel.
        RecordingException
            Already recording.
        RecordingException
            Must provide a Sink object.
        zNot connected to voice channel.zAlready recording.zMust provide a Sink object.T)targetargsN)r   r   ru   r   r   empty_socketr
   DecodeManagerrq   r(  r/  rw   initrb   Thread
recv_audio)r(   rw   callbackr/  r2  ts         r)   start_recordingzVoiceClient.start_recording  s    :   "$%FGG>>$%9::$%$%BCC))$/$			$?? 
 	
	r+   c                    | j                   st        d      | j                  j                          d| _         d| _        y)zStops the recording.
        Must be already recording.

        .. versionadded:: 2.0

        Raises
        ------
        RecordingException
            Not currently recording.
        Not currently recording audio.FN)ru   r   rq   r   rt   r   s    r)   stop_recordingzVoiceClient.stop_recording"  s5     ~~$%EFFr+   c                V    | j                   st        d      | j                   | _        y)zPauses or unpauses the recording.
        Must be already recording.

        .. versionadded:: 2.0

        Raises
        ------
        RecordingException
            Not currently recording.
        r<  N)ru   r   rt   r   s    r)   toggle_pausezVoiceClient.toggle_pause3  s$     ~~$%EFF++or+   c                    	 t        j                   | j                  gg g d      \  }}}|sy |D ]  }|j                  d        C)Ng           )selectr_   recv)r(   readyrC   ss       r)   r3  zVoiceClient.empty_socketB  sJ     --r2sCKE1a t	 r+   c                   i | _         t        j                         | _        |  | j                  rt        j
                  | j                  gg | j                  gd      \  }}}|s|rt        d|        Q	 | j                  j                  d      }| j                  |       | j                  rt        j                         | _        | j                  j                          t        j                    ||g| | j"                        }|j%                         }|t        |       y y # t        $ r | j                          Y  w xY w)Ng{Gz?zSocket error: rA  )rv   timeperf_counterrx   ru   rB  r_   printrC  OSErrorr=  r.  ry   rw   rD   rg   run_coroutine_threadsafer`   result)	r(   rw   r8  r2  rD  rC   errr0   rL  s	            r)   r7  zVoiceClient.recv_audioJ  s   
 >@!..0nn"MM4;;-dkk]DQME1cN3%01{{''-
 d# nn "..0		33HT4ID4I499U"&M   ##%s   5D' 'EEc                <   |j                   | j                  vrL| j                  r| j                  s|j                  | _        d}n|j                  | j                  z
  dz  dz
  }n~|j                  | j                  |j                      d   z
  dz  }|j
                  | j                  |j                      d   z
  }t        d|dz  |z  z
        }|dkD  r|dk7  r|dz
  }n|dz
  }| j                  j                  |j                   |j
                  |j                  fi       t        j                  dd      t        dt        |            z  t        j                  j                  z  |j                  z   |_        |j                   | j                   j"                  vr8t%        j&                  d       |j                   | j                   j"                  vr8| j(                  j+                  |j                  | j                   j"                  |j                      d	          y )
Nr   i  i  r	   d   <   z<hg?r  )rZ   rv   r/  receive_timefirst_packet_timestamprm   absupdater   r   maxrW   r
   _OpusStructCHANNELSdecoded_datars   r  rG  r   rw   write)r(   r0   silencedRTdTdiffs         r)   recv_decoded_audiozVoiceClient.recv_decoded_audioi  s   99D000((.2.?.?+ &&)D)DDM !!D$8$8$CA$FFC $"6"6tyy"A!"DDBsR#X^+,Dr	bCi)s(##TYYARAR0S$TU KKa 3q#g,#77$:J:J:S:SS  	
 iitww///JJt iitww///		))477+;+;DII+Fy+QRr+   c                V    | j                   duxr | j                   j                         S )z+Indicates if we're currently playing audio.N)ro   r$  r   s    r)   r$  zVoiceClient.is_playing  s#    ||4'EDLL,C,C,EEr+   c                V    | j                   duxr | j                   j                         S )z6Indicates if we're playing audio, but if we're paused.N)ro   	is_pausedr   s    r)   ra  zVoiceClient.is_paused  s#    ||4'DDLL,B,B,DDr+   c                `    | j                   r"| j                   j                          d| _         yy)zStops playing audio.N)ro   r   r   s    r)   r   zVoiceClient.stop  s%    <<LLDL r+   c                R    | j                   r| j                   j                          yy)zPauses the audio playing.N)ro   pauser   s    r)   rd  zVoiceClient.pause  s    <<LL  r+   c                R    | j                   r| j                   j                          yy)zResumes the audio playing.N)ro   resumer   s    r)   rf  zVoiceClient.resume  s    <<LL! r+   c                J    | j                   r| j                   j                  S dS )zThe audio source being played, if playing.

        This property can also be used to change the audio source currently being played.
        N)ro   r  r   s    r)   r  zVoiceClient.source  s     '+llt||""<<r+   c                    t        |t              s#t        d|j                  j                   d      | j
                  t        d      | j
                  j                  |       y )Nzexpected AudioSource not .zNot playing anything.)r   r   r%  r{   rO   ro   
ValueError_set_source)r(   r   s     r)   r  zVoiceClient.source  sU    %-78P8P7QQRSTT<<455  'r+   T)encodec               0   | j                  ddd       |rV| j                  st        j                         | _        | j                  j	                  || j                  j
                        }n|}| j                  |      }	 | j                  j                  || j                  | j                  f       | j                  dt        j                  j
                  d       y# t        $ r. t        j                  d| j                  | j                         Y bw xY w)a  Sends an audio packet composed of the data.

        You must be connected to play audio.

        Parameters
        ----------
        data: :class:`bytes`
            The :term:`py:bytes-like object` denoting PCM or Opus voice data.
        encode: :class:`bool`
            Indicates if ``data`` should be encoded into Opus.

        Raises
        ------
        ClientException
            You are not connected.
        opus.OpusError
            Encoding the data failed.
        rl   r	   i  z2A packet has been dropped (seq: %s, timestamp: %s)rm   r   N)r   rp   r
   r   rl  SAMPLES_PER_FRAMEr   r_   sendtorV   rX   BlockingIOErrorr   r   rl   rm   )r(   r0   rl  encoded_datapackets        r)   send_audio_packetzVoiceClient.send_audio_packet  s    ( 	Q.<<#||~<<..tT\\5S5STLL''5	KKv(8(8$//'JK 	dll&D&DjQ  	LLD	s    2C 4DD)r&   r   r'   rE   )rF   zGuild | None)rF   r   rH   rJ   rN   )rF   r   )r8   r   r7   rL   rF   rG   )rF   r   )rF   rL   )r8   r   rF   rG   rM   )r'   rE   rF   rG   )r   r   rF   r   )r  r   r  (Callable[[Exception | None], Any] | Noner  zLiteral[False]rF   rG   )r  r   r  rt  r  zLiteral[True]rF   zasyncio.Future)r  r   r  rt  r  r   rF   zNone | asyncio.Future)r/  r   )r0   r   )rF   zAudioSource | None)r   r   rF   rG   )r0   r   rl  r   rF   rG   )8rO   rP   rQ   rR   __annotations__r*   r    	warn_naclr   propertyr   r   r   r1   r5   r   r   r   r   r   r9   r   r   r   r   r=   r   r   r   r   r   r   r  r  r  staticmethodr   r  r   r  r.  r:  r=  r?  r3  r7  r^  r$  ra  r   rd  rf  r  setterrs  __classcell__)r{   s   @r)   r"   r"      sc   4 O
I#"J I3O/  4 4    --" *DJB+%PN0 	6 	6 > >1f 16 $*
E(,JKVMTM  

 
 ;?&+ 8	
 $ 
  
 ;?	 8	
 # 
  ;?!HH 8	H
 H 
HT": IN 5n"&>$SLFE !
"
 = = ]]( ( @D %R %Rr+   r"   )<rR   
__future__r   rg   loggingrB  r_   r   rb   rG  typingr   r   r   r   r    r
   r   r   r   errorsr   r   gatewayplayerr   r   sinksr   r   r   r   r   r&   r   r   r   r   rz   r   types.voicer   rI   r   r   rK   r   r   ru  nacl.secretr   r    ImportError__all__	getLoggerrO   r   r!   r"   rS   r+   r)   <module>r     s   %N #        B B  ' 5  , 4 4 &F+J  H w"k= k=\WR- WRu  Hs   %C CC