Spamworldpro Mini Shell
Spamworldpro


Server : Apache/2.4.52 (Ubuntu)
System : Linux webserver 6.8.0-49-generic #49~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Wed Nov 6 17:42:15 UTC 2 x86_64
User : www-data ( 33)
PHP Version : 8.1.2-1ubuntu2.21
Disable Function : NONE
Directory :  /lib/python3/dist-packages/twisted/words/protocols/__pycache__/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : //lib/python3/dist-packages/twisted/words/protocols/__pycache__/irc.cpython-310.pyc
o

�b���	@sz
dZddlZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddl
Z
ddlZddlmZddlmZddlmZddlmZmZmZddlmZddlmZdd	lmZmZmZe d�Z!e d
�Z"e d�Z#e#Z$e d�Z%d
Z&dZ'Gdd�de(�Z)Gdd�de(�Z*Gdd�de+�Z,dd�Z-�d{dd�Z.�d|dd�Z/Gdd�de0�Z1Gdd�d�Z2�d}d!d"�Z3Gd#d$�d$ej4�Z5Gd%d&�d&e2�Z6Gd'd(�d(ej7�Z8d)d*�Z9Gd+d,�d,ej4ej:�Z;Gd-d.�d.ej4ej:�Z<Gd/d0�d0ej=�Z>d1d2�Z?Gd3d4�d4ej7ej:�Z@Gd5d6�d6ejA�ZBd7d8�ZCGd9d:�d:e;�ZDd;ZEd<ZFd=ZGd>ZHd?ZIeJeKgd@�eLdA���ZMdBdC�eM�N�D�ZOGdDdE�dEejP�ZQeQ�ZRGdFdG�dGejS�ZTdHdI�ZUGdJdK�dKe2�ZVdLdM�ZWdNdO�ZXdPdQ�ZYe dR�ZZdSdT�Z[e dA�Z\e!e\dUe#e\dVe"e\dWe\e\e\iZ]iZ^e]�N�D]\Z_Z`e_e^e`dX<�q�[_[`e�ae�be\��dY�ejc�ZddZd[�Zed\d]�Zfd^ZgeZegd_egegegiZhiZieh�N�D]\Z_Z`e_eie`dX<�q�e�ae�beg��dY�ejc�Zjd`da�Zkdbdc�Zlddde�ZmdfZndgZodhZpdiZqdjZrdkZsdlZtdmZudnZvdoZwdpZxdqZydrZzdsZ{dtZ|duZ}dvZ~dwZdxZ�dyZ�dzZ�d{Z�d|Z�d}Z�d~Z�dZ�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�d�Z�id�df�d�dg�d�dh�d�di�d�dj�d�dk�d�dl�d�dm�d�dn�d�do�d�dp�d�dq�d�dr�d�ds��ddt��ddu��ddv�i�ddw��ddx��ddy��ddz��dd{��dd|��d	d}��d
d~��dd��dd���d
d���dd���dd���dd���dd���dd���dd���i�dd���dd���dd���dd���dd���dd���dd���dd���dd���dd���dd���dd���d d���d!d���d"d���d#d���d$d���i�d%d���d&d���d'd���d(d���d)d���d*d���d+d���d,d���d-d���d.d���d/d���d0d���d1d���d2d���d3d���d4d���d5d���i�d6d���d7d���d8d���d9d���d:d���d;d���d<d���d=d���d>d���d?d���d@d���dAd���dBd���dCd���dDd���dEd���dFd���i�dGd���dHd���dId���dJd���dKd���dLd���dMd���dNd“�dOdÓ�dPdē�dQdœ�dRdƓ�dSdǓ�dTdȓ�dUdɓ�dVdʓ�dWd˓�i�dXd̓�dYd͓�dZdΓ�d[dϓ�d\dГ�d]dѓ�d^dғ�d_dӓ�d`dԓ�dadՓ�dbd֓�dcdד�dddؓ�dedٓ�dfdړ�dgdۓ�dhdܓ�i�didݓ�djdޓ�dkdߓ�dld��dmd��dnd��dod��dpd��dqd��drd��dsd��dtd��dud��dvd��dwd��dxd��dyd��d�d�d�d�dz��Z�iZ�e��N�D]	\Z_Z`e_e�e`<�q1dS(~a*
Internet Relay Chat protocol for client and server.

Future Plans
============

The way the IRCClient class works here encourages people to implement
IRC clients by subclassing the ephemeral protocol class, and it tends
to end up with way more state than it should for an object which will
be destroyed as soon as the TCP transport drops.  Someone oughta do
something about that, ya know?

The DCC support needs to have more hooks for the client for it to be
able to ask the user things like "Do you want to accept this session?"
and "Transfer #2 is 67% done." and otherwise manage the DCC sessions.

Test coverage needs to be better.

@var MAX_COMMAND_LENGTH: The maximum length of a command, as defined by RFC
    2812 section 2.3.

@var attributes: Singleton instance of L{_CharacterAttributes}, used for
    constructing formatted text information.

@author: Kevin Turner

@see: RFC 1459: Internet Relay Chat Protocol
@see: RFC 2812: Internet Relay Chat: Client Protocol
@see: U{The Client-To-Client-Protocol
<http://www.irchelp.org/irchelp/rfc/ctcpspec.html>}
�N)�reduce)�path)�Optional)�protocol�reactor�task)�styles)�basic)�_textattributes�log�reflect�
�
� �z&#!+c@�eZdZdS)�
IRCBadMessageN��__name__�
__module__�__qualname__�rr�=/usr/lib/python3/dist-packages/twisted/words/protocols/irc.pyrH�rc@r)�IRCPasswordMismatchNrrrrrrLrrc@�eZdZdZdS)�IRCBadModeszS
    A malformed mode was encountered while attempting to parse a mode string.
    N�rrr�__doc__rrrrrP�rcCs�d}g}|s
td��|dd�dkr|dd��dd�\}}|�d�d	kr7|�dd�\}}|��}|�|�n|��}|�d�}|||fS)
z�
    Breaks a message from an IRC server into its prefix, command, and
    arguments.

    @param s: The message to break.
    @type s: L{bytes}

    @return: A tuple of (prefix, command, args).
    @rtype: L{tuple}
    �zEmpty line.r��:N� � :���)r�split�find�append�pop)�s�prefix�trailing�args�commandrrr�parsemsgVs

r/�Pcs�fdd�|�d�D�S)a�
    Split a string into multiple lines.

    Whitespace near C{str[length]} will be preferred as a breaking point.
    C{"\n"} will also be used as a breaking point.

    @param str: The string to split.
    @type str: C{str}

    @param length: The maximum length which will be allowed for any string in
        the result.
    @type length: C{int}

    @return: C{list} of C{str}
    cs"g|]
}t�|��D]}|�q
qSr)�textwrap�wrap)�.0�line�chunk��lengthrr�
<listcomp>�s"zsplit.<locals>.<listcomp>�
�r&)�strr7rr6rr&qsr&c	Cs,|rzt|�WSttfyY|Sw|S)z�
    Convert a value to an integer if possible.

    @rtype: C{int} or type of L{default}
    @return: An integer when C{value} can be converted to an integer,
        otherwise return C{default}
    )�int�	TypeError�
ValueError)�value�defaultrrr�
_intOrDefault�s
�rAc@r)�UnhandledCommandzO
    A command dispatcher could not locate an appropriate command handler.
    NrrrrrrB�rrBc@s*eZdZUdZdZeeed<dd�ZdS)�_CommandDispatcherMixina�
    Dispatch commands to handlers based on their name.

    Command handler names should be of the form C{prefix_commandName},
    where C{prefix} is the value specified by L{prefix}, and must
    accept the parameters as given to L{dispatch}.

    Attempting to mix this in more than once for a single class will cause
    strange behaviour, due to L{prefix} being overwritten.

    @type prefix: C{str}
    @ivar prefix: Command handler prefix, used to locate handler attributes
    Nr+csf�fdd����fdd�}||�}|dur||�S|d�}|dur+td�|��d���||g|�R�S)	z2
        Perform actual command dispatch.
        cs�j�d|��S)N�_)r+)r.��selfrr�_getMethodName��z8_CommandDispatcherMixin.dispatch.<locals>._getMethodNamecst��|�d�S�N)�getattr)�name�rGrFrr�
_getMethod�rHz4_CommandDispatcherMixin.dispatch.<locals>._getMethodN�unknownzNo handler for z could be found)rB)rF�commandNamer-rM�methodrrLr�dispatch�s�z _CommandDispatcherMixin.dispatch)	rrrrr+rr;�__annotations__rQrrrrrC�s
rC�r r c	Cst|�dkr
td��|ddvrtd|����ggf}d}d}|D]D}|dvr:|dkr2td|����d�|�}d}q!d}|||vrXz|�d�}WntyWtd|����w||�||f�|d	7}q!t|�dkrvtd
|�d|����|dkr�td|����|S)a2
    Parse an IRC mode string.

    The mode string is parsed into two lists of mode changes (added and
    removed), with each mode change represented as C{(mode, param)} where mode
    is the mode character, and param is the parameter passed for that mode, or
    L{None} if no parameter is required.

    @type modes: C{str}
    @param modes: Modes string to parse.

    @type params: C{list}
    @param params: Parameters specified along with L{modes}.

    @type paramModes: C{(str, str)}
    @param paramModes: A pair of strings (C{(add, remove)}) that indicate which modes take
        parameters when added or removed.

    @returns: Two lists of mode changes, one for modes added and the other for
        modes removed respectively, mode changes in each list are represented as
        C{(mode, param)}.
    rzEmpty mode stringz+-zMalformed modes string: Nr%zEmpty mode sequence: zNot enough parameters: r!zToo many parameters: r#)�lenr�indexr)�
IndexErrorr()�modes�params�
paramModes�changes�	direction�count�ch�paramrrr�
parseModes�s6
�
r_c@s�eZdZUdZdZdZdZeee	d<dd�Z
dd�Zd	d
�Zd/dd�Z
d
d�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zd0dd �Zd!d"�Zd#d$�Zd%d&�Zd'd(�Zd)d*�Zd0d+d,�Zd-d.�ZdS)1�IRCz.
    Internet Relay Chat server protocol.
    r N�encodingcCs"g|_|jdurt��|_dSdSrI)�channels�hostname�socket�getfqdnrErrr�connectionMades
�zIRC.connectionMadecCs@|tt}t|t�r|jr|jnd}|�|�}|j�|�dS�N�utf-8)�CR�LF�
isinstancer;ra�encode�	transport�write)rFr4�useEncodingrrr�sendLines


zIRC.sendLinecOs�|std��d|vs|ddkrtd|��d�|gt|��}d|vr,d�|d|�}|�|�t|�dkrDt�d	t|�|f�d
Sd
S)a�
        Send a line formatted as an IRC message.

        First argument is the command, all subsequent arguments are parameters
        to that command.  If a prefix is desired, it may be specified with the
        keyword argument 'prefix'.

        The L{sendCommand} method is generally preferred over this one.
        Notably, this method does not support sending message tags, while the
        L{sendCommand} method does.
        �IRC message requires a command.r#rr"zDSomebody screwed up, 'cuz this doesn't look like a command to me: %sr+z:{} {}��-Message has %d parameters (RFC allows 15):
%sN)r>�join�list�formatrprTr�msg)rFr.�parameter_listr+r4rrr�sendMessages&��

���zIRC.sendMessagecCs�|std��d|vs|ddkrtd|�d���|duri}d�|gt|��}|r2d|�d|��}|rA|�|�}d|�d|��}|�|�t|�d	krYt�d
t|�|f�dSdS)a�
        Send to the remote peer a line formatted as an IRC message.

        @param command: The command or numeric to send.
        @type command: L{unicode}

        @param parameters: The parameters to send with the command.
        @type parameters: A L{tuple} or L{list} of L{unicode} parameters

        @param prefix: The prefix to send with the command.  If not
            given, no prefix is sent.
        @type prefix: L{unicode}

        @param tags: A dict of message tags.  If not given, no message
            tags are sent.  The dict key should be the name of the tag
            to send as a string; the value should be the unescaped value
            to send with the tag, or either None or "" if no value is to
            be sent with the tag.
        @type tags: L{dict} of tags (L{unicode}) => values (L{unicode})
        @see: U{https://ircv3.net/specs/core/message-tags-3.2.html}
        rqr#rr"zInvalid command: "�"N�@rrrs)r>rtru�_stringTagsrprTrrw)rFr.�
parametersr+�tagsr4�tagStrrrr�sendCommand4s(


���zIRC.sendCommandcCsT|�|�g}|��D]\}}|r|�|�d|�|����q|�|�qd�|�S)z�
        Converts a tag dictionary to a string.

        @param tags: The tag dict passed to sendMsg.

        @rtype: L{unicode}
        @return: IRCv3-format tag string
        �=�;)�
_validateTags�itemsr(�_escapeTagValuert)rFr~�
tagStrings�tagr?rrrr|cs
	
zIRC._stringTagscCsD|��D]\}}|std��|D]}|��s|dvrtd��qqdS)z�
        Checks the tag dict for errors and raises L{ValueError} if an
        error is found.

        @param tags: The tag dict passed to sendMsg.
        zA tag name is required.)�-�/�.z Tag contains invalid characters.N)r�r>�isalnum)rFr~r�r?�charrrrr�us���zIRC._validateTagscCs,|�dd��dd��dd��dd��d	d
�S)a<
        Escape the given tag value according to U{escaping rules in IRCv3
        <https://ircv3.net/specs/core/message-tags-3.2.html>}.

        @param value: The string value to escape.
        @type value: L{str}

        @return: The escaped string for sending as a message value
        @rtype: L{str}
        �\z\\r�z\:r#z\s�
z\rr9z\n)�replace)rFr?rrrr��s
�zIRC._escapeTagValuecCs�t|t�r
|�d�}|j|�t�}|��|_|D]'}t|�dkr"q|dtkr.|dd�}t	|�\}}}|�
�}|�|||�qdS)z�
        This hack is to support mIRC, which sends LF only, even though the RFC
        says CRLF.  (Also, the flexibility of LineReceiver to turn "line mode"
        on and off was not required.)
        rh�r%N)rk�bytes�decode�bufferr&rjr)rTrir/�upper�
handleCommand)rF�data�linesr4r+r.rXrrr�dataReceived�s


�zIRC.dataReceivedcC�Zt|d|d�}z|dur|||�WdS|�|||�WdSty,t��YdSw�a�
        Determine the function to call for the given command and call it with
        the given arguments.

        @param command: The IRC command to determine the function for.
        @type command: L{bytes}

        @param prefix: The prefix of the IRC message (as returned by
            L{parsemsg}).
        @type prefix: L{bytes}

        @param params: A list of parameters to call the function with.
        @type params: L{list}
        zirc_%sN�rJ�irc_unknown�
BaseExceptionr�deferr�rFr.r+rXrPrrrr����zIRC.handleCommandcCst|||��)z�
        Called by L{handleCommand} on a command that doesn't have a defined
        handler. Subclasses should override this method.
        ��NotImplementedError�rFr+r.rXrrrr���zIRC.irc_unknowncCs |�d|dt|���f|�dS)a�
        Send a message to a channel or user

        @type sender: C{str} or C{unicode}
        @param sender: Who is sending this message.  Should be of the form
            username!ident@hostmask (unless you know better!).

        @type recip: C{str} or C{unicode}
        @param recip: The recipient of this message.  If a channel, it must
            start with a channel prefix.

        @type message: C{str} or C{unicode}
        @param message: The message being sent.
        �PRIVMSGr"N)r��lowQuote�rF�sender�recip�messagerrr�privmsg�� zIRC.privmsgcCs|�d|d|��f|�dS)a�
        Send a "notice" to a channel or user.

        Notices differ from privmsgs in that the RFC claims they are different.
        Robots are supposed to send notices and not respond to them.  Clients
        typically display notices differently from privmsgs.

        @type sender: C{str} or C{unicode}
        @param sender: Who is sending this message.  Should be of the form
            username!ident@hostmask (unless you know better!).

        @type recip: C{str} or C{unicode}
        @param recip: The recipient of this message.  If a channel, it must
            start with a channel prefix.

        @type message: C{str} or C{unicode}
        @param message: The message being sent.
        �NOTICEr"N)r�r�rrr�notice�sz
IRC.noticecCs |�d|�d|�d|���dS)a�
        Send an action to a channel or user.

        @type sender: C{str} or C{unicode}
        @param sender: Who is sending this message.  Should be of the form
            username!ident@hostmask (unless you know better!).

        @type recip: C{str} or C{unicode}
        @param recip: The recipient of this message.  If a channel, it must
            start with a channel prefix.

        @type message: C{str} or C{unicode}
        @param message: The action being sent.
        r"z ACTION r$N�rpr�rrr�action�r�z
IRC.actionc	Cst|dur(|dur|�d|jt||df�dS|�d|jt||t|�f�dS|�d|�d|�dt|����dS)a]
        Send the topic to a user.

        @type user: C{str} or C{unicode}
        @param user: The user receiving the topic.  Only their nickname, not
            the full hostmask.

        @type channel: C{str} or C{unicode}
        @param channel: The channel for which this is the topic.

        @type topic: C{str} or C{unicode} or L{None}
        @param topic: The topic string, unquoted, or None if there is no topic.

        @type author: C{str} or C{unicode}
        @param author: If the topic is being changed, the full username and
            hostmask of the person changing it.
        N�:%s %s %s %s :%szNo topic is set.r"z TOPIC r$)rprc�RPL_NOTOPIC�	RPL_TOPICr�)rF�user�channel�topic�authorrrrr�s����$z	IRC.topicc	Cs |�d|jd||||f�dS)a�
        Send the author of and time at which a topic was set for the given
        channel.

        This sends a 333 reply message, which is not part of the IRC RFC.

        @type user: C{str} or C{unicode}
        @param user: The user receiving the topic.  Only their nickname, not
            the full hostmask.

        @type channel: C{str} or C{unicode}
        @param channel: The channel for which this information is relevant.

        @type author: C{str} or C{unicode}
        @param author: The nickname (without hostmask) of the user who last set
            the topic.

        @type date: C{int}
        @param date: A POSIX timestamp (number of seconds since the epoch) at
            which the topic was last set.
        z:%s %d %s %s %s %diMN�rprc)rFr�r�r��daterrr�topicAuthor's�zIRC.topicAuthorc	Cs�t|�t|�d}d|}g}d}|D]1}|t|�d|kr8|�d|jt||d�|�f�|g}t|�}q|�|�|t|�d7}q|rX|�d|jt||d�|�f�|�d|jt||f�dS)	a�
        Send the names of a channel's participants to a user.

        @type user: C{str} or C{unicode}
        @param user: The user receiving the name list.  Only their nickname,
            not the full hostmask.

        @type channel: C{str} or C{unicode}
        @param channel: The channel for which this is the namelist.

        @type names: C{list} of C{str} or C{unicode}
        @param names: The names to send.
        rrrr!z:%s %s %s = %s :%sr#z :%s %s %s %s :End of /NAMES listN)rTrprc�RPL_NAMREPLYrtr(�RPL_ENDOFNAMES)	rFr�r��names�prefixLength�namesLength�Lr\�nrrrr�As4��

����z	IRC.namescCsj|D]$}|\}}}}}	}
}|	dvsJ�|�d|jt|||||||	|
|f�q|�d|jt||f�dS)a�
        Send a list of users participating in a channel.

        @type user: C{str} or C{unicode}
        @param user: The user receiving this member information.  Only their
            nickname, not the full hostmask.

        @type channel: C{str} or C{unicode}
        @param channel: The channel for which this is the member information.

        @type memberInfo: C{list} of C{tuples}
        @param memberInfo: For each member of the given channel, a 7-tuple
            containing their username, their hostmask, the server to which they
            are connected, their nickname, the letter "H" or "G" (standing for
            "Here" or "Gone"), the hopcount from C{user} to this member, and
            this member's real name.
        )�H�Gz":%s %s %s %s %s %s %s %s %s :%d %sz:%s %s %s %s :End of /WHO list.N)rprc�RPL_WHOREPLY�RPL_ENDOFWHO)rFr�r��
memberInfo�info�username�hostmask�server�nickname�flag�hops�realNamerrr�whojs0�����zIRC.whoc
Cs�|�d|jt|||||f�|�d|jt||||f�|r+|�d|jt||f�|�d|jt|||	|
f�|�d|jt||d�|�f�|�d|jt||f�dS)	aQ
        Send information about the state of a particular user.

        @type user: C{str} or C{unicode}
        @param user: The user receiving this information.  Only their nickname,
            not the full hostmask.

        @type nick: C{str} or C{unicode}
        @param nick: The nickname of the user this information describes.

        @type username: C{str} or C{unicode}
        @param username: The user's username (eg, ident response)

        @type hostname: C{str}
        @param hostname: The user's hostmask

        @type realName: C{str} or C{unicode}
        @param realName: The user's real name

        @type server: C{str} or C{unicode}
        @param server: The name of the server to which the user is connected

        @type serverInfo: C{str} or C{unicode}
        @param serverInfo: A descriptive string about that server

        @type oper: C{bool}
        @param oper: Indicates whether the user is an IRC operator

        @type idle: C{int}
        @param idle: The number of seconds since the user last sent a message

        @type signOn: C{int}
        @param signOn: A POSIX timestamp (number of seconds since the epoch)
            indicating the time the user signed on

        @type channels: C{list} of C{str} or C{unicode}
        @param channels: A list of the channels which the user is participating in
        z:%s %s %s %s %s %s * :%sz:%s %s %s %s %s :%sz :%s %s %s %s :is an IRC operatorz-:%s %s %s %s %d %d :seconds idle, signon timer�r#z :%s %s %s %s :End of WHOIS list.N)	rprc�
RPL_WHOISUSER�RPL_WHOISSERVER�RPL_WHOISOPERATOR�
RPL_WHOISIDLE�RPL_WHOISCHANNELSrt�RPL_ENDOFWHOIS)rFr��nickr�rcr�r��
serverInfo�oper�idle�signOnrbrrr�whois�s>4������������z	IRC.whoiscC�|�d|�d|���dS)a9
        Send a join message.

        @type who: C{str} or C{unicode}
        @param who: The name of the user joining.  Should be of the form
            username!ident@hostmask (unless you know better!).

        @type where: C{str} or C{unicode}
        @param where: The channel the user is joining.
        r"z JOIN Nr�)rFr��whererrrrt�szIRC.joincCs>|r|�d|�d|�d|���dS|�d|�d|���dS)a�
        Send a part message.

        @type who: C{str} or C{unicode}
        @param who: The name of the user joining.  Should be of the form
            username!ident@hostmask (unless you know better!).

        @type where: C{str} or C{unicode}
        @param where: The channel the user is joining.

        @type reason: C{str} or C{unicode}
        @param reason: A string describing the misery which caused this poor
            soul to depart.
        r"z PART r$Nr�)rFr�r��reasonrrr�part�s zIRC.partcGs&|�d|jt|||d�|�f�dS)a�
        Send information about the mode of a channel.

        @type user: C{str} or C{unicode}
        @param user: The user receiving the name list.  Only their nickname,
            not the full hostmask.

        @type channel: C{str} or C{unicode}
        @param channel: The channel for which this is the namelist.

        @type mode: C{str}
        @param mode: A string describing this channel's modes.

        @param args: Any additional arguments required by the modes.
        z:%s %s %s %s %s %sr#N)rprc�RPL_CHANNELMODEISrt)rFr�r��moder-rrr�channelModes
��zIRC.channelMode)NNrI)rrrrr�rcrarr;rRrfrpryr�r|r�r�r�r�r�r�r�r�r�r�r�r�r�rtr�r�rrrrr`�s4

"/
 )+N

r`c@seZdZdZdZdd�Zed:dd��Zedd	��Zed
d��Z	edd
��Z
edd��Zd:dd�Zdd�Z
dd�Zdd�Zdd�Zdd�Zdd�Zdd�Zd d!�Zd"d#�Zd$d%�Zd&d'�Zd(d)�Zd*d+�Zd,d-�Zd.d/�Zd0d1�Zd2d3�Zd4d5�Zd6d7�Zd8d9�Z dS);�ServerSupportedFeaturesz�
    Handle ISUPPORT messages.

    Feature names match those in the ISUPPORT RFC draft identically.

    Information regarding the specifics of ISUPPORT was gleaned from
    <http://www.irc.org/tech_docs/draft-brocklesby-irc-isupport-03.txt>.
    �isupportc	Cs,dtd�dd|�d�|�gd��d�|_dS)N��z#&��	z(ovh)@+%)�br �lkr )�
CHANNELLEN�	CHANTYPES�MODES�NICKLEN�PREFIX�	CHANMODES)�tuple�_parsePrefixParam�_parseChanModesParam�	_featuresrErrr�__init__&s�z ServerSupportedFeatures.__init__Ncs(�durdd����fdd�}t|��S)a9
        Split ISUPPORT parameter arguments.

        Values can optionally be processed by C{valueProcessor}.

        For example::

            >>> ServerSupportedFeatures._splitParamArgs(['A:1', 'B:2'])
            (('A', '1'), ('B', '2'))

        @type params: C{iterable} of C{str}

        @type valueProcessor: C{callable} taking {str}
        @param valueProcessor: Callable to process argument values, or L{None}
            to perform no processing

        @rtype: C{list} of C{(str, object)}
        @return: Sequence of C{(name, processedValue)}
        NcSs|SrIr)�xrrr�<lambda>J�z9ServerSupportedFeatures._splitParamArgs.<locals>.<lambda>c3s>��D]}d|vr
|d7}|�dd�\}}|�|�fVqdS)Nr"r!r:)r^�ar��rX�valueProcessorrr�_parseLs��z7ServerSupportedFeatures._splitParamArgs.<locals>._parse)ru)�clsrXr�r�rr�r�_splitParamArgs4s
z'ServerSupportedFeatures._splitParamArgscs$�fdd�}d�vr�Sd�|��S)z�
        Unescape an ISUPPORT parameter.

        The only form of supported escape is C{\xHH}, where HH must be a valid
        2-digit hexadecimal number.

        @rtype: C{str}
        c	3sz���d�}|�d�V|D],}|dd�|dd�}}zt|d�}Wnty2td|����wt|�|VqdS)N�\xrr��zInvalid hex octet: )r&r)r<r>�chr)�partsr*�octet�rest�r?rr�	_unescape`s�
��z>ServerSupportedFeatures._unescapeParamValue.<locals>._unescaper�r )rt)r�r?rrrr�_unescapeParamValueUsz+ServerSupportedFeatures._unescapeParamValuecs<d|vr|d7}|�dd�\}}|�fdd�|�d�D�fS)z�
        Split an ISUPPORT parameter.

        @type param: C{str}

        @rtype: C{(str, list)}
        @return: C{(key, arguments)}
        r�r!csg|]}��|��qSr)r)r3�v�r�rrr8}�z7ServerSupportedFeatures._splitParam.<locals>.<listcomp>�,r:)r�r^�keyr?rrr�_splitParamps
z#ServerSupportedFeatures._splitParamcCs`|sdS|ddkrd|vrtd��|�dd�\}}t|tt|���}|dd�}tt||��S)a�
        Parse the ISUPPORT "PREFIX" parameter.

        The order in which the parameter arguments appear is significant, the
        earlier a mode appears the more privileges it gives.

        @rtype: C{dict} mapping C{str} to C{(str, int)}
        @return: A dictionary mapping a mode character to a two-tuple of
            C({symbol, priority)}, the lower a priority (the lowest being
            C{0}) the more privileges it gives
        Nr�(�)zMalformed PREFIX parameterr!)r>r&�zip�rangerT�dict)r�r+rW�symbolsrrrr�s
z)ServerSupportedFeatures._parsePrefixParamcCsDd}t|�t|�krtdt|�t|�f��tdd�||�}t|�S)z�
        Parse the ISUPPORT "CHANMODES" parameter.

        See L{isupport_CHANMODES} for a detailed explanation of this parameter.
        )�addressModesr^�setParam�noParamz9Expecting a maximum of %d channel mode parameters, got %dcSs||pdfS)Nr r)rr?rrrr��sz>ServerSupportedFeatures._parseChanModesParam.<locals>.<lambda>)rTr>�mapr)rFrXr�r�rrrr��s��z,ServerSupportedFeatures._parseChanModesParamcCs|j�||�S)a�
        Get a server supported feature's value.

        A feature with the value L{None} is equivalent to the feature being
        unsupported.

        @type feature: C{str}
        @param feature: Feature name

        @type default: C{object}
        @param default: The value to default to, assuming that C{feature}
            is not supported

        @return: Feature value
        )r��get)rF�featurer@rrr�
getFeature�sz"ServerSupportedFeatures.getFeaturecCs|�|�duS)z[
        Determine whether a feature is supported or not.

        @rtype: C{bool}
        N)r)rFrrrr�
hasFeature�sz"ServerSupportedFeatures.hasFeaturecCsP|D]#}|�|�\}}|�d�r|j�|dd�d�q|�||�|j|<qdS)a2
        Parse ISUPPORT parameters.

        If an unknown parameter is encountered, it is simply added to the
        dictionary, keyed by its name, as a tuple of the parameters provided.

        @type params: C{iterable} of C{str}
        @param params: Iterable of ISUPPORT parameters to parse
        r�r!N)r�
startswithr�r)rQ)rFrXr^rr?rrr�parse�s

�zServerSupportedFeatures.parsecCst|�S)z-
        Unknown ISUPPORT parameter.
        �r�)rFr.rXrrr�isupport_unknown��z(ServerSupportedFeatures.isupport_unknowncC�|�|t�S)zJ
        The maximum number of each channel type a user may join.
        �r�rA�rFrXrrr�isupport_CHANLIMIT��z*ServerSupportedFeatures.isupport_CHANLIMITcCs*z|�|�WSty|�d�YSw)aA
        Available channel modes.

        There are 4 categories of channel mode::

            addressModes - Modes that add or remove an address to or from a
            list, these modes always take a parameter.

            param - Modes that change a setting on a channel, these modes
            always take a parameter.

            setParam - Modes that change a setting on a channel, these modes
            only take a parameter when being set.

            noParam - Modes that change a setting on a channel, these modes
            never take a parameter.
        r�)r�r>rr"rrr�isupport_CHANMODES�s
�z*ServerSupportedFeatures.isupport_CHANMODEScC�t|d|�d��S)zG
        Maximum length of a channel name a client may create.
        rr��rArr"rrr�isupport_CHANNELLEN��z+ServerSupportedFeatures.isupport_CHANNELLENcC�t|d�S)z)
        Valid channel prefixes.
        rrr"rrr�isupport_CHANTYPES�r$z*ServerSupportedFeatures.isupport_CHANTYPEScC�|dpdS)z�
        Mode character for "ban exceptions".

        The presence of this parameter indicates that the server supports
        this functionality.
        r�err"rrr�isupport_EXCEPTS��z(ServerSupportedFeatures.isupport_EXCEPTScCs
|�|�S)z�
        Safe channel identifiers.

        The presence of this parameter indicates that the server supports
        this functionality.
        )r�r"rrr�isupport_IDCHANs
z'ServerSupportedFeatures.isupport_IDCHANcCr,)z�
        Mode character for "invite exceptions".

        The presence of this parameter indicates that the server supports
        this functionality.
        r�Irr"rrr�isupport_INVEXr/z&ServerSupportedFeatures.isupport_INVEXcCr*)zH
        Maximum length of a kick message a client may provide.
        r�rAr"rrr�isupport_KICKLENr$z(ServerSupportedFeatures.isupport_KICKLENcCr )z�
        Maximum number of "list modes" a client may set on a channel at once.

        List modes are identified by the "addressModes" key in CHANMODES.
        r!r"rrr�isupport_MAXLIST sz(ServerSupportedFeatures.isupport_MAXLISTcCr*)z
        Maximum number of modes accepting parameters that may be sent, by a
        client, in a single MODE command.
        rr3r"rrr�isupport_MODES(r�z&ServerSupportedFeatures.isupport_MODEScC�|dS)z#
        IRC network name.
        rrr"rrr�isupport_NETWORK/rz(ServerSupportedFeatures.isupport_NETWORKcCr&)zB
        Maximum length of a nickname the client may use.
        rr�r'r"rrr�isupport_NICKLEN5r)z(ServerSupportedFeatures.isupport_NICKLENcCs.z|�|d�WSty|�d�YSw)zQ
        Mapping of channel modes that clients may have to status flags.
        rr�)r�r>rr"rrr�isupport_PREFIX;s
�z'ServerSupportedFeatures.isupport_PREFIXcC�dS)z�
        Flag indicating that a client may request a LIST without being
        disconnected due to the large amount of data generated.
        Trr"rrr�isupport_SAFELISTDsz)ServerSupportedFeatures.isupport_SAFELISTcCr7)zv
        The server supports sending messages to only to clients on a channel
        with a specific status.
        rrr"rrr�isupport_STATUSMSGKsz*ServerSupportedFeatures.isupport_STATUSMSGcCst|�|t��S)zh
        Maximum number of targets allowable for commands that accept multiple
        targets.
        )rr�rAr"rrr�isupport_TARGMAXRsz(ServerSupportedFeatures.isupport_TARGMAXcCr*)z<
        Maximum length of a topic that may be set.
        rr3r"rrr�isupport_TOPICLENYr$z)ServerSupportedFeatures.isupport_TOPICLENrI)!rrrrr+r��classmethodr�rrr�r�rrrrr#r%r(r+r.r0r2r4r5r6r8r9r:r<r=r>r?rrrrr�sF	 




				r�c@sVeZdZdZdZdZdZdZdZdZ	dZ
dZdZdZ
dZdZdZdZdZdZdZdZdZdZd	Zd
ZdZdZdZd
d�Zdd�Zdd�Zdd�Z dd�Z!dd�Z"dd�Z#dd�Z$dd�Z%dd �Z&d!d"�Z'd#d$�Z(d%d&�Z)d'd(�Z*d)d*�Z+d+d,�Z,d-d.�Z-d/d0�Z.d1d2�Z/d3d4�Z0d5d6�Z1d7d8�Z2d9d:�Z3d;d<�Z4d=d>�Z5d?d@�Z6dAdB�Z7dCdD�Z8dEdF�Z9dGdH�Z:dIdJ�Z;dKdL�Z<dMdN�Z=dOdP�Z>d�dQdR�Z?d�dSdT�Z@d�dUdV�ZAe@ZBdWdX�ZCd�dYdZ�ZDd�d[d\�ZEd�d]d^�ZFd_d`�ZGd�dadb�ZHdcdd�ZI�ddedf�ZJdgdh�ZKd�didj�ZL�ddmdn�ZMdodp�ZN�ddqdr�ZOdsdt�ZPdZQduZRd�dvdw�ZSdxdy�ZTdzd{�ZUd|d}�ZVd~d�ZWd�d��ZXd�d��ZYd�d��ZZd�d��Z[d�d��Z\d�d��Z]d�d��Z^d�d��Z_d�d��Z`d�d��Zad�d��Zbd�d��Zcd�d��Zdd�d��Zed�d��Zfd�d��Zgd�d��Zhd�d��Zid�d��Zjd�d��Zkd�d��Zld�d��Zmd�d��Znd�d��Zod�d��Zpd�d��Zqd�d��Zrd�d��Zsd�d��Ztd�d��Zud�d��Zvd�d��Zwd�d��Zxd�dÄZyd�dńZzd�dDŽZ{d�dɄZ|d�d˄Z}d�d̈́Z~d�dτZd�dфZ�d�dӄZ�d�dՄZ�d�dׄZ�d�dلZ�d�dۄZ�d�d݄Z�d�d߄Z�d�d�Z�d�d�Z�d�d�Z�d�d�Z�d�d�Z�d�d�Z�d�d�Z�d�d�Z�d�d�Z�d�d�Z�d�d��Z�d�d��Z�d�d��Z�d�d��Z�d�d��Z�dS(�	IRCClienta�

    Internet Relay Chat client protocol, with sprinkles.

    In addition to providing an interface for an IRC client protocol,
    this class also contains reasonable implementations of many common
    CTCP methods.

    TODO
    ====
     - Limit the length of messages sent (because the IRC server probably
       does).
     - Add flood protection/rate limiting for my CTCP replies.
     - NickServ cooperation.  (a mix-in?)

    @ivar nickname: Nickname the client will use.
    @ivar password: Password used to log on to the server.  May be L{None}.
    @ivar realname: Supplied to the server during login as the "Real name"
        or "ircname".  May be L{None}.
    @ivar username: Supplied to the server during login as the "User name".
        May be L{None}

    @ivar userinfo: Sent in reply to a C{USERINFO} CTCP query.  If L{None}, no
        USERINFO reply will be sent.
        "This is used to transmit a string which is settable by
        the user (and never should be set by the client)."
    @ivar fingerReply: Sent in reply to a C{FINGER} CTCP query.  If L{None}, no
        FINGER reply will be sent.
    @type fingerReply: Callable or String

    @ivar versionName: CTCP VERSION reply, client name.  If L{None}, no VERSION
        reply will be sent.
    @type versionName: C{str}, or None.
    @ivar versionNum: CTCP VERSION reply, client version.
    @type versionNum: C{str}, or None.
    @ivar versionEnv: CTCP VERSION reply, environment the client is running in.
    @type versionEnv: C{str}, or None.

    @ivar sourceURL: CTCP SOURCE reply, a URL where the source code of this
        client may be found.  If L{None}, no SOURCE reply will be sent.

    @ivar lineRate: Minimum delay between lines sent to the server.  If
        L{None}, no delay will be imposed.
    @type lineRate: Number of Seconds.

    @ivar motd: Either L{None} or, between receipt of I{RPL_MOTDSTART} and
        I{RPL_ENDOFMOTD}, a L{list} of L{str}, each of which is the content
        of an I{RPL_MOTD} message.

    @ivar erroneousNickFallback: Default nickname assigned when an unregistered
        client triggers an C{ERR_ERRONEUSNICKNAME} while trying to register
        with an illegal nickname.
    @type erroneousNickFallback: C{str}

    @ivar _registered: Whether or not the user is registered. It becomes True
        once a welcome has been received from the server.
    @type _registered: C{bool}

    @ivar _attemptedNick: The nickname that will try to get registered. It may
        change if it is illegal or already taken. L{nickname} becomes the
        L{_attemptedNick} that is successfully registered.
    @type _attemptedNick:  C{str}

    @type supported: L{ServerSupportedFeatures}
    @ivar supported: Available ISUPPORT features on the server

    @type hostname: C{str}
    @ivar hostname: Host name of the IRC server the client is connected to.
        Initially the host name is L{None} and later is set to the host name
        from which the I{RPL_WELCOME} message is received.

    @type _heartbeat: L{task.LoopingCall}
    @ivar _heartbeat: Looping call to perform the keepalive by calling
        L{IRCClient._sendHeartbeat} every L{heartbeatInterval} seconds, or
        L{None} if there is no heartbeat.

    @type heartbeatInterval: C{float}
    @ivar heartbeatInterval: Interval, in seconds, to send I{PING} messages to
        the server as a form of keepalive, defaults to 120 seconds. Use L{None}
        to disable the heartbeat.
    N�ircz#http://twistedmatrix.com/downloads/r�r!�
z!unusednames=params,prefix,channelFr �defaultnick�xcCs2t|�}t|t�r|�d�}|d7}tj�||�S)Nrh�
)r�rkr;rlr	�LineReceiverrp)rFr4�	quoteLinerrr�_reallySendLine�s


zIRCClient._reallySendLinecCs:|jdur|�|�dS|j�|�|js|��dSdSrI)�lineRaterI�_queuer(�_queueEmptying�	_sendLine�rFr4rrrrp�s
�zIRCClient.sendLinecCs8|jr|�|j�d��t�|j|j�|_dSd|_dS)Nr)rKrIr)r�	callLaterrJrMrLrErrrrM�s
zIRCClient._sendLinecCstj�||�|��dSrI)r	rG�connectionLost�
stopHeartbeat�rFr�rrrrP�szIRCClient.connectionLostcCst�|j�S)z6
        Create the heartbeat L{LoopingCall}.
        )r�LoopingCall�_sendHeartbeatrErrr�_createHeartbeat�r$zIRCClient._createHeartbeatcCs|�d|j�dS)zR
        Send a I{PING} message to the IRC server as a form of keepalive.
        zPING Nr�rErrrrT�r)zIRCClient._sendHeartbeatcCs"|jdur|j��d|_dSdS)zy
        Stop sending I{PING} messages to keep the connection to the server
        alive.

        @since: 11.1
        N)�
_heartbeat�stoprErrrrQ�s


�zIRCClient.stopHeartbeatcCs6|��|jdurdS|��|_|jj|jdd�dS)z�
        Start sending I{PING} messages every L{IRCClient.heartbeatInterval}
        seconds to keep the connection to the server alive during periods of no
        activity.

        @since: 11.1
        NF)�now)rQ�heartbeatIntervalrUrV�startrErrr�startHeartbeat
s


zIRCClient.startHeartbeatcCr;)z�
        Called with creation date information about the server, usually at logon.

        @type when: C{str}
        @param when: A string describing when the server was created, probably.
        Nr)rF�whenrrr�createdr�zIRCClient.createdcCr;)z�
        Called with daemon information about the server, usually at logon.

        @type info: C{str}
        @param info: A string describing what software the server is running, probably.
        Nr�rFr�rrr�yourHost&r�zIRCClient.yourHostcCr;)a�
        Called with information about the server, usually at logon.

        @type servername: C{str}
        @param servername: The hostname of this server.

        @type version: C{str}
        @param version: A description of what software this server runs.

        @type umodes: C{str}
        @param umodes: All the available user modes.

        @type cmodes: C{str}
        @param cmodes: All the available channel modes.
        Nr)rF�
servername�version�umodes�cmodesrrr�myInfo.r�zIRCClient.myInfocCr;)z�
        Called with information about the number of connections, usually at logon.

        @type info: C{str}
        @param info: A description of the number of clients and servers
        connected to the network, probably.
        Nrr^rrr�luserClient?r�zIRCClient.luserClientcCr;)z�
        Called with information about where the client should reconnect.

        @type info: C{str}
        @param info: A plaintext description of the address that should be
        connected to.
        Nrr^rrr�bounceHr�zIRCClient.bouncecCr;)z�
        Called with various information about what the server supports.

        @type options: C{list} of C{str}
        @param options: Descriptions of features or limits of the server, possibly
        in the form "NAME=VALUE".
        Nr)rF�optionsrrrr�Qr�zIRCClient.isupportcCr;)zl
        Called with the number of channels existent on the server.

        @type channels: C{int}
        Nr)rFrbrrr�
luserChannelsZr�zIRCClient.luserChannelscCr;)zc
        Called with the number of ops logged on to the server.

        @type ops: C{int}
        Nr)rF�opsrrr�luserOpar�zIRCClient.luserOpcCr;)z�
        Called with information about the server connected to.

        @type info: C{str}
        @param info: A plaintext string describing the number of users and servers
        connected to this server.
        Nrr^rrr�luserMehr�zIRCClient.luserMecCr;)zN
        Called when I have a message from a user to me or a channel.
        Nr�rFr�r�r�rrrr�s�zIRCClient.privmsgcCr;)z�
        Called when I finish joining a channel.

        channel has the starting character (C{'#'}, C{'&'}, C{'!'}, or C{'+'})
        intact.
        Nr�rFr�rrr�joinedyr�zIRCClient.joinedcCr;)z�
        Called when I have left a channel.

        channel has the starting character (C{'#'}, C{'&'}, C{'!'}, or C{'+'})
        intact.
        Nrrnrrr�left�r�zIRCClient.leftcCr;)a
        Called when I have a notice from a user to me or a channel.

        If the client makes any automated replies, it must not do so in
        response to a NOTICE message, per the RFC::

            The difference between NOTICE and PRIVMSG is that
            automatic replies MUST NEVER be sent in response to a
            NOTICE message. [...] The object of this rule is to avoid
            loops between clients automatically sending something in
            response to something it received.
        Nrrlrrr�noticed�r�zIRCClient.noticedcCr;)a�
        Called when users or channel's modes are changed.

        @type user: C{str}
        @param user: The user and hostmask which instigated this change.

        @type channel: C{str}
        @param channel: The channel where the modes are changed. If args is
        empty the channel for which the modes are changing. If the changes are
        at server level it could be equal to C{user}.

        @type set: C{bool} or C{int}
        @param set: True if the mode(s) is being added, False if it is being
        removed. If some modes are added and others removed at the same time
        this function will be called twice, the first time with all the added
        modes, the second with the removed ones. (To change this behaviour
        override the irc_MODE method)

        @type modes: C{str}
        @param modes: The mode or modes which are being changed.

        @type args: C{tuple}
        @param args: Any additional information required for the mode
        change.
        Nr)rFr�r��setrWr-rrr�modeChanged�r�zIRCClient.modeChangedcCr;)z?
        Called with the results of a CTCP PING query.
        Nr)rFr��secsrrr�pong�rmzIRCClient.pongcCr;)zE
        Called after successfully signing on to the server.
        NrrErrr�signedOn�rmzIRCClient.signedOncCr;)z9
        Called when I am kicked from a channel.
        Nr)rFr��kickerr�rrr�
kickedFrom�rmzIRCClient.kickedFromcC�
||_dS)z7
        Called when my nick has been changed.
        N)r�)rFr�rrr�nickChanged�s
zIRCClient.nickChangedcCr;)zC
        Called when I see another user joining a channel.
        Nr�rFr�r�rrr�
userJoined�rmzIRCClient.userJoinedcCr;)zC
        Called when I see another user leaving a channel.
        Nrr{rrr�userLeft�rmzIRCClient.userLeftcCr;)zM
        Called when I see another user disconnect from the network.
        Nr)rFr��quitMessagerrr�userQuit�rmzIRCClient.userQuitcCr;)zQ
        Called when I observe someone else being kicked from a channel.
        Nr)rF�kickeer�rwr�rrr�
userKicked�rmzIRCClient.userKickedcCr;)zJ
        Called when I see a user perform an ACTION on a channel.
        Nr�rFr�r�r�rrrr��rmzIRCClient.actioncCr;)zt
        In channel, user changed the topic to newTopic.

        Also called when first joining a channel.
        Nr)rFr�r��newTopicrrr�topicUpdated�szIRCClient.topicUpdatedcCr;)zD
        A user changed their name from oldname to newname.
        Nr)rF�oldname�newnamerrr�userRenamed�rmzIRCClient.userRenamedcCr;)a#
        I received a message-of-the-day banner from the server.

        motd is a list of strings, where each string was sent as a separate
        message from the server. To display, you might want to use::

            '\n'.join(motd)

        to get a nicely formatted string.
        Nr)rF�motdrrr�receivedMOTD�szIRCClient.receivedMOTDcC�F|dtvr
d|}|r|�d|�d|���dS|�d|���dS)a
        Join a channel.

        @type channel: C{str}
        @param channel: The name of the channel to join. If it has no prefix,
            C{'#'} will be prepended to it.
        @type key: C{str}
        @param key: If specified, the key used to join the channel.
        r�#zJOIN r#N��CHANNEL_PREFIXESrp)rFr�rrrrrt
�

zIRCClient.joincCr�)a
        Leave a channel.

        @type channel: C{str}
        @param channel: The name of the channel to leave. If it has no prefix,
            C{'#'} will be prepended to it.
        @type reason: C{str}
        @param reason: If given, the reason for leaving.
        rr�zPART r$Nr�)rFr�r�rrr�leaver�zIRCClient.leavecCsR|dtvr
d|}|r|�d|�d|�d|���dS|�d|�d|���dS)a�
        Attempt to kick a user from a channel.

        @type channel: C{str}
        @param channel: The name of the channel to kick the user from. If it has
            no prefix, C{'#'} will be prepended to it.
        @type user: C{str}
        @param user: The nick of the user to kick.
        @type reason: C{str}
        @param reason: If given, the reason for kicking the user.
        rr�zKICK r#r$Nr�)rFr�r�r�rrr�kick,s
 zIRCClient.kickcCs.|dtvr
d|}|�d|�d|���dS)z�
        Attempt to invite user to channel

        @type user: C{str}
        @param user: The user to invite
        @type channel: C{str}
        @param channel: The channel to invite the user too

        @since: 11.0
        rr�zINVITE r#Nr�r{rrr�inviteAszIRCClient.invitecCsJ|dtvr
d|}|dkr|�d|�d|���dS|�d|���dS)a 
        Attempt to set the topic of the given channel, or ask what it is.

        If topic is None, then I sent a topic query instead of trying to set the
        topic. The server should respond with a TOPIC message containing the
        current topic of the given channel.

        @type channel: C{str}
        @param channel: The name of the channel to change the topic on. If it
            has no prefix, C{'#'} will be prepended to it.
        @type topic: C{str}
        @param topic: If specified, what to set the topic to.
        rr�NzTOPIC r$r�)rFr�r�rrrr�Ps
zIRCClient.topiccCsx|rd|�d|��}nd|�d|��}|durd||f}n|dur*|�d|��}n|dur5|�d|��}|�|�dS)a?
        Change the modes on a user or channel.

        The C{limit}, C{user}, and C{mask} parameters are mutually exclusive.

        @type chan: C{str}
        @param chan: The name of the channel to operate on.
        @type set: C{bool}
        @param set: True to give the user or channel permissions and False to
            remove them.
        @type modes: C{str}
        @param modes: The mode flags to set on the user or channel.
        @type limit: C{int}
        @param limit: In conjunction with the C{'l'} mode flag, limits the
             number of users on the channel.
        @type user: C{str}
        @param user: The user to change the mode on.
        @type mask: C{str}
        @param mask: In conjunction with the C{'b'} mode flag, sets a mask of
            users to be banned from the channel.
        zMODE z +z -Nz%s %dr#r�)rF�chanrrrW�limitr��maskr4rrrr�fszIRCClient.modecCs&|dtvr
d|}|�|||�dS)a�
        Send a message to a channel

        @type channel: C{str}
        @param channel: The channel to say the message on. If it has no prefix,
            C{'#'} will be prepended to it.
        @type message: C{str}
        @param message: The message to say.
        @type length: C{int}
        @param length: The maximum number of octets to send at a time.  This has
            the effect of turning a single call to C{msg()} into multiple
            commands to the server.  This is useful when long messages may be
            sent that would otherwise cause the server to kick us off or
            silently truncate the text we are sending.  If None is passed, the
            entire message is always send in one command.
        rr�N)r�rw)rFr�r�r7rrr�say�sz
IRCClient.saycCs0d�d|j�d�dd|�}d}tt|�|S)a�
        Estimate a safe maximum line length for the given command.

        This is done by assuming the maximum values for nickname length,
        realname and hostname combined with the command that needs to be sent
        and some guessing. A theoretical maximum value is used because it is
        possible that our nickname, username or hostname changes (on the server
        side) while the length is still being calculated.
        z:{}!{}@{} {}r�r��
bbbbbbbbbb�?cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccr)rv�	supportedr�MAX_COMMAND_LENGTHrT)rFr.�theoretical�fudgerrr�_safeMaximumLineLength�s�	z IRCClient._safeMaximumLineLengthcCshd|�d�}|dur|�|�}t|�d}||kr!td||f��t|||�D]	}|�||�q(dS)a�
        Send a message to a user or channel.

        The message will be split into multiple commands to the server if:
         - The message contains any newline characters
         - Any span between newline characters is longer than the given
           line-length.

        @param user: Username or channel name to which to direct the
            message.
        @type user: C{str}

        @param message: Text to send.
        @type message: C{str}

        @param length: Maximum number of octets to send in a single
            command, including the IRC protocol framing. If L{None} is given
            then L{IRCClient._safeMaximumLineLength} is used to determine a
            value.
        @type length: C{int}
        zPRIVMSG r$Nr�z/Maximum length must exceed %d for message to %s)r�rTr>r&rp)rFr�r�r7�fmt�
minimumLengthr4rrrrw�s
���z
IRCClient.msgcCr�)a-
        Send a notice to a user.

        Notices are like normal message, but should never get automated
        replies.

        @type user: C{str}
        @param user: The user to send a notice to.
        @type message: C{str}
        @param message: The contents of the notice to send.
        zNOTICE r$Nr�)rFr�r�rrrr��szIRCClient.noticecC�|�d|�dS)z�
        Mark this client as away.

        @type message: C{str}
        @param message: If specified, the away message.
        zAWAY :%sNr��rFr�rrr�away��zIRCClient.awaycCs|��dS)z(
        Clear the away status.
        N)r�rErrr�back�r�zIRCClient.backcCs4|dur
|�d|�dS|�d|�d|���dS)z�
        Retrieve user information about the given nickname.

        @type nickname: C{str}
        @param nickname: The nickname about which to retrieve information.

        @since: 8.2
        NzWHOIS r#r�)rFr�r�rrrr��s	zIRCClient.whois�foo�barcCsR|jdur
|�d|j�|�|�|jdur||_|�d�|j|||j��dS)a?
        Login to the server.

        @type nickname: C{str}
        @param nickname: The nickname to register.
        @type hostname: C{str}
        @param hostname: If specified, the hostname to logon as.
        @type servername: C{str}
        @param servername: If specified, the servername to logon as.
        NzPASS %szUSER {} {} {} :{})�passwordrp�setNickr�rv�realname)rFr�rcr`rrr�registers


��zIRCClient.registercCs||_|�d|�dS)z�
        Set this client's nickname.

        @type nickname: C{str}
        @param nickname: The nickname to change to.
        zNICK %sN)�_attemptedNickrp�rFr�rrrr�szIRCClient.setNickcCr�)z�
        Disconnect from the server

        @type message: C{str}

        @param message: If specified, the message to give when quitting the
            server.
        zQUIT :%sNr�r�rrr�quit%s	zIRCClient.quitcCs|�|d|fg�dS)a*
        Strike a pose.

        @type channel: C{str}
        @param channel: The name of the channel to have an action on. If it
            has no prefix, it is sent to the user of that name.
        @type action: C{str}
        @param action: The action to preform.
        @since: 9.0
        �ACTIONN��
ctcpMakeQuery)rFr�r�rrr�describe2szIRCClient.describe�cs�|jduri|_|dur$tjtjtj�d��fdd�td�D��}nt|�}t��|j||f<|�	|d|fg�t
|j�|jkrgdd�|j��D�}|�
�t
|j�|j}t|�D]}|j||d=q\dSdS)	zA
        Measure round-trip delay to another IRC client.
        Nr csg|]}t����qSr)�random�choice)r3�i��charsrrr8Kr	z"IRCClient.ping.<locals>.<listcomp>r��PINGcSsg|]\}}||f�qSrr)r3�krrrrr8Ssr!)�_pings�string�
ascii_letters�digits�punctuationrtrr;�timer�rT�
_MAX_PINGRINGr��sort)rFr��textr�byValue�excessr�rr�r�pingBs 
�zIRCClient.pingcC�td��)aK
        This is supposed to send a user a file directly.  This generally
        doesn't work on any client, and this method is included only for
        backwards compatibility and completeness.

        @param user: C{str} representing the user
        @param file: an open file (unknown, since this is not implemented)
        z�XXX!!! Help!  I need to bind a socket, have it listen, and tell me its address.  (and stop accepting once we've made a single connection.)r�)rFr��filerrr�dccSendYs	�zIRCClient.dccSendcC�|�|dd|||gfg�dS)z<
        Send a DCC RESUME request to another user.
        �DCC�RESUMENr��rFr��fileName�port�	resumePosrrr�	dccResumeg�zIRCClient.dccResumecCr�)zT
        Send a DCC ACCEPT response to clients who have requested a resume.
        r��ACCEPTNr�r�rrr�dccAcceptResumemr�zIRCClient.dccAcceptResumecCs|�|j�|_|�|j�dS)zg
        Called when we try to register or change to a nickname that is already
        taken.
        N)�alterCollidedNickr�r��rFr+rXrrr�irc_ERR_NICKNAMEINUSEwszIRCClient.irc_ERR_NICKNAMEINUSEcCs|dS)ar
        Generate an altered version of a nickname that caused a collision in an
        effort to create an unused related name for subsequent registration.

        @param nickname: The nickname a user is attempting to register.
        @type nickname: C{str}

        @returns: A string that is in some way different from the nickname.
        @rtype: C{str}
        rDrr�rrrr�szIRCClient.alterCollidedNickcCs|js|�|j�dSdS)a�
        Called when we try to register or change to an illegal nickname.

        The server should send this reply when the nickname contains any
        disallowed characters.  The bot will stall, waiting for RPL_WELCOME, if
        we don't handle this during sign-on.

        @note: The method uses the spelling I{erroneus}, as it appears in
            the RFC, section 6.1.
        N)�_registeredr��erroneousNickFallbackr�rrr�irc_ERR_ERRONEUSNICKNAME�s�z"IRCClient.irc_ERR_ERRONEUSNICKNAMEcCr�)z6
        Called when the login was incorrect.
        zPassword Incorrect.)rr�rrr�irc_ERR_PASSWDMISMATCH�rz IRCClient.irc_ERR_PASSWDMISMATCHcCs(||_d|_|j|_|��|��dS)zK
        Called when we have received the welcome from the server.
        TN)rcr�r�r�rvr[r�rrr�irc_RPL_WELCOME�s
zIRCClient.irc_RPL_WELCOMEcCs>|�d�d}|d}||jkr|�|�dS|�||�dS)z5
        Called when a user joins a channel.
        �!rr%N)r&r�ror|�rFr+rXr�r�rrr�irc_JOIN��

zIRCClient.irc_JOINcCs>|�d�d}|d}||jkr|�|�dS|�||�dS)z6
        Called when a user leaves a channel.
        r�rN)r&r�rpr}r�rrr�irc_PART�r�zIRCClient.irc_PARTcCs"|�d�d}|�||d�dS)z.
        Called when a user has quit.
        r�rN)r&r�rFr+rXr�rrr�irc_QUIT�szIRCClient.irc_QUITc	
Cs�|d|d|dd�}}}|ddvrd|}||jkr$|��}n|��}z
t|||�\}}WntyHt�ddd�|�f�YdSw|r]t|�\}}|�	||d	d
�|�|�|rst|�\}}|�	||dd
�|�|�dSdS)z5
        Parse a server mode change message.
        rr!r�Nz-+�+zCAn error occurred while parsing the following MODE message: MODE %sr#Tr F)
r��getUserModeParams�getChannelModeParamsr_rr�errrtrrs)	rFr�rXr�rWr-rY�added�removedrrr�irc_MODE�s. 


�
���zIRCClient.irc_MODEcCs|�d|d�dS)z1
        Called when some has pinged us.
        zPONG %sr%Nr�r�rrr�irc_PING�szIRCClient.irc_PINGcCsv|}|d}|d}|sdS|dtkr2t|�}|dr%|�|||d�|ds+dSd�|d�}|�|||�dS)z/
        Called when we get a message.
        rr%N�extended�normalr#)�X_DELIM�ctcpExtract�	ctcpQueryrtr��rFr+rXr�r�r��mrrr�irc_PRIVMSG�szIRCClient.irc_PRIVMSGcCsn|}|d}|d}|dtkr.t|�}|dr!|�|||d�|ds'dSd�|d�}|�|||�dS)z3
        Called when a user gets a notice.
        rr%r�r�Nr#)r�r��	ctcpReplyrtrqr�rrr�
irc_NOTICEszIRCClient.irc_NOTICEcCs@|�dd�d}||jkr|�|d�dS|�||d�dS)z<
        Called when a user changes their nickname.
        r�r!rN)r&r�rzr�r�rrr�irc_NICKs
zIRCClient.irc_NICKcCs^|�d�d}|d}|d}|d}|��|j��kr%|�|||�dS|�||||�dS)z>
        Called when a user is kicked from a channel.
        r�rr!r%N)r&�lowerr�rxr�)rFr+rXrwr��kickedr�rrr�irc_KICK$szIRCClient.irc_KICKcCs0|�d�d}|d}|d}|�|||�dS)z7
        Someone in the channel set the topic.
        r�rr!N�r&r��rFr+rXr�r��newtopicrrr�	irc_TOPIC2szIRCClient.irc_TOPICcCs0|�d�d}|d}|d}|�|||�dS)zt
        Called when the topic for a channel is initially reported or when it
        subsequently changes.
        r�rr!r�Nr�r�rrr�
irc_RPL_TOPIC;szIRCClient.irc_RPL_TOPICcCs,|�d�d}|d}d}|�|||�dS)Nr�rr!r r�r�rrr�irc_RPL_NOTOPICEszIRCClient.irc_RPL_NOTOPICcCs2|d�d�r|ddd�|d<|dg|_dS�Nr%z- r�)rr�r�rrr�irc_RPL_MOTDSTARTKszIRCClient.irc_RPL_MOTDSTARTcCsF|d�d�r|ddd�|d<|jdurg|_|j�|d�dSr�)rr�r(r�rrr�irc_RPL_MOTDPs

zIRCClient.irc_RPL_MOTDcCs|j}d|_|�|�dS)z�
        I{RPL_ENDOFMOTD} indicates the end of the message of the day
        messages.  Deliver the accumulated lines to C{receivedMOTD}.
        N)r�r�)rFr+rXr�rrr�irc_RPL_ENDOFMOTDWszIRCClient.irc_RPL_ENDOFMOTDcC�|�|d�dS�Nr!)r]r�rrr�irc_RPL_CREATED`�zIRCClient.irc_RPL_CREATEDcCrr)r_r�rrr�irc_RPL_YOURHOSTcrzIRCClient.irc_RPL_YOURHOSTcCs@|d�dd�}t|�dkr|�d�t|�dks|j|�dS)Nr!r��)r&rTr(rd)rFr+rXr�rrr�irc_RPL_MYINFOfs

�zIRCClient.irc_RPL_MYINFOcCrr)rfr�rrr�irc_RPL_BOUNCElrzIRCClient.irc_RPL_BOUNCEcCs&|dd�}|j�|�|�|�dS)Nr!r%)r�rr�)rFr+rXr-rrr�irc_RPL_ISUPPORToszIRCClient.irc_RPL_ISUPPORTcCrr)rer�rrr�irc_RPL_LUSERCLIENTxrzIRCClient.irc_RPL_LUSERCLIENTcC�.z|�t|d��WdStyYdSwr)rjr<r>r�rrr�irc_RPL_LUSEROP{�
�zIRCClient.irc_RPL_LUSEROPcCrr)rhr<r>r�rrr�irc_RPL_LUSERCHANNELS�rzIRCClient.irc_RPL_LUSERCHANNELScCrr)rkr�rrr�irc_RPL_LUSERME�rzIRCClient.irc_RPL_LUSERMEcC�dSrIrr�rrrr���zIRCClient.irc_unknowncCs`t�}|D](\}}t|d|d�}||vr(|dur ||||�n|�||||�|�|�qdS)z�
        Dispatch method for any CTCP queries received.

        Duplicated CTCP queries are ignored and no dispatch is
        made. Unrecognized CTCP queries invoke L{IRCClient.ctcpUnknownQuery}.
        zctcpQuery_%sN)rrrJ�ctcpUnknownQuery�add)rFr�r��messages�seenr�r�rPrrrr��s�zIRCClient.ctcpQuerycCs t�d|�d|�d|���dS)z�
        Fallback handler for unrecognized CTCP queries.

        No CTCP I{ERRMSG} reply is made to remove a potential denial of service
        avenue.
        zUnknown CTCP query from �: r#N�rrw�rFr�r�r�r�rrrr�s zIRCClient.ctcpUnknownQuerycCs|�|||�dSrI)r�r�rrr�ctcpQuery_ACTION�rzIRCClient.ctcpQuery_ACTIONcCs$|�d�d}|�|d|fg�dS)Nr�rr��r&�
ctcpMakeReply�rFr�r�r�r�rrr�ctcpQuery_PING�szIRCClient.ctcpQuery_PINGcCsl|dur|�d|�d|�d��|jsdSt|j�r|��}nt|j�}|�d�d}|�|d|fg�dS)N�Why did � send 'z' with a FINGER query?r�r�FINGER)�
quirkyMessage�fingerReply�callabler;r&r)rFr�r�r��replyr�rrr�ctcpQuery_FINGER�s


zIRCClient.ctcpQuery_FINGERcCsf|dur|�d|�d|�d��|jr1|�d�d}|�|dd|j|jp%d|jp)dffg�dSdS)	Nrr z' with a VERSION query?r�r�VERSIONz%s:%s:%sr )r"�versionNamer&r�
versionNum�
versionEnvrrrr�ctcpQuery_VERSION�s"������zIRCClient.ctcpQuery_VERSIONcCsR|dur|�d|�d|�d��|jr'|�d�d}|�|d|jfdg�dSdS)Nrr z' with a SOURCE query?r�r�SOURCE)r,N)r"�	sourceURLr&rrrrr�ctcpQuery_SOURCE�s�zIRCClient.ctcpQuery_SOURCEcCsP|dur|�d|�d|�d��|jr&|�d�d}|�|d|jfg�dSdS)Nrr z' with a USERINFO query?r�r�USERINFO)r"�userinfor&rrrrr�ctcpQuery_USERINFO�s�zIRCClient.ctcpQuery_USERINFOc	Cs�|�d�d}|s tt�|jd��}|�|dd�|�fg�dS|��}t|d|d��d�}|sB|�|dd||dffg�dSt|d	d
�}|�|d|fg�dS)a
        A master index of what CTCP tags this client knows.

        If no arguments are provided, respond with a list of known tags, sorted
        in alphabetical order.
        If an argument is provided, provide human-readable help on
        the usage of that tag.
        r�r�
ctcpQuery_�
CLIENTINFOr#N�ERRMSGz!CLIENTINFO %s :Unknown query '%s'rr )r&�sortedr�prefixedMethodNames�	__class__rrtrJ)	rFr�r�r�r�r�r-rP�docrrr�ctcpQuery_CLIENTINFO�s"	���	zIRCClient.ctcpQuery_CLIENTINFOcCs(|�d�d}|�|dd|fg�dS)Nr�rr4z%s :No error has occurred.rrrrr�ctcpQuery_ERRMSG	szIRCClient.ctcpQuery_ERRMSGcCsX|dur|�d|�d|�d��|�d�d}|�|ddt�t�t����fg�dS)Nrr z' with a TIME query?r�r�TIMEz:%s)r"r&rr��asctime�	localtimerrrr�ctcpQuery_TIME	s�zIRCClient.ctcpQuery_TIMEc	Cs�|sdS|�dd�d��}t|d|d�}|r2|jdur g|_|t|�dd�}||||�dS|�d�d}|�|dd|�d|�d	�fg�|�|�d
|���dS)a+
        Initiate a Direct Client Connection

        @param user: The hostmask of the user/client.
        @type user: L{bytes}

        @param channel: The name of the IRC channel.
        @type channel: L{bytes}

        @param data: The DCC request message.
        @type data: L{bytes}
        Nr!r�dcc_r�r4zDCC z :Unknown DCC type '�'z offered unknown DCC type )r&r�rJ�dcc_sessionsrTrr")rFr�r�r��dcctype�handlerr�rrr�
ctcpQuery_DCC	s
�zIRCClient.ctcpQuery_DCCcCs�t�|�}t|�dkrtd|����|dd�\}}}t|�}zt|�}Wnty3td|����wd}t|�dkrNzt|d�}Wn	tyMYnw|�||||||�dS)Nr�zmalformed DCC SEND request: �Indecipherable port r%r)�shlexr&rTr�dccParseAddressr<r>�	dccDoSend)rFr�r�r��filename�addressr��sizerrr�dcc_SEND5	s$
��zIRCClient.dcc_SENDcC�tt�|�}t|�dkrtd|����|dd�\}}}z
t|�}t|�}Wn
ty/YdSw|�||||�dS)Nr�z#malformed DCC SEND ACCEPT request: )rFr&rTrr<r>�dccDoAcceptResume�rFr�r�r�rIr�r�rrr�
dcc_ACCEPTM	�
�zIRCClient.dcc_ACCEPTcCrM)Nr�z#malformed DCC SEND RESUME request: )rFr&rTrr<r>�dccDoResumerOrrr�
dcc_RESUMEZ	rQzIRCClient.dcc_RESUMEcCs~t�|�}t|�dkrtd|����|dd�\}}}t|�}zt|�}Wnty3td|����w|�|||||�dS)Nr�zmalformed DCC CHAT request: rE)rFr&rTrrGr<r>�	dccDoChat)rFr�r�r�rIrJr�rrr�dcc_CHATg	s
�zIRCClient.dcc_CHATcCr;)a
        Called when I receive a DCC SEND offer from a client.

        By default, I do nothing here.

        @param user: The hostmask of the requesting user.
        @type user: L{bytes}

        @param address: The IP address of the requesting user.
        @type address: L{bytes}

        @param port: An integer representing the port of the requesting user.
        @type port: L{int}

        @param fileName: The name of the file to be transferred.
        @type fileName: L{bytes}

        @param size: The size of the file to be transferred, which may be C{-1}
            if the size of the file was not specified in the DCC SEND request.
        @type size: L{int}

        @param data: A 3-list of [fileName, address, port].
        @type data: L{list}
        Nr)rFr�rJr�r�rKr�rrrrHy	r�zIRCClient.dccDoSendcCr;)a�
        Called when a client is trying to resume an offered file via DCC send.
        It should be either replied to with a DCC ACCEPT or ignored (default).

        @param user: The hostmask of the user who wants to resume the transfer
            of a file previously offered via DCC send.
        @type user: L{bytes}

        @param file: The name of the file to resume the transfer of.
        @type file: L{bytes}

        @param port: An integer representing the port of the requesting user.
        @type port: L{int}

        @param resumePos: The position in the file from where the transfer
            should resume.
        @type resumePos: L{int}
        Nr�rFr�r�r�r�rrrrR�	�zIRCClient.dccDoResumecCr;)a]
        Called when a client has verified and accepted a DCC resume request
        made by us.  By default it will do nothing.

        @param user: The hostmask of the user who has accepted the DCC resume
            request.
        @type user: L{bytes}

        @param file: The name of the file to resume the transfer of.
        @type file: L{bytes}

        @param port: An integer representing the port of the accepting user.
        @type port: L{int}

        @param resumePos: The position in the file from where the transfer
            should resume.
        @type resumePos: L{int}
        NrrVrrrrN�	rWzIRCClient.dccDoAcceptResumecCrrIr)rFr�r�rJr�r�rrrrT�	rzIRCClient.dccDoChatcC�|�|t|��dS)z�
        Send one or more C{extended messages} as a CTCP reply.

        @type messages: a list of extended messages.  An extended
        message is a (tag, data) tuple, where 'data' may be L{None}.
        N)r��
ctcpStringify�rFr�rrrrr�	�zIRCClient.ctcpMakeReplycCrX)z�
        Send one or more C{extended messages} as a CTCP query.

        @type messages: a list of extended messages.  An extended
        message is a (tag, data) tuple, where 'data' may be L{None}.
        N)rwrYrZrrrr��	r[zIRCClient.ctcpMakeQuerycCsP|D]#}t|d|dd�}|r||||d�q|�|||d|d�qdS)z@
        Dispatch method for any CTCP replies received.
        zctcpReply_%srNr!)rJ�ctcpUnknownReply)rFr�r�rr�rPrrrr��	s�zIRCClient.ctcpReplycCs^|�dd�d}|jr||f|jvrtd|�d|����|j||f}|�|t��|�dS)Nr�r!rzBogus PING response from r)r&r�rrur�)rFr�r�r�r��t0rrr�ctcpReply_PING�	s
zIRCClient.ctcpReply_PINGc	Cs"t�d|�d|�d|�d��dS)a�
        Called when a fitting ctcpReply_ method is not found.

        @param user: The hostmask of the user.
        @type user: L{bytes}

        @param channel: The name of the IRC channel.
        @type channel: L{bytes}

        @param tag: The CTCP request tag for which no fitting method is found.
        @type tag: L{bytes}

        @param data: The CTCP message.
        @type data: L{bytes}
        zUnknown CTCP reply from rr#r9Nrrrrrr\�	s"zIRCClient.ctcpUnknownReplyc	Cs(t�|�t�d�t�|||���dS)a
        When I get a message that's so broken I can't use it.

        @param line: The indecipherable message.
        @type line: L{bytes}

        @param excType: The exception type of the exception raised by the
            message.
        @type excType: L{type}

        @param excValue: The exception parameter of excType or its associated
            value(the second argument to C{raise}).
        @type excValue: L{BaseException}

        @param tb: The Traceback as a traceback object.
        @type tb: L{traceback}
        r N)rrwrt�	traceback�format_exception)rFr4�excType�excValue�tbrrr�
badMessage
s
zIRCClient.badMessagecCst�|d�dS)z�
        This is called when I receive a message which is peculiar, but not
        wholly indecipherable.

        @param s: The peculiar message.
        @type s: L{bytes}
        r9Nr�rFr*rrrr""
szIRCClient.quirkyMessagecCs(t�|_g|_|jr|�|j�dSdSrI)r�r�rK�performLoginr�r�rErrrrf.
s
�zIRCClient.connectionMadecCs2t|t�r
|�d�}|�dd�}tj�||�dS)NrhrF�)rkr;rlr�r	rGr��rFr�rrrr�4
s

zIRCClient.dataReceivedcCs�ttkrt|t�r|�d�}t|�}zt|�\}}}|tvr"t|}|�|||�WdSty@|j	|gt
���R�YdSwrg)r�r;rkr��
lowDequoter/�numeric_to_symbolicr�rrd�sys�exc_info)rFr4r+r.rXrrr�lineReceived:
s
�zIRCClient.lineReceivedcCsddgS)z�
        Get user modes that require parameters for correct parsing.

        @rtype: C{[str, str]}
        @return: C{[add, remove]}
        r rrErrrr�H
szIRCClient.getUserModeParamscCs�ddg}|j�di�}d�|���|d<|d<|j�d�}|durL|d|�dd�7<|d|�dd�7<|d|d<|d|�d	d�7<|S)
z�
        Get channel modes that require parameters for correct parsing.

        @rtype: C{[str, str]}
        @return: C{[add, remove]}
        r r�rr!r�Nrr^r)r�rrt�keysr)rFrX�prefixes�	chanmodesrrrr�Q
s	zIRCClient.getChannelModeParamscCr�r�r�r�rrrr�f
r�zIRCClient.handleCommandcCs|j��}d|d<d|d<|S)NrAr�)�__dict__�copy)rF�dctrrr�__getstate__~
s
zIRCClient.__getstate__rI)NNN)r )r�r�)�rrrrrcr�r�r�r�r�r0r#r(r)r*r-�dcc_destdirrArfrJrKrL�	delimiter�
__pychecker__r�r�r�rVrYrIrprMrPrUrTrQr[r]r_rdrerfr�rhrjrkr�rorprqrsrurvrxrzr|r}rr�r�r�r�r�rtr�r�r�r�r�r�r�r�rwr�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�r�r�r�r�r�r�rrrrrr	r
rr
rrr�r�rrrr&r+r.r1r9r:r>rDrLrPrSrUrHrRrNrTrr�r�r^r\rdr"rfr�rmr�r�r�rtrrrrrA`s*Q			





"
%	







!
	
			"


	rAcCstd|vr	|Szt|�}Wntytd|����w|d?d@|d?d@|d?d@|d@f}d�tt|��}|S)Nr�zIndecipherable address ��r��)r<r>rrtrr;)rJrrrrG�
s��


�rGc@s&eZdZdZdZddd�Zdd�ZdS)	�DccFileReceiveBasica[
    Bare protocol to receive a Direct Client Connection SEND stream.

    This does enough to keep the other guy talking, but you'll want to extend
    my dataReceived method to *do* something with the data I get.

    @ivar bytesReceived: An integer representing the number of bytes of data
        received.
    @type bytesReceived: L{int}
    rcCs||_|dk|_dS)z�
        @param resumeOffset: An integer representing the amount of bytes from
            where the transfer of data should be resumed.
        @type resumeOffset: L{int}
        rN)�
bytesReceived�resume)rF�resumeOffsetrrrr��
szDccFileReceiveBasic.__init__cCs*|jt|�|_|j�t�d|j��dS)z�
        See: L{protocol.Protocol.dataReceived}

        Warning: This just acknowledges to the remote host that the data has
        been received; it doesn't I{do} anything with the data, so you'll want
        to override this.
        z!iN)r|rTrmrn�struct�packrhrrrr��
sz DccFileReceiveBasic.dataReceivedN)r)rrrrr|r�r�rrrrr{�
s

	r{c@sLeZdZdZdZdZdZdZdZdd�Z	dd�Z
d	d
�Zdd�Zd
d�Z
dS)�DccSendProtocola�
    Protocol for an outgoing Direct Client Connection SEND.

    @ivar blocksize: An integer representing the size of an individual block of
        data.
    @type blocksize: L{int}

    @ivar file: The file to be sent.  This can be either a file object or
        simply the name of the file.
    @type file: L{file} or L{bytes}

    @ivar bytesSent: An integer representing the number of bytes sent.
    @type bytesSent: L{int}

    @ivar completed: An integer representing whether the transfer has been
        completed or not.
    @type completed: L{int}

    @ivar connected: An integer representing whether the connection has been
        established or not.
    @type connected: L{int}
    iNrcCst|�tur
t|�|_dSdSrI)�typer;�openr��rFr�rrrr��
s�zDccSendProtocol.__init__cCsd|_|��dSr)�	connected�	sendBlockrErrrrf�
szDccSendProtocol.connectionMadecCs>t�d|�}||jkr
dS||jkr|j��dS|��dS)Nz!I)r�unpack�	bytesSentrm�loseConnectionr�)rFr��bytesShesGotrrrr��
s


zDccSendProtocol.dataReceivedcCsF|j�|j�}|r|j�|�|jt|�|_dS|j��d|_dSr)	r��read�	blocksizermrnr�rTr��	completed)rF�blockrrrr��
s

zDccSendProtocol.sendBlockcCs$d|_t|jd�r|j��dSdS)Nr�close)r��hasattrr�r�rRrrrrP�
s�zDccSendProtocol.connectionLost)rrrrr�r�r�r�r�r�rfr�r�rPrrrrr��
s
r�c@s eZdZeZdd�Zdd�ZdS)�DccSendFactorycCs
||_dSrI)r�r�rrrr�s
zDccSendFactory.__init__cCs|�|j�}||_|SrI)rr��factory)rF�
connection�prrr�
buildProtocol
szDccSendFactory.buildProtocolN)rrrr�rr�r�rrrrr�sr�c
Cs�d}t|d�r"|��}z
t�|�}|tj}W|Sty!Ynwt|d�r@t�|j	�r@z	t�
|j	�}W|Sty?Ynwt|d�rqt|d�rqzz|�dd�|��}W|�dd�W|S|�dd�wtypY|Sw|S)a3
    I'll try my damndest to determine the size of this file object.

    @param file: The file object to determine the size of.
    @type file: L{io.IOBase}

    @rtype: L{int} or L{None}
    @return: The size of the file object as an integer if it can be determined,
        otherwise return L{None}.
    N�filenorK�seek�tellrr�)
r�r��os�fstat�stat�ST_SIZEr�r�existsrK�getsizer�r�)r�rKr��stat_rrr�fileSizes<

����
��r�c@sNeZdZdZdZe�d�e�d�ZdZ	dZ
dZddd�Zdd�Z
d	d
�ZdS)�DccChataH
    Direct Client Connection protocol type CHAT.

    DCC CHAT is really just your run o' the mill basic.LineReceiver
    protocol.  This class only varies from that slightly, accepting
    either LF or CR LF for a line delimeter for incoming messages
    while always using CR LF for outgoing.

    The lineReceived method implemented here uses the DCC connection's
    'client' attribute (provided upon construction) to deliver incoming
    lines from the DCC chat via IRCClient's normal privmsg interface.
    That's something of a spoof, which you may well want to override.
    N�asciirgcCs$||_|r||_|jd|_dSdS)aw
        Initialize a new DCC CHAT session.

        queryData is a 3-tuple of
        (fromUser, targetUserOrChannel, data)
        as received by the CTCP query.

        (To be honest, fromUser is the only thing that's currently
        used here. targetUserOrChannel is potentially useful, while
        the 'data' argument is solely for informational purposes.)
        rN)�client�	queryData�remoteParty�rFr�r�rrrr�Rs
�zDccChat.__init__cCsR|j||_|j�t�}|��|_|D]}|dtkr!|dd�}|�|�qdS)Nr%)r�r&rjr)rirm)rFr�r�r4rrrr�cs
�zDccChat.dataReceivedcCs2t�d|j�d|���|j�|j|jj|�dS)Nz	DCC CHAT<z> )rrwr�r�r�r�rNrrrrmoszDccChat.lineReceivedrI)rrrrr�rirl�NLrvr�r�r�r�r�rmrrrrr�=s
r�c@s4eZdZeZdZdd�Zdd�Zdd�Zdd	�Z	d
S)�DccChatFactoryFcCs||_||_dSrI�r�r�r�rrrr�xs
zDccChatFactory.__init__cCs|j|j|jd�}||_|S)Nr�)rr�r�r�)rF�addrr�rrrr�|szDccChatFactory.buildProtocolcC�|jj�|�dSrI�r�rA�remove�rF�unused_connector�
unused_reasonrrr�clientConnectionFailed�rz%DccChatFactory.clientConnectionFailedcCr�rIr�r�rrr�clientConnectionLost�rz#DccChatFactory.clientConnectionLostN)
rrrr�r�noisyr�r�r�r�rrrrr�tsr�c
Cs|}|��}t|�dkr|S|dd�\}}}}d|vrn,zt|�}Wn	ty,Ynw|d?d@|d?d@|d?d@|d@f}d�tt|��}|dkrx|}d	}t|�d
krnz
t|d�}d|f}Wn	tymYnwd�||||�}	|	S|d
kr�d|�d|��}	|	S|}	|	S)z�
    Given the data chunk from a DCC query, return a descriptive string.

    @param data: The data from a DCC query.
    @type data: L{bytes}

    @rtype: L{bytes}
    @return: A descriptive string.
    rNr�rxryr�rz�SENDr �z of size %d bytesz(SEND for file '{}'{} at host {}, port {}�CHATzCHAT for host z, port )r&rTr<r>rtrr;rv)
r��	orig_datarB�argrJr�rI�size_txtrK�dcc_textrrr�dccDescribe�sP�


�����r�c@s�eZdZUdZdZdZdZdZdZe	e
ed<dZ	ddd	�Z
d
d�Zdd
�Zdd�Zdd�Zdd�Zdd�Zdefdd�Zdefdd�ZdS)�DccFileReceivea�
    Higher-level coverage for getting a file from DCC SEND.

    I allow you to change the file's name and destination directory.  I won't
    overwrite an existing file unless I've been told it's okay to do so.  If
    passed the resumeOffset keyword argument I will attempt to resume the file
    from that amount of bytes.

    XXX: I need to let the client know when I am finished.
    XXX: I need to decide how to keep a progress indicator updated.
    XXX: Client needs a way to tell me "Do not finish until I say so."
    XXX: I need to make sure the client understands if the file cannot be written.

    @ivar filename: The name of the file to get.
    @type filename: L{bytes}

    @ivar fileSize: The size of the file to get, which has a default value of
        C{-1} if the size of the file was not specified in the DCC SEND
        request.
    @type fileSize: L{int}

    @ivar destDir: The destination directory for the file to be received.
    @type destDir: L{bytes}

    @ivar overwrite: An integer representing whether an existing file should be
        overwritten or not.  This initially is an L{int} but can be modified to
        be a L{bool} using the L{set_overwrite} method.
    @type overwrite: L{int} or L{bool}

    @ivar queryData: queryData is a 3-tuple of (user, channel, data).
    @type queryData: L{tuple}

    @ivar fromUser: This is the hostmask of the requesting user and is found at
        index 0 of L{queryData}.
    @type fromUser: L{bytes}
    �dccr%r�rN�fromUsercCsDtj||d�||_||_||_||_|r ||_|jd|_dSdS)N)r~r)r{r�rI�destDirr��
_resumeOffsetr�r�)rFrIr�r�r�r~rrrr��s�zDccFileReceive.__init__cCs\t�|�sttjd|��t�|�sttjd|��t�|tj	tj
B�s)ttjd|��||_dS)a
        Set the directory where the downloaded file will be placed.

        May raise OSError if the supplied directory path is not suitable.

        @param directory: The directory where the file to be received will be
            placed.
        @type directory: L{bytes}
        zYou see no directory there.z>You cannot put a file into something which is not a directory.z*This directory is too hard to write in to.N)
rr��OSError�errno�ENOENT�isdir�ENOTDIRr��access�X_OK�W_OK�EACCESr�)rF�	directoryrrr�
set_directory�s


��
zDccFileReceive.set_directorycCry)z�
        Change the name of the file being transferred.

        This replaces the file name provided by the sender.

        @param filename: The new name for the file.
        @type filename: L{bytes}
        N)rI)rFrIrrr�set_filenames
	zDccFileReceive.set_filenamecCry)z�
        May I overwrite existing files?

        @param boolean: A boolean value representing whether existing files
            should be overwritten or not.
        @type boolean: L{bool}
        N)�	overwrite)rF�booleanrrr�
set_overwrite s
zDccFileReceive.set_overwritecCs�t�t�|j|j��}t�|�}|jr6|r6t|d�|_|j�	|j
�|j��t�
d|j|j��f�dS|jrB|sBttjd|��|jsG|sOt|d�|_dSttjd|��)Nzrb+z0Attempting to resume %s - starting from %d bytesz8You cannot resume writing to a file that does not exist!�wbzBThere's a file in the way.  Perhaps that's why you cannot open it.)r�abspathrtr�rIr�r}r�r�r�r��truncaterrwr�r�r�r�r��EEXIST)rF�dstr�rrrrf,s0


��
�
�zDccFileReceive.connectionMadecCs|j�|�t�||�dSrI)r�rnr{r�rhrrrr�HszDccFileReceive.dataReceivedcCs�d|_|�d�}|jdkr4d||j|jf}|j|jkrn|j|jkr.d||j|jf}n
|�d�}nd||jf}t|d�rW|�d|jj�d	�}t|jd
�rY|j��dSdSdS)z�
        When the connection is lost, I close the file.

        @param reason: The reason why the connection was lost.
        @type reason: L{Failure}
        rz closed.z%s  %d/%d bytes receivedz%s (Warning: %d bytes short)z (file larger than expected)z%s  %d bytes receivedr�z and written to z.
r�N)r�r�r|r�r�rKr�)rFr��logmsgrrrrPNs.

�
�
�zDccFileReceive.connectionLost�returncCsh|jsdt|�d�d�S|j}|dusJ�t|���}|jdur)|j�d|�d�}d|j�d|��}|S)Nz&<Unconnected DccFileReceive object at r��>z (rzDCC transfer of 'z' from )r��idrmr;�getPeerr�rI)rFrm�from_r*rrr�__str__ps
zDccFileReceive.__str__cCs&d|j�dt|�d�d|j�d�}|S)N�<z at r�z: GET r�)r7r�rIrerrr�__repr__|s"zDccFileReceive.__repr__)r%Nr�r)rrrrrIr�r�r�r�rr�rRr�r�r�r�r�rfr�rPr;r�r�rrrrr��s$
%
�
"r������)�white�black�blue�green�lightRed�red�magenta�orange�yellow�
lightGreen�cyan�	lightCyan�	lightBlue�lightMagenta�gray�	lightGrayr�cCsi|]\}}||�qSrr)r3rK�coderrr�
<dictcomp>�r	r�c@s8eZdZdZe�eje�Ze�ej	e�Z
eee
d�ZdS)�_CharacterAttributesa�
    Factory for character attributes, including foreground and background color
    and non-color attributes such as bold, reverse video and underline.

    Character attributes are applied to actual text by using object
    indexing-syntax (C{obj['abc']}) after accessing a factory attribute, for
    example::

        attributes.bold['Some text']

    These can be nested to mix attributes::

        attributes.bold[attributes.underline['Some text']]

    And multiple values can be passed::

        attributes.normal[attributes.bold['Some'], ' text']

    Non-color attributes can be accessed by attribute name, available
    attributes are:

        - bold
        - reverseVideo
        - underline

    Available colors are:

        0. white
        1. black
        2. blue
        3. green
        4. light red
        5. red
        6. magenta
        7. orange
        8. yellow
        9. light green
        10. cyan
        11. light cyan
        12. light blue
        13. light magenta
        14. gray
        15. light gray

    @ivar fg: Foreground colors accessed by attribute name, see above
        for possible names.

    @ivar bg: Background colors accessed by attribute name, see above
        for possible names.

    @since: 13.1
    )�bold�reverseVideo�	underlineN)rrrrr
�_ColorAttribute�_ForegroundColorAttr�_IRC_COLORS�fg�_BackgroundColorAttr�bg�_BOLD�_REVERSE_VIDEO�
_UNDERLINE�attrsrrrrr��s5��r�c@s2eZdZdZdZ						d	dd�Zdd�ZdS)
�_FormattingStatez�
    Formatting state/attributes of a single character.

    Attributes include:
        - Formatting nullifier
        - Bold
        - Underline
        - Reverse video
        - Foreground color
        - Background color

    @since: 13.1
    ��offr�r�r��
foreground�
backgroundFNcCs(||_||_||_||_||_||_dSrIr)rFrr�r�r�rrrrrr��s	
z_FormattingState.__init__cCs�g}|jr
|�t�|jr|�t�|jr|�t�|jdus$|jdurGd}|jdur3|d|jf7}|jdur@|d|jf7}|�t	|�t
d�tt
|��S)z�
        Emit a mIRC control sequence that will set up all the attributes this
        formatting state has set.

        @return: A string containing mIRC control sequences that mimic this
            formatting state.
        Nr z%02dz,%02d)r�r(r�r�rr�rrr�_COLOR�_OFFrtrr;)rFr�crrr�toMIRCControlCodes
s




z#_FormattingState.toMIRCControlCodes)FFFFNN)rrrr�compareAttributesr�rrrrrr�s
�rcst�fdd�t|�|�S)aI
    Apply a function of two arguments cumulatively to the items of
    a sequence, from right to left, so as to reduce the sequence to
    a single value.

    @type f: C{callable} taking 2 arguments

    @param z: Initial value.

    @param xs: Sequence to reduce.

    @return: Single value resulting from reducing C{xs}.
    cs
�||�SrIr)r��y��frrr�6
s
z_foldr.<locals>.<lambda>)r�reversed)r�z�xsrrr�_foldr(
src
@sdeZdZdZdZedededede	diZ
dd	�Zd
d�Zdd
�Z
dd�Zdd�Zdd�Zdd�ZdS)�_FormattingParsera�
    A finite-state machine that parses formatted IRC text.

    Currently handled formatting includes: bold, reverse, underline,
    mIRC color codes and the ability to remove all current formatting.

    @see: U{http://www.mirc.co.uk/help/color.txt}

    @type _formatCodes: C{dict} mapping C{str} to C{str}
    @cvar _formatCodes: Mapping of format code values to names.

    @type state: C{str}
    @ivar state: Current state of the finite-state machine.

    @type _buffer: C{str}
    @ivar _buffer: Buffer, containing the text content, of the formatting
        sequence currently being parsed, the buffer is used as the content for
        L{_attrs} before being added to L{_result} and emptied upon calling
        L{emit}.

    @type _attrs: C{set}
    @ivar _attrs: Set of the applicable formatting states (bold, underline,
        etc.) for the current L{_buffer}, these are applied to L{_buffer} when
        calling L{emit}.

    @type foreground: L{_ForegroundColorAttr}
    @ivar foreground: Current foreground color attribute, or L{None}.

    @type background: L{_BackgroundColorAttr}
    @ivar background: Current background color attribute, or L{None}.

    @ivar _result: Current parse result.
    �staterr��colorr�r�cCs*d|_d|_t�|_d|_d|_d|_dS)N�TEXTr )r�_bufferrr�_attrs�_resultrrrErrrr�f
s
z_FormattingParser.__init__cCs|�|j|�dS)zs
        Handle input.

        @type ch: C{str}
        @param ch: A single character of input to process
        N)rQr)rFr]rrr�processn
r�z_FormattingParser.processcCs |��|jdur
tj|_|jS)z�
        Flush the current buffer and return the final parsed result.

        @return: Structured text and attributes.
        N)�emitr�
attributesr�rErrr�completew
s
z_FormattingParser.completecCs�|jrAdd�|jD�}|�td|j|jg��|s|�tj�|�|j�t	t
j|��|�}|j
dur7||_
n|j
|d|_dSdS)z?
        Add the currently parsed input to the result.
        cSsg|]}tt|��qSr)rJr)r3rKrrrr8�
r	z*_FormattingParser.emit.<locals>.<listcomp>Nr )rr�extend�filterrrr(rr�r�operator�getitemr)r)rFr�attrrrrr�
s


�z_FormattingParser.emitcCsz|j�|�}|dkr|��d|_dS|dur |j|7_dS|��|dkr4t�|_d|_|_dS|j�	|g�dS)z�
        Handle the "text" state.

        Along with regular text, single token formatting codes are handled
        in this state too.

        @param ch: The character being processed.
        r�COLOR_FOREGROUNDNr)
�_formatCodesrrrrrrrrr�symmetric_difference_update)rFr]�
formatNamerrr�
state_TEXT�
s	
z_FormattingParser.state_TEXTcCs�|��rt|j�dkr|j|7_dS|jr*t|j�tt�}ttjt|�|_	nd|_	|_
|dkr?|jr?d|_d|_dSd|_d|_|��|�
|�dS)aF
        Handle the foreground color state.

        Foreground colors can consist of up to two digits and may optionally
        end in a I{,}. Any non-digit or non-comma characters are treated as
        invalid input and result in the state being reset to "text".

        @param ch: The character being processed.
        r�Nr
r �COLOR_BACKGROUNDr)�isdigitrTrr<r�rJrr��_IRC_COLOR_NAMESrrrrr�rFr]�colrrr�state_COLOR_FOREGROUND�
s
z(_FormattingParser.state_COLOR_FOREGROUNDcCst|��rt|j�dkr|j|7_dS|jr,t|j�tt�}ttjt|�|_	d|_|�
�d|_|�|�dS)ad
        Handle the background color state.

        Background colors can consist of up to two digits and must occur after
        a foreground color and must be preceded by a I{,}. Any non-digit
        character is treated as invalid input and results in the state being
        set to "text".

        @param ch: The character being processed.
        r�r rN)
r*rTrr<r�rJrr�r+rrrrr,rrr�state_COLOR_BACKGROUND�
sz(_FormattingParser.state_COLOR_BACKGROUNDN)rrrrr+r	r�rrrr%r�rrrr(r.r/rrrrr9
s "�	$rcCs"t�}|D]}|�|�q|��S)a 
    Parse text containing IRC formatting codes into structured information.

    Color codes are mapped from 0 to 15 and wrap around if greater than 15.

    @type text: C{str}
    @param text: Formatted text to parse.

    @return: Structured text and attributes.

    @since: 13.1
    )rrr)r�rr]rrr�parseFormattedText�
s
r0cCst�|t�d�S)aE
    Assemble formatted text from structured information.

    Currently handled formatting includes: bold, reverse, underline,
    mIRC color codes and the ability to remove all current formatting.

    It is worth noting that assembled text will always begin with the control
    code to disable other attributes for the sake of correctness.

    For example::

        from twisted.words.protocols.irc import attributes as A
        assembleFormattedText(
            A.normal[A.bold['Time: '], A.fg.lightRed['Now!']])

    Would produce "Time: " in bold formatting, followed by "Now!" with a
    foreground color of light red and without any additional formatting.

    Available attributes are:
        - bold
        - reverseVideo
        - underline

    Available colors are:
        0. white
        1. black
        2. blue
        3. green
        4. light red
        5. red
        6. magenta
        7. orange
        8. yellow
        9. light green
        10. cyan
        11. light cyan
        12. light blue
        13. light magenta
        14. gray
        15. light gray

    @see: U{http://www.mirc.co.uk/help/color.txt}

    @param formatted: Structured text and attributes.

    @rtype: C{str}
    @return: String containing mIRC control sequences that mimic those
        specified by I{formatted}.

    @since: 13.1
    r)r
�flattenr)�	formattedrrr�assembleFormattedText�
s4r3cCst|�}t�|t���S)z�
    Remove all formatting codes from C{text}, leaving only the text.

    @type text: C{str}
    @param text: Formatted text to parse.

    @rtype: C{str}
    @return: Plain text without any control sequences.

    @since: 13.1
    )r0r
r1�DefaultFormattingState)r�r2rrr�stripFormatting5sr5r!c
Cs�g}g}||d�}|�t�}d}|r*|r|�|�d��n|�|�d��|}|sttd|��|dd�<ttd|��|dd�<ttt|��|dd�<tt	|��D]!}||�t
d�}|d}t	|�dkrj|d}	nd}	||	f||<qQ|S)z�
    Extract CTCP data from a string.

    @return: A C{dict} containing two keys:
       - C{'extended'}: A list of CTCP (tag, data) tuples.
       - C{'normal'}: A list of strings which were not inside a CTCP delimiter.
    )r�r�rNr!)r&r�r(r)rur r�ctcpDequoterrT�SPC)
r��extended_messages�normal_messages�retvalr�oddr�r�r�r�rrrr�Js,

�
r��0r��rr%r�cCs&ttttfD]
}|�|t|�}q|SrI)�M_QUOTE�NULr�rir��mQuoteTable�r*r
rrrr��sr�cC�tfdd�}t�||�S)NcS�4|��d}z||}W|Sty|}Y|Swr��group�KeyError)�matchobj�
mDequoteTabler*rrr�sub��
��zlowDequote.<locals>.sub)rH�
mEscape_rerI�r*rIrrrri��rir�r�cCs"ttfD]
}|�|t|�}q|SrI)�X_QUOTEr�r��xQuoteTablerArrr�	ctcpQuote�srPcCrB)NcSrCrrD)rG�
xDequoteTabler*rrrrI�rJzctcpDequote.<locals>.sub)rQ�
xEscape_rerIrLrrrr6�rMr6c	Cs�g}|D]<\}}|r+t|t�s#z
d�tt|��}Wn	ty"Ynw|�d|��}nt|�}t|�}t�|�t��}|�|�qd�|�}|S)z�
    @type messages: a list of extended messages.  An extended
    message is a (tag, data) tuple, where 'data' may be L{None}, a
    string, or a list of strings to be joined with whitespace.

    @returns: String
    r#r )rkr;rtrr=rPr�r()r�coded_messagesr�r�r�r4rrrrY�s 
�
rY�001�002�003�004�005�010�302�303�301�305�306�311�312�313�317�318�319�314�369�321�322�323�325�324�331�332�341�342�346�347�348�349�351�352�315�353�366�364�365�367�368�371�374�375�372�376�381�382�383�391�392�393�394�395�200�201�202�203�204�205�206�207�208�209�210�261�262�211�212�219�242�243�221�234�235�251�252�253�254�255�256�257�258�259�263�401�402�403�404�405�406�407�408�409�411�412�413�414�415�416�421�422�423�424�431�432�433�436�437�441�442�443�444�445�446�451�461�462�463�464�465�466�467�471�472�473�474�475�476�477�478�481�482�483�484�485�491�492�501�502�RPL_WELCOME�RPL_YOURHOST�RPL_CREATED�
RPL_MYINFO�RPL_ISUPPORT�
RPL_BOUNCE�RPL_USERHOST�RPL_ISON�RPL_AWAY�
RPL_UNAWAY�RPL_NOWAWAYr�r�r�r�r�r��RPL_WHOWASUSER�RPL_ENDOFWHOWAS�
RPL_LISTSTART�RPL_LIST�RPL_LISTEND�RPL_UNIQOPISr�r�r��RPL_INVITING�
RPL_SUMMONING�RPL_INVITELIST�RPL_ENDOFINVITELIST�RPL_EXCEPTLIST�RPL_ENDOFEXCEPTLIST�RPL_VERSIONr�r�r�r��	RPL_LINKS�RPL_ENDOFLINKS�RPL_BANLIST�RPL_ENDOFBANLIST�RPL_INFO�
RPL_ENDOFINFO�
RPL_MOTDSTART�RPL_MOTD�
RPL_ENDOFMOTD�
RPL_YOUREOPER�
RPL_REHASHING�RPL_YOURESERVICE�RPL_TIME�RPL_USERSSTART�	RPL_USERS�RPL_ENDOFUSERS�RPL_NOUSERS�
RPL_TRACELINK�RPL_TRACECONNECTING�RPL_TRACEHANDSHAKE�RPL_TRACEUNKNOWN�RPL_TRACEOPERATOR�
RPL_TRACEUSER�RPL_TRACESERVER�RPL_TRACESERVICE�RPL_TRACENEWTYPE�RPL_TRACECLASS�RPL_TRACERECONNECT�RPL_TRACELOG�RPL_TRACEEND�RPL_STATSLINKINFO�RPL_STATSCOMMANDS�RPL_ENDOFSTATS�RPL_STATSUPTIME�RPL_STATSOLINE�RPL_UMODEIS�RPL_SERVLIST�RPL_SERVLISTEND�RPL_LUSERCLIENT�RPL_LUSEROP�RPL_LUSERUNKNOWN�RPL_LUSERCHANNELS�RPL_LUSERME�RPL_ADMINME�
RPL_ADMINLOC1�
RPL_ADMINLOC2�RPL_ADMINEMAIL�RPL_TRYAGAIN�ERR_NOSUCHNICK�ERR_NOSUCHSERVER�ERR_NOSUCHCHANNEL�ERR_CANNOTSENDTOCHAN�ERR_TOOMANYCHANNELS�ERR_WASNOSUCHNICK�ERR_TOOMANYTARGETS�ERR_NOSUCHSERVICE�ERR_NOORIGIN�ERR_NORECIPIENT�ERR_NOTEXTTOSEND�ERR_NOTOPLEVEL�ERR_WILDTOPLEVEL�ERR_BADMASK�ERR_TOOMANYMATCHES�ERR_UNKNOWNCOMMAND�
ERR_NOMOTD�ERR_NOADMININFO�
ERR_FILEERROR�ERR_NONICKNAMEGIVEN�ERR_ERRONEUSNICKNAME�ERR_NICKNAMEINUSE�ERR_NICKCOLLISION�ERR_UNAVAILRESOURCE�ERR_USERNOTINCHANNEL�ERR_NOTONCHANNEL�ERR_USERONCHANNEL�ERR_NOLOGIN�ERR_SUMMONDISABLED�ERR_USERSDISABLED�ERR_NOTREGISTERED�ERR_NEEDMOREPARAMS�ERR_ALREADYREGISTRED�ERR_NOPERMFORHOST�ERR_PASSWDMISMATCH�ERR_YOUREBANNEDCREEP�ERR_YOUWILLBEBANNED�
ERR_KEYSET�ERR_CHANNELISFULL�ERR_UNKNOWNMODE�ERR_INVITEONLYCHAN�ERR_BANNEDFROMCHAN�ERR_BADCHANNELKEY�ERR_BADCHANMASK�ERR_NOCHANMODES�ERR_BANLISTFULL�ERR_NOPRIVILEGES�ERR_CHANOPRIVSNEEDED�ERR_CANTKILLSERVER�ERR_RESTRICTED�ERR_UNIQOPPRIVSNEEDED)�ERR_NOOPERHOST�ERR_NOSERVICEHOST�ERR_UMODEUNKNOWNFLAG�ERR_USERSDONTMATCH)r0rI)rS)�rr�r!r�r��rerFrdr�r�rrkr1r�r_�	functoolsrr�typingr�twisted.internetrrr�twisted.persistedr�twisted.protocolsr	�twisted.pythonr
rrrr?rir�rjr7r�r��	Exceptionrrr>rr/r&rA�RuntimeErrorrBrCr_�Protocolr`r�rGrArG�	Ephemeralr{r��Factoryr�r�r��
ClientFactoryr�r�r�r	r�rrrrrrr�r�r+�CharacterAttributesMixinr�r�_FormattingStateMixinrrrr0r3r5r�r�r>r@rHr�r�compile�escape�DOTALLrKr�rirNrOrQrRrPr6rYr�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�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�rrrrrrrrrr	r
rrr
rrrrrrrrrrrrrrrrrrr r!r"r#r$r%r&r'r(r)r*r+r,r-r.r/r0r1r2r3r4r5r6r7r8r9r:r;r<r=r>r?r@rArBrCrDrErFrGrHrIrJrKrLrMrNrOrPrQrRrSrTrUrVrWrXrYrZr[r\r]r^�symbolic_to_numericrjrrrr�<module>sZ (:"H1#I-7;?��@A37*���������	�
���
������������������� �!�"�#�$�%�&�'�(�)�*�+�,�-�.�/�0�1�2�3�4�5�6�7�8�9�:�;�<�=�>�?�@�A�B�C�D�E�F�G�H�I�J�K�L�M�N�O�P�Q�R�S�T�U�V�W�X�Y�Z�[�\�]�^�_�`�a�b�c�d�e�f�g�h�i�j�k�l�m�n�o�p�q�r�s�t�u�v�w�x�y�z�{�|�}�~������������������	��
�
��

Spamworldpro Mini