U
    Â“«j&—  ã                   @   s  d Z ddlmZmZ ddlmZ ddlmZ ddlmZm	Z
mZ ddlmZmZ ddlmZmZmZ ddlmZ dd	lmZ dd
lmZmZ ddlmZ eejƒG dd„ dƒƒZeejƒG dd„ dƒƒZdZ eej!ƒG dd„ dej"ƒƒZ#G dd„ dej$ƒZ%G dd„ dej&ƒZ'eej!ƒG dd„ dej(ƒƒZ)e *e'e)¡ G dd„ dej&ƒZ+eejƒG dd„ dej(ƒƒZ,e *e+e,¡ G dd„ dej&ƒZ-eej!ƒG dd „ d ej&ƒƒZ.ee.ejej/ƒ G d!d"„ d"ej(ƒZ0e *e.e0¡ eej1ej2ƒG d#d$„ d$ƒƒZ3G d%d&„ d&e3ƒZ4ddd$d&gZ5d'S )(a  
A module that needs a better name.

Implements new cred things for words.

How does this thing work?

  - Network connection on some port expecting to speak some protocol

  - Protocol-specific authentication, resulting in some kind of credentials object

  - twisted.cred.portal login using those credentials for the interface
    IUser and with something implementing IChatClient as the mind

  - successful login results in an IUser avatar the protocol can call
    methods on, and state added to the realm such that the mind will have
    methods called on it as is necessary

  - protocol specific actions lead to calls onto the avatar; remote events
    lead to calls onto the mind

  - protocol specific hangup, realm is notified, user is removed from active
    play, the end.
é    )ÚctimeÚtime)Úimplementer)Ú	copyright)ÚcredentialsÚerrorÚportal)ÚdeferÚprotocol)ÚfailureÚlogÚreflect)ÚregisterAdapter)Úpb)ÚewordsÚiwords)Úircc                   @   sV   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zdd
d„Zdd„ Zdd„ Z	dd„ Z
dd„ Zd	S )ÚGroupc                 C   s   || _ i | _dddœ| _d S )NÚ )ÚtopicÚtopic_author)ÚnameÚusersÚmeta©Úselfr   © r   ú9/tmp/pip-unpacked-wheel-59kc99xd/twisted/words/service.pyÚ__init__.   s
    þzGroup.__init__c                 C   s   t  t||ƒ¡S ©N)r   ÚFailureÚ	Exception)r   ÚerrÚpr   r   r   Ú_ebUserCall6   s    zGroup._ebUserCallc                 C   s0   |D ]&\}}|s|j \}}|  || ¡ ¡ qd S r   )ÚvalueÚremoveÚgetErrorMessage)r   ÚresultsÚsuccessÚresultÚuserr"   r   r   r   Ú_cbUserCall9   s    
zGroup._cbUserCallc                 C   s”   t j |¡std |¡ƒ‚|j| jkrŠg }|| j|j< | j ¡ D ]6}||k	r@t 	|j
| |¡}|j| j|d� | |¡ q@t |¡ | j¡ t d ¡S )Nz{!r} is not a chat client©r#   )r   ÚIChatClientÚ
providedByÚAssertionErrorÚformatr   r   Úvaluesr	   ÚmaybeDeferredÚ
userJoinedÚ
addErrbackr$   ÚappendÚDeferredListÚaddCallbackr,   Úsucceed)r   r+   Z	additionsr#   Údr   r   r   Úadd?   s    ÿz	Group.addNc                 C   sˆ   z| j |j= W n tk
r"   Y n\X g }| j  ¡ D ]8}||k	r2t |j| ||¡}|j| j|d� | 	|¡ q2t 
|¡ | j¡ t d ¡S ©Nr-   )r   r   ÚKeyErrorr2   r	   r3   ÚuserLeftr5   r$   r6   r7   r8   r,   r9   )r   r+   ÚreasonZremovalsr#   r:   r   r   r   r&   N   s    zGroup.removec                 C   s   t  t| jƒ¡S r   )r	   r9   Úlenr   ©r   r   r   r   Úsize]   s    z
Group.sizec                 C   sp   || kst ‚g }| j ¡ D ]8}||k	rt |j|| |¡}|j| j|d� | |¡ qt 	|¡ 
| j¡ t d ¡S r<   )r0   r   r2   r	   r3   Úreceiver5   r$   r6   r7   r8   r,   r9   )r   ÚsenderÚ	recipientÚmessageZreceivesr#   r:   r   r   r   rC   `   s    zGroup.receivec                 C   s`   || _ g }| j ¡ D ].}t |j| |¡}|j| j|d� | |¡ qt 	|¡ 
| j¡ t d ¡S r<   )r   r   r2   r	   r3   ÚgroupMetaUpdater5   r$   r6   r7   r8   r,   r9   )r   r   Zsetsr#   r:   r   r   r   ÚsetMetadatak   s    zGroup.setMetadatac                 C   s   t | j ¡ ƒS r   )Úiterr   r2   rA   r   r   r   Ú	iterusersu   s    zGroup.iterusers)N)Ú__name__Ú
__module__Ú__qualname__r   r$   r,   r;   r&   rB   rC   rH   rJ   r   r   r   r   r   ,   s   

r   c                   @   sN   e Zd ZdZdZdd„ Zdd„ Zdd„ Zddd	„Zd
d„ Z	dd„ Z
dd„ ZdS )ÚUserNc                 C   s   || _ g | _tƒ | _d S r   )r   Úgroupsr   ÚlastMessager   r   r   r   r      s    zUser.__init__c                 C   s   || _ || _tƒ | _d S r   )ÚrealmÚmindr   ÚsignOn)r   rQ   rR   r   r   r   ÚloggedIn„   s    zUser.loggedInc                    s    ‡ ‡fdd„}ˆ   ˆj¡ |¡S )Nc                    s   ˆj  ˆ ¡ | S r   )rO   r6   ©r*   ©Úgroupr   r   r   ÚcbJoinŠ   s    zUser.join.<locals>.cbJoin)r;   rR   r8   )r   rW   rX   r   rV   r   Újoin‰   s    z	User.joinc                    s"   ‡ ‡fdd„}ˆ   ˆj|¡ |¡S )Nc                    s   ˆj  ˆ ¡ | S r   )rO   r&   rU   rV   r   r   ÚcbLeave‘   s    zUser.leave.<locals>.cbLeave)r&   rR   r8   )r   rW   r?   rZ   r   rV   r   Úleave�   s    z
User.leavec                 C   s   t ƒ | _| | j||¡S r   )r   rP   rC   rR   )r   rE   rF   r   r   r   Úsend—   s    z	User.sendc                 C   s
   t | jƒS r   )rI   rO   rA   r   r   r   Ú
itergroups›   s    zUser.itergroupsc                 C   s"   | j d d … D ]}|  |¡ qd S r   )rO   r[   )r   Úgr   r   r   Úlogoutž   s    zUser.logout)N)rK   rL   rM   rQ   rR   r   rT   rY   r[   r\   r]   r_   r   r   r   r   rN   z   s   
rN   zNickServ!NickServ@servicesc                   @   s‚  e Zd ZdZdZdZdZdZdZdd„ Z	dd„ Z
dd	„ Zd
d„ ZdPdd„Zdd„ Zdd„ ZdZdZdd„ Zdd„ Zdd„ Zdd„ Zdd„ ZejdfejdfejdfejdfgZejd fejd!fgZd"d#„ Z d$d%„ Z!d&d'„ Z"d(d)„ Z#dQd*d+„Z$dRd,d-„Z%d.d/„ Z&d0d1„ Z'd2d3„ Z(d4d5„ Z)d6d7„ Z*d8d9„ Z+d:d;„ Z,d<d=„ Z-d>d?„ Z.d@dA„ Z/dBdC„ Z0dDdE„ Z1dFdG„ Z2dHdI„ Z3dJdK„ Z4dLdM„ Z5dNdO„ Z6dS )SÚIRCUserzM
    Protocol instance representing an IRC user connected to the server.
    Núutf-8c                 C   s    | j | _| jj| _| jj| _d S r   )Úirc_NICKSERV_PRIVMSGÚirc_PRIVMSGÚfactoryrQ   r   ÚhostnamerA   r   r   r   ÚconnectionMade¼   s    
zIRCUser.connectionMadec                 C   s   | j d k	r|   ¡  d | _d S r   )r_   Úavatar©r   r?   r   r   r   ÚconnectionLostÁ   s    
zIRCUser.connectionLostc                 O   s€   d|kr| j |d< d|kr,| j | j¡|d< | ||d gt|ƒ }g }|D ]"}t|tƒrb| d¡}| |¡ qJt	j
j||Ž d S )NÚprefixÚtora   )re   r   ÚencodeÚencodingÚlistÚ
isinstanceÚbytesÚdecoder6   r   ÚIRCÚsendMessage)r   ÚcommandZparameter_listÚkwZarglistZarglistUnicodeÚargr   r   r   rs   Ç   s    


zIRCUser.sendMessagec                 C   s,   |   |j› d|j› d| j› �d|j ¡ d S )Nú!ú@ú#)rY   r   re   ©r   rW   r+   r   r   r   r4   Ö   s    zIRCUser.userJoinedc                 C   s2   |   |j› d|j› d| j› �d|j |p*d¡ d S )Nrw   rx   ry   Zleaving)Úpartr   re   ©r   rW   r+   r?   r   r   r   r>   Ù   s
    ýzIRCUser.userLeftc                 C   s`   t j |¡rd|j }n|j}| dd¡}| ¡ D ](}|  |j› d|j› d| j› �||¡ q2d S )Nry   Útextz<an unrepresentable message>rw   rx   )r   ÚIGroupr/   r   ÚgetÚ
splitlinesÚprivmsgre   )r   rD   rE   rF   ZrecipientNamer}   ÚLr   r   r   rC   à   s    ýzIRCUser.receivec              
   C   sJ   d|krF|d }|  dd¡}|  | jd|j ||› d|› d| j› �¡ d S )Nr   r   r   ry   rw   rx   )r   r   r   re   )r   rW   r   r   Úauthorr   r   r   rG   ñ   s    üzIRCUser.groupMetaUpdatec                 C   s   |d | _ dS )zÃ
        Password message -- Register a password.

        Parameters: <password>

        [REQUIRED]

        Note that IRC requires the client send this *before* NICK
        and USER.
        éÿÿÿÿN)Úpassword©r   rj   Úparamsr   r   r   Úirc_PASS   s    zIRCUser.irc_PASSc                 C   s¼   |d }zt |tƒr | | j¡}W n2 tk
rT   |  tt|ƒd¡ | j 	¡  Y dS X || _
|| _| jD ]\}}|  ||| jj ¡ qh| jdkr |  t|d¡ n| j}d| _|  ||¡ dS )zh
        Nick message -- Set your nickname.

        Parameters: <nickname>

        [REQUIRED]
        r   z;Your nickname cannot be decoded. Please use ASCII or UTF-8.Nz	Password?)ro   rp   rq   rm   ÚUnicodeDecodeErrorr�   ÚNICKSERVÚreprÚ	transportÚloseConnectionÚnicknamer   Ú_motdMessagesrs   rd   Ú_serverInfor…   ÚlogInAs)r   rj   r‡   rŽ   Úcoder}   r…   r   r   r   Úirc_NICK  s*    
ý

zIRCUser.irc_NICKc                 C   s   |d | _ dS )zk
        User message -- Set your realname.

        Parameters: <user> <mode> <unused> <realname>
        r„   N)Zrealnamer†   r   r   r   Úirc_USER/  s    	zIRCUser.irc_USERc                 C   s`   |d }|d }| j dkr&| j ¡  n6| ¡ dkrD|  t| j d¡ n| j }d| _ |  ||¡ dS )ú^
        Send a (private) message.

        Parameters: <msgtarget> <text to be sent>
        r   r„   NZnickservz1Denied.  Please send me (NickServ) your password.)rŽ   rŒ   r�   Úlowerr�   rŠ   r‘   )r   rj   r‡   Útargetr…   rŽ   r   r   r   rb   :  s    
ýzIRCUser.irc_NICKSERV_PRIVMSGc                 C   s6   | j j t ||¡| tj¡}|j| j| j	|fd� d S )N)ZerrbackArgs)
rd   r   Úloginr   ZUsernamePasswordr   ÚIUserÚaddCallbacksÚ_cbLoginÚ_ebLogin)r   rŽ   r…   r:   r   r   r   r‘   Q  s    
  ÿzIRCUser.logInAsz:connected to Twisted IRCzA:Your host is %(serviceName)s, running version %(serviceVersion)sz,:This server was created on %(creationDate)sz&%(serviceName)s %(serviceVersion)s w nz(:- %(serviceName)s Message of the Day - z:End of /MOTD command.c                 C   sZ   |\}}}|t jks"td|›�ƒ‚| `|| _|| _| jD ]\}}|  ||| jj	 ¡ q8d S )NzRealm is buggy, got )
r   r™   r0   rc   rg   r_   Ú_welcomeMessagesrs   rd   r�   )r   r*   Úifacerg   r_   r’   r}   r   r   r   r›   n  s    
zIRCUser._cbLoginc                 C   sh   |  tj¡r|  t|d¡ n>|  tj¡r8|  t|d¡ n"t d¡ t 	|¡ |  t|d¡ | j
 ¡  d S )Nz*Already logged in.  No pod people allowed!zLogin failed.  Goodbye.zUnhandled error during login:z"Server error during login.  Sorry.)Úcheckr   ÚAlreadyLoggedInr�   rŠ   ÚecredZUnauthorizedLoginr   Úmsgr"   rŒ   r�   )r   r"   rŽ   r   r   r   rœ   z  s      ÿ

zIRCUser._ebLoginc                 C   s   | j dk	r|  d| j¡ dS )zK
        Ping message

        Parameters: <server1> [ <server2> ]
        NZPONG)rQ   rs   re   r†   r   r   r   Úirc_PING‰  s    
zIRCUser.irc_PINGc                 C   s   | j  ¡  dS )z>
        Quit

        Parameters: [ <Quit Message> ]
        N)rŒ   r�   r†   r   r   r   Úirc_QUIT’  s    zIRCUser.irc_QUITc                 G   s.   |r|   tjd¡ n|  | jd|j d¡ d S )Nú:Unknown MODE flag.ry   ú+)rs   r   ÚERR_UNKNOWNMODEZchannelModer   )r   rW   ÚmodesÚargsr   r   r   Ú_channelModeš  s    zIRCUser._channelModec                 C   s@   |r|   tjd¡ n(|| jkr.|   tjd¡ n|   tjd¡ d S )Nr¥   r¦   z(:You can't look at someone else's modes.)rs   r   r§   rg   ZRPL_UMODEISZERR_USERSDONTMATCH)r   r+   r¨   r   r   r   Ú	_userMode   s    
 ÿzIRCUser._userModec                    sÔ   z"ˆ d }t |tƒr | ˆj¡}W n* tk
rL   ˆ tjˆ d d¡ Y dS X | d¡rš‡ ‡fdd„}ˆj	 
|dd… ¡}|jˆj|tˆ dd… ƒd� n6‡fd	d
„}ˆj	 |¡}|jˆj|tˆ dd… ƒd� dS )z€
        User mode message

        Parameters: <nickname>
        *( ( "+" / "-" ) *( "i" / "w" / "o" / "O" / "r" ) )

        r   z2:No such nickname (could not decode your unicode!)Nry   c                    s$   |   tj¡ ˆ tjˆ d d¡ d S )Nr   ú:That channel doesn't exist.©Útrapr   ÚNoSuchGrouprs   r   ÚERR_NOSUCHCHANNEL©r"   ©r‡   r   r   r   ÚebGroupÀ  s      ÿz!IRCUser.irc_MODE.<locals>.ebGroupé   )ZcallbackArgsc                    s   ˆ   tjd¡ d S )Nz:No such nickname.©rs   r   ÚERR_NOSUCHNICKr±   rA   r   r   ÚebUserÊ  s    z IRCUser.irc_MODE.<locals>.ebUser)ro   rp   rq   rm   r‰   rs   r   r¶   Ú
startswithrQ   ÚlookupGrouprš   rª   ÚtupleÚ
lookupUserr«   )r   rj   r‡   ÚchannelOrUserr³   r:   r·   r   r²   r   Úirc_MODEª  s$    
ý
 zIRCUser.irc_MODEc                 C   s   dS )zl
        Userhost message

        Parameters: <nickname> *( SPACE <nickname> )

        [Optional]
        Nr   r†   r   r   r   Úirc_USERHOSTÐ  s    zIRCUser.irc_USERHOSTc                    s¸   z"|d ‰t ˆtƒr ˆ ˆj¡‰W n* tk
rL   ˆ tj|d d¡ Y dS X |d ‰ ˆ d¡rvˆj	 
ˆdd… ¡}nˆj	 ˆ¡ dd„ ¡}‡ ‡fd	d
„}‡‡fdd„}| ||¡ dS )r•   r   z6:No such nick/channel (could not decode your unicode!)Nr„   ry   r´   c                 S   s   | j S r   )rR   ©r+   r   r   r   Ú<lambda>ñ  ó    z%IRCUser.irc_PRIVMSG.<locals>.<lambda>c                    s   | d k	rˆj  | dˆ i¡S d S )Nr}   )rg   r\   )Ztarg)ÚmessageTextr   r   r   ÚcbTargetô  s    z%IRCUser.irc_PRIVMSG.<locals>.cbTargetc                    s   ˆ   tjˆd¡ d S )Nz:No such nick/channel.rµ   r±   )r   Ú
targetNamer   r   ÚebTargetø  s    z%IRCUser.irc_PRIVMSG.<locals>.ebTarget)ro   rp   rq   rm   r‰   rs   r   r¶   r¸   rQ   r¹   r»   r8   rš   )r   rj   r‡   r—   rÃ   rÅ   r   )rÂ   r   rÄ   r   rc   Ú  s(    
ý
ÿzIRCUser.irc_PRIVMSGc                    s–   z"|d ‰ t ˆ tƒr ˆ  ˆj¡‰ W n* tk
rL   ˆ tj|d d¡ Y dS X ˆ  d¡rdˆ dd… ‰ ‡fdd„}‡ ‡fdd	„}ˆj	 
ˆ ¡ ||¡ dS )
zm
        Join message

        Parameters: ( <channel> *( "," <channel> ) [ <key> *( "," <key> ) ] )
        r   ú1:No such channel (could not decode your unicode!)Nry   r´   c                    s    ‡ ‡fdd„}ˆj  ˆ ¡ |¡S )Nc                    s>   ˆ  ˆ ˆ¡ ˆ ˆjdˆ j dd„ ˆ  ¡ D ƒ¡ ˆ ˆ ¡ d S )Nry   c                 S   s   g | ]
}|j ‘qS r   ©r   ©Ú.0r+   r   r   r   Ú
<listcomp>  s     zEIRCUser.irc_JOIN.<locals>.cbGroup.<locals>.cbJoin.<locals>.<listcomp>)r4   Únamesr   rJ   Ú
_sendTopic)ZignrV   r   r   rX     s    ýz1IRCUser.irc_JOIN.<locals>.cbGroup.<locals>.cbJoin©rg   rY   r8   )rW   rX   rA   ©rW   r   ÚcbGroup  s    	z!IRCUser.irc_JOIN.<locals>.cbGroupc                    s   ˆ  tjdˆ  d¡ d S )Nry   z:No such channel.)rs   r   r°   r±   ©Ú	groupNamer   r   r   r³     s
      ÿz!IRCUser.irc_JOIN.<locals>.ebGroup)ro   rp   rq   rm   r‰   rs   r   r°   r¸   rQ   ÚgetGrouprš   ©r   rj   r‡   rÏ   r³   r   rÐ   r   Úirc_JOINý  s     
ý
zIRCUser.irc_JOINc                    sÎ   z*|d ‰ t |d tƒr(|d  ˆj¡‰ W n* tk
rT   ˆ tj|d d¡ Y dS X ˆ  d¡rlˆ dd… ‰ t	|ƒdkr–|d ‰t ˆtƒršˆ d¡‰nd‰‡‡fdd„}‡ ‡fd	d
„}ˆj
 ˆ ¡ ||¡ dS )zc
        Part message

        Parameters: <channel> *( "," <channel> ) [ <Part Message> ]
        r   z:Could not decode your unicode!Nry   r´   ra   c                    s$   ‡ ‡‡fdd„}ˆj  ˆ ˆ¡ |¡S )Nc                    s   ˆ  ˆ ˆˆ¡ d S r   )r>   rU   )rW   r?   r   r   r   rZ   @  s    z2IRCUser.irc_PART.<locals>.cbGroup.<locals>.cbLeave)rg   r[   r8   )rW   rZ   )r?   r   rÎ   r   rÏ   ?  s    z!IRCUser.irc_PART.<locals>.cbGroupc                    s,   |   tj¡ ˆ tjdˆ  d|  ¡  ¡ d S )Nry   ú:)r®   r   r¯   rs   r   ÚERR_NOTONCHANNELr'   r±   rÐ   r   r   r³   E  s      
ÿz!IRCUser.irc_PART.<locals>.ebGroup)ro   rp   rq   rm   r‰   rs   r   rÖ   r¸   r@   rQ   r¹   rš   rÓ   r   )rÑ   r?   r   r   Úirc_PART%  s*      ÿ

zIRCUser.irc_PARTc                    s–   z"|d ‰ t ˆ tƒr ˆ  ˆj¡‰ W n* tk
rL   ˆ tj|d d¡ Y dS X ˆ  d¡rdˆ dd… ‰ ‡fdd„}‡ ‡fdd	„}ˆj	 
ˆ ¡ ||¡ dS )
zb
        Names message

        Parameters: [ <channel> *( "," <channel> ) [ <target> ] ]
        r„   rÆ   Nry   r´   c                    s(   ˆ   ˆ jd| j dd„ |  ¡ D ƒ¡ d S )Nry   c                 S   s   g | ]
}|j ‘qS r   rÇ   rÈ   r   r   r   rÊ   g  s     z6IRCUser.irc_NAMES.<locals>.cbGroup.<locals>.<listcomp>)rË   r   rJ   rÎ   rA   r   r   rÏ   e  s
      ÿz"IRCUser.irc_NAMES.<locals>.cbGroupc                    s$   |   tj¡ ˆ ˆjdˆ  g ¡ d S )Nry   )r®   r   r¯   rË   r   r±   ©Úchannelr   r   r   r³   j  s    z"IRCUser.irc_NAMES.<locals>.ebGroup)ro   rp   rq   rm   r‰   rs   r   r°   r¸   rQ   r¹   rš   rÓ   r   rØ   r   Ú	irc_NAMESM  s     	
ý
zIRCUser.irc_NAMESc                 C   sŽ   z&|d }t |d tƒr$| | j¡}W n$ tk
rJ   |  tjd¡ Y dS X | d¡rb|dd… }t	|ƒdkr€|  
||d ¡ n
|  |¡ dS )zJ
        Topic message

        Parameters: <channel> [ <topic> ]
        r   z<:That channel doesn't exist (could not decode your unicode!)Nry   r´   )ro   rp   rq   rm   r‰   rs   r   r°   r¸   r@   Ú	_setTopicÚ	_getTopic)r   rj   r‡   rÙ   r   r   r   Ú	irc_TOPICq  s    þ
zIRCUser.irc_TOPICc                 C   s`   |j  d¡}|r\|j  d¡pd}|j  dd¡}|  | jd|j |¡ |  | jd|j ||¡ dS )zP
        Send the topic of the given group to this user, if it has one.
        r   r   z<noone>Ú
topic_dater   ry   N)r   r   r   r   ZtopicAuthor)r   rW   r   rƒ   Údater   r   r   rÌ   Š  s    zIRCUser._sendTopicc                    s(   ‡ ‡fdd„}ˆj  ˆ ¡ ˆj|¡ d S )Nc                    s"   |   tj¡ ˆ tjdˆ d¡ d S ©Nú=r¬   r­   r±   rØ   r   r   r³   ™  s       ÿz"IRCUser._getTopic.<locals>.ebGroup)rQ   r¹   rš   rÌ   )r   rÙ   r³   r   rØ   r   rÜ   •  s    zIRCUser._getTopicc                    s4   ‡‡fdd„}‡ ‡fdd„}ˆj  ˆ ¡ ||¡ d S )Nc                    sH   ˆ j  ¡ }ˆ|d< ˆj|d< ttƒ ƒ|d< ‡ ‡fdd„}ˆ  |¡ |¡S )Nr   r   rÞ   c                    s   ˆ  tjdˆ j d¡ d S )Nry   z.:You need to be a channel operator to do that.)rs   r   ZERR_CHANOPRIVSNEEDEDr   r±   rV   r   r   ÚebSet«  s
    ýz1IRCUser._setTopic.<locals>.cbGroup.<locals>.ebSet)r   Úcopyr   Úintr   rH   r5   )rW   ZnewMetarâ   )r   r   rÎ   r   rÏ   ¥  s    

z"IRCUser._setTopic.<locals>.cbGroupc                    s"   |   tj¡ ˆ tjdˆ d¡ d S rà   r­   r±   rØ   r   r   r³   ´  s       ÿz"IRCUser._setTopic.<locals>.ebGroup)rQ   r¹   rš   )r   rÙ   r   rÏ   r³   r   )rÙ   r   r   r   rÛ   ¡  s    zIRCUser._setTopicc                 C   s<   |D ]$\}}}|   tj|t|ƒd| ¡ q|   tjd¡ dS )zõ
        Send a group of LIST response lines

        @type channels: C{list} of C{(str, int, str)}
        @param channels: Information about the channels being sent:
            their name, the number of participants, and their topic.
        rÕ   z:End of /LISTN)rs   r   ZRPL_LISTÚstrZRPL_LISTEND)r   Úchannelsr   rB   r   r   r   r   rn   ¼  s    zIRCUser.listc                    sÔ   |r°z,|d }t |tƒr$| ˆ j¡}| d¡}W n* tk
rZ   ˆ  tj|d d¡ Y dS X g }|D ],}| 	d¡r~|dd… }| 
ˆ j |¡¡ qdtj|dd�}| d	d
„ ¡ n
ˆ j ¡ }‡ fdd„}| |¡ dS )zÎ
        List query

        Return information about the indicated channels, or about all
        channels if none are specified.

        Parameters: [ <channel> *( "," <channel> ) [ <target> ] ]
        r   ú,rÆ   Nry   r´   T)ZconsumeErrorsc                 S   s   dd„ | D ƒS )Nc                 S   s   g | ]\}}|r|‘qS r   r   ©rÉ   ÚsÚrr   r   r   rÊ   ë  s      z6IRCUser.irc_LIST.<locals>.<lambda>.<locals>.<listcomp>r   )Zgsr   r   r   rÀ   ë  rÁ   z"IRCUser.irc_LIST.<locals>.<lambda>c                    s6   dd„ ‰ t  ‡ fdd„| D ƒ¡}| ‡fdd„¡ |S )Nc                 S   s   |j | |j d¡fS )Nr   )r   r   r   )rB   rW   r   r   r   ÚgotSizeñ  s    z3IRCUser.irc_LIST.<locals>.cbGroups.<locals>.gotSizec                    s   g | ]}|  ¡  ˆ |¡‘qS r   )rB   r8   ©rÉ   rW   ©rë   r   r   rÊ   õ  s     z6IRCUser.irc_LIST.<locals>.cbGroups.<locals>.<listcomp>c                    s   ˆ   dd„ | D ƒ¡S )Nc                 S   s   g | ]\}}|r|‘qS r   r   rè   r   r   r   rÊ   ÷  s      zHIRCUser.irc_LIST.<locals>.cbGroups.<locals>.<lambda>.<locals>.<listcomp>)rn   )r(   rA   r   r   rÀ   ÷  rÁ   z4IRCUser.irc_LIST.<locals>.cbGroups.<locals>.<lambda>)r	   r7   r8   )rO   r:   rA   rí   r   ÚcbGroupsð  s    ÿz"IRCUser.irc_LIST.<locals>.cbGroups)ro   rp   rq   rm   Úsplitr‰   rs   r   r°   r¸   r6   rQ   r¹   r	   r7   r8   r]   )r   rj   r‡   ZallChannelsræ   rO   Úchrî   r   rA   r   Úirc_LISTÈ  s.    
ý


zIRCUser.irc_LISTc                    s,   ˆ   ˆ jd|j ‡ fdd„| ¡ D ƒ¡ d S )Nry   c              	      s*   g | ]"}|j ˆ jˆ jj |j d d|j f‘qS )ÚHr   )r   re   rQ   )rÉ   ÚmrA   r   r   rÊ      s   ÿz'IRCUser._channelWho.<locals>.<listcomp>)Zwhor   rJ   ©r   rW   r   rA   r   Ú_channelWhoü  s    
þýzIRCUser._channelWhoc                 C   s   |   tjd¡ d S )Nz:User /WHO not implemented)rs   r   ÚRPL_ENDOFWHO©r   r+   r   r   r   Ú_userWho  s    zIRCUser._userWhoc                    sÌ   |sˆ  tjd¡ dS z"|d ‰ tˆ tƒr6ˆ  ˆj¡‰ W n* tk
rb   ˆ  tj|d d¡ Y dS X ˆ  d¡r ‡ ‡fdd„}ˆj	 
ˆ dd… ¡}| ˆj|¡ n(‡ ‡fd	d
„}ˆj	 ˆ ¡}| ˆj|¡ dS )zC
        Who query

        Parameters: [ <mask> [ "o" ] ]
        z:/WHO not supported.Nr   z2:End of /WHO list (could not decode your unicode!)ry   c                    s    |   tj¡ ˆ tjˆ d¡ d S ©Nz:End of /WHO list.)r®   r   r¯   rs   r   rö   r±   ©r¼   r   r   r   r³   *  s    z IRCUser.irc_WHO.<locals>.ebGroupr´   c                    s    |   tj¡ ˆ tjˆ d¡ d S rù   )r®   r   Ú
NoSuchUserrs   r   rö   r±   rú   r   r   r·   2  s    zIRCUser.irc_WHO.<locals>.ebUser)rs   r   rö   ro   rp   rq   rm   r‰   r¸   rQ   r¹   rš   rõ   r»   rø   )r   rj   r‡   r³   r:   r·   r   rú   r   Úirc_WHO	  s*    
ý
zIRCUser.irc_WHOc                    s€   ‡fdd„}‡ ‡fdd„}z"ˆ d }t |tƒr:| ˆj¡}W n* tk
rf   ˆ tjˆ d d¡ Y dS X ˆj 	|¡ 
||¡ dS )zV
        Whois query

        Parameters: [ <target> ] <mask> *( "," <mask> )
        c                    sN   ˆ   ˆ j| j| jˆ jj| jˆ jjddttƒ | j ƒ| jdd„ |  ¡ D ƒ¡ d S )NzHi mom!Fc                 S   s   g | ]}d |j  ‘qS )ry   rÇ   rì   r   r   r   rÊ   L  s     z5IRCUser.irc_WHOIS.<locals>.cbUser.<locals>.<listcomp>)Zwhoisr   rQ   rä   r   rP   rS   r]   r¿   rA   r   r   ÚcbUser@  s    õz!IRCUser.irc_WHOIS.<locals>.cbUserc                    s$   |   tj¡ ˆ tjˆ d d¡ d S )Nr   ú:No such nick/channel)r®   r   rû   rs   r   r¶   r±   r²   r   r   r·   O  s    z!IRCUser.irc_WHOIS.<locals>.ebUserr   rþ   N)ro   rp   rq   rm   r‰   rs   r   r¶   rQ   r»   rš   )r   rj   r‡   rý   r·   r+   r   r²   r   Ú	irc_WHOIS9  s    
zIRCUser.irc_WHOISc                 C   s   |   tjd¡ dS )zE
        Oper message

        Parameters: <name> <password>
        z:O-lines not applicableN)rs   r   ZERR_NOOPERHOSTr†   r   r   r   Úirc_OPER^  s    zIRCUser.irc_OPER)N)N)N)7rK   rL   rM   Ú__doc__rO   r_   rg   rQ   rm   rf   ri   rs   r4   r>   rC   rG   rŽ   r…   rˆ   r“   r”   rb   r‘   r   ZRPL_WELCOMEZRPL_YOURHOSTZRPL_CREATEDZ
RPL_MYINFOr�   ZRPL_MOTDSTARTZRPL_ENDOFMOTDr�   r›   rœ   r£   r¤   rª   r«   r½   r¾   rc   rÔ   r×   rÚ   rÝ   rÌ   rÜ   rÛ   rn   rñ   rõ   rø   rü   rÿ   r   r   r   r   r   r`   ¦   sn   
"þüöþ	


&
#(($4
0%r`   c                   @   s   e Zd ZdZeZdd„ ZdS )Ú
IRCFactorya  
    IRC server that creates instances of the L{IRCUser} protocol.

    @ivar _serverInfo: A dictionary mapping:
        "serviceName" to the name of the server,
        "serviceVersion" to the copyright version,
        "creationDate" to the time that the server was started.
    c                 C   s&   || _ || _| j jtjtƒ dœ| _d S )N)ZserviceNameZserviceVersionZcreationDate)rQ   r   r   r   Úversionr   r�   )r   rQ   r   r   r   r   r   s  s    ýzIRCFactory.__init__N)rK   rL   rM   r  r`   r
   r   r   r   r   r   r  g  s   	r  c                   @   s<   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	d
„ Zdd„ ZdS )ÚPBMindc                 C   s   d S r   r   rA   r   r   r   r   ~  s    zPBMind.__init__c                 C   s.   t  t¡}t|tƒr| d¡}||j | ¡fS ©Nra   )r   Úqualr  ro   rå   rl   ÚinvokerÚregisterReference©r   Újellierr  r   r   r   ÚjellyFor�  s    


zPBMind.jellyForc                 C   s   d S r   r   )r   r+   rW   r   r   r   Úremote_userJoined‡  s    zPBMind.remote_userJoinedc                 C   s   d S r   r   )r   r+   rW   r?   r   r   r   Úremote_userLeftŠ  s    zPBMind.remote_userLeftc                 C   s   d S r   r   ©r   rD   rE   rF   r   r   r   Úremote_receive�  s    zPBMind.remote_receivec                 C   s   d S r   r   ©r   rW   r   r   r   r   Úremote_groupMetaUpdate�  s    zPBMind.remote_groupMetaUpdateN)	rK   rL   rM   r   r  r  r  r  r  r   r   r   r   r  }  s   r  c                   @   s2   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	d
„ZdS )ÚPBMindReferencer   c                 C   sJ   t j |¡rt| j| j|ƒ}nt| j| j|ƒ}|  dt| j| j|ƒ||¡S )NrC   )r   r~   r/   ÚPBGrouprQ   rg   ÚPBUserÚ
callRemote)r   rD   rE   rF   Zrecr   r   r   rC   ˜  s       ÿzPBMindReference.receivec                 C   s   |   dt| j| j|ƒ|¡S )NrG   )r  r  rQ   rg   r  r   r   r   rG   ¡  s
      ÿzPBMindReference.groupMetaUpdatec                 C   s&   |   dt| j| j|ƒt| j| j|ƒ¡S )Nr4   ©r  r  rQ   rg   r  rz   r   r   r   r4   ¦  s
    ýzPBMindReference.userJoinedNc                 C   s(   |   dt| j| j|ƒt| j| j|ƒ|¡S )Nr>   r  r|   r   r   r   r>   ­  s    üzPBMindReference.userLeft)N)rK   rL   rM   r   rC   rG   r4   r>   r   r   r   r   r  ”  s
   	r  c                   @   s6   e Zd Zdd„ Zdd„ Zdd„ Zddd	„Zd
d„ ZdS )r  c                 C   s   || _ || _|| _d S r   )rQ   rg   rW   )r   rQ   rg   rW   r   r   r   r   º  s    zPBGroup.__init__c                 C   s   t | jj| jj| jjfƒS r   )ÚhashrQ   r   rg   rW   rA   r   r   r   ÚprocessUniqueID¿  s    zPBGroup.processUniqueIDc                 C   sN   t  | j¡}t|tƒr | d¡}| jj}t|tƒr<| d¡}|||j 	| ¡fS r  )
r   r  Ú	__class__ro   rå   rl   rW   r   r  r  )r   r
  r  rW   r   r   r   r  Â  s    



zPBGroup.jellyForNc                 C   s   | j  | j|¡S r   )rg   r[   rW   rh   r   r   r   Úremote_leaveË  s    zPBGroup.remote_leavec                 C   s   | j  | j|¡S r   )rg   r\   rW   ©r   rF   r   r   r   Úremote_sendÎ  s    zPBGroup.remote_send)N)rK   rL   rM   r   r  r  r  r  r   r   r   r   r  ¹  s
   	
r  c                   @   sX   e Zd Zdd„ Zddd„Zdd„ Zdd	„ Zd
d„ Zdd„ Zddd„Z	dd„ Z
dd„ ZdS )ÚPBGroupReferencec                 C   s*   |\}}}|  d¡| _tj | |||g¡S r  )rq   r   r   ÚRemoteReferenceÚ
unjellyFor)r   Z	unjellierZunjellyListZclsNamer   Úrefr   r   r   r  Ô  s    
zPBGroupReference.unjellyForNc                 C   s   |   d|¡S )Nr[   ©r  rh   r   r   r   r[   Ù  s    zPBGroupReference.leavec                 C   s   |   d|¡S )Nr\   r!  r  r   r   r   r\   Ü  s    zPBGroupReference.sendc                 C   s   d S r   r   r÷   r   r   r   r;   ß  s    zPBGroupReference.addc                 C   s   d S r   r   rA   r   r   r   rJ   ã  s    zPBGroupReference.iterusersc                 C   s   d S r   r   r  r   r   r   rC   ç  s    zPBGroupReference.receivec                 C   s   d S r   r   )r   r+   r?   r   r   r   r&   ë  s    zPBGroupReference.removec                 C   s   d S r   r   )r   r   r   r   r   rH   ï  s    zPBGroupReference.setMetadatac                 C   s   d S r   r   rA   r   r   r   rB   ó  s    zPBGroupReference.size)N)N)rK   rL   rM   r  r[   r\   r;   rJ   rC   r&   rH   rB   r   r   r   r   r  Ò  s   

r  c                   @   s   e Zd Zdd„ Zdd„ ZdS )r  c                 C   s   || _ || _|| _d S r   )rQ   rg   r+   )r   rQ   rg   r+   r   r   r   r   ü  s    zPBUser.__init__c                 C   s   t | jj| jj| jjfƒS r   )r  rQ   r   rg   r+   rA   r   r   r   r    s    zPBUser.processUniqueIDN)rK   rL   rM   r   r  r   r   r   r   r  û  s   r  c                   @   s`   e Zd Zdd„ Zdd„ Zdd„ Zedd„ ƒZejd	d„ ƒZd
d„ Z	dd„ Z
dd„ Zddd„ZdS )Ú
ChatAvatarc                 C   s
   || _ d S r   )rg   )r   rg   r   r   r   r     s    zChatAvatar.__init__c                 C   s0   t  | j¡}t|tƒr | d¡}||j | ¡fS r  )r   r  r  ro   rå   rl   r  r  r	  r   r   r   r  
  s    

zChatAvatar.jellyForc                    s(   ‡ fdd„}ˆ j j |¡}| |¡ |S )Nc                    s(   ‡ ‡fdd„}ˆj  ˆ ¡}| |¡ |S )Nc                    s   t ˆjjˆjˆ ƒS r   )r  rg   rQ   )ZignoredrV   r   r   rX     s    z7ChatAvatar.remote_join.<locals>.cbGroup.<locals>.cbJoinrÍ   )rW   rX   r:   rA   rÎ   r   rÏ     s    
z'ChatAvatar.remote_join.<locals>.cbGroup)rg   rQ   rÒ   r8   )r   rÑ   rÏ   r:   r   rA   r   Úremote_join  s    
zChatAvatar.remote_joinc                 C   s   d S r   r   rA   r   r   r   r     s    zChatAvatar.namec                 C   s   d S r   r   )r   r%   r   r   r   r   "  s    c                 C   s   d S r   r   r  r   r   r   rG   '  s    zChatAvatar.groupMetaUpdatec                 C   s   d S r   r   r  r   r   r   rC   +  s    zChatAvatar.receivec                 C   s   d S r   r   rz   r   r   r   r4   /  s    zChatAvatar.userJoinedNc                 C   s   d S r   r   r|   r   r   r   r>   3  s    zChatAvatar.userLeft)N)rK   rL   rM   r   r  r#  Úpropertyr   ÚsetterrG   rC   r4   r>   r   r   r   r   r"    s   

r"  c                   @   s   e Zd Zdd„ Zdd„ ZdS )ÚAvatarReferencec                 C   s   |   d|¡S )NrY   r!  )r   rÑ   r   r   r   rY   <  s    zAvatarReference.joinc                    s,   t  ¡ ‰ | j ‡ fdd„¡ | jj ¡  ˆ S )Nc                      s
   ˆ   d ¡S r   )Úcallbackr   ©r:   r   r   rÀ   A  rÁ   z&AvatarReference.quit.<locals>.<lambda>)r	   ZDeferredZbrokerZnotifyOnDisconnectrŒ   r�   rA   r   r(  r   Úquit?  s    zAvatarReference.quitN)rK   rL   rM   rY   r)  r   r   r   r   r&  ;  s   r&  c                   @   sˆ   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dZ
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 S )!Ú
WordsRealmra   c                 C   s
   || _ d S r   rÇ   r   r   r   r   r   M  s    zWordsRealm.__init__c                 C   s   t |ƒS r   )rN   r   r   r   r   ÚuserFactoryP  s    zWordsRealm.userFactoryc                 C   s   t |ƒS r   )r   r   r   r   r   ÚgroupFactoryS  s    zWordsRealm.groupFactoryc                    s   ‡ ‡fdd„}|S )Nc                      s"   t ˆddd„ ƒƒ  d  ˆ _ˆ _d S )Nr_   c                   S   s   d S r   r   r   r   r   r   rÀ   Y  rÁ   z:WordsRealm.logoutFactory.<locals>.logout.<locals>.<lambda>)ÚgetattrrQ   rR   r   ©rg   Úfacetr   r   r_   W  s    z(WordsRealm.logoutFactory.<locals>.logoutr   )r   rg   r/  r_   r   r.  r   ÚlogoutFactoryV  s    zWordsRealm.logoutFactoryc                    s8   t ˆ tƒrˆ  ˆj¡‰ ‡ ‡‡‡fdd„}ˆ ˆ ¡ |¡S )Nc                    sp   | j d k	rt ¡ ‚ˆD ]J}|| d ƒ}|d k	r|  ˆˆ¡ ˆ ˆ_ˆˆ_ | ˆ_||ˆ | |¡f  S qtˆˆƒ‚d S r   )rQ   r   r    rT   r   rg   r0  ÚNotImplementedError)rg   rž   r/  ©ÚavatarIdÚ
interfacesrR   r   r   r   Ú	gotAvatarb  s    

z+WordsRealm.requestAvatar.<locals>.gotAvatar)ro   rp   rq   Ú	_encodingÚgetUserr8   )r   r3  rR   r4  r5  r   r2  r   ÚrequestAvatar^  s    
zWordsRealm.requestAvatarc                 C   s   d S r   r   rA   r   r   r   r]   q  s    zWordsRealm.itergroupsFTc                 C   s   t ‚d S r   ©r1  r   r   r   r   r»   y  s    zWordsRealm.lookupUserc                 C   s   t ‚d S r   r9  rô   r   r   r   r¹   |  s    zWordsRealm.lookupGroupc                 C   s   t ‚dS )aÓ  
        Add the given user to this service.

        This is an internal method intended to be overridden by
        L{WordsRealm} subclasses, not called by external code.

        @type user: L{IUser}

        @rtype: L{twisted.internet.defer.Deferred}
        @return: A Deferred which fires with L{None} when the user is
        added, or which fails with
        L{twisted.words.ewords.DuplicateUser} if a user with the
        same name exists already.
        Nr9  r÷   r   r   r   ÚaddUser  s    zWordsRealm.addUserc                 C   s   t ‚dS )aY  
        Add the given group to this service.

        @type group: L{IGroup}

        @rtype: L{twisted.internet.defer.Deferred}
        @return: A Deferred which fires with L{None} when the group is
        added, or which fails with
        L{twisted.words.ewords.DuplicateGroup} if a group with the
        same name exists already.
        Nr9  rô   r   r   r   ÚaddGroup�  s    zWordsRealm.addGroupc                    s.   ˆj r$‡ ‡fdd„}ˆ ˆ ¡ |¡S ˆ ˆ ¡S )Nc                    s   |   tj¡ ˆ ˆ ¡S r   )r®   r   ÚDuplicateGroupr¹   r±   ©r   r   r   r   r³   ¡  s    z$WordsRealm.getGroup.<locals>.ebGroup)ÚcreateGroupOnRequestÚcreateGroupr5   r¹   )r   r   r³   r   r=  r   rÒ   ž  s    zWordsRealm.getGroupc                    s.   ˆj r$‡ ‡fdd„}ˆ ˆ ¡ |¡S ˆ ˆ ¡S )Nc                    s   |   tj¡ ˆ ˆ ¡S r   )r®   r   ÚDuplicateUserr»   r±   r=  r   r   r·   «  s    z"WordsRealm.getUser.<locals>.ebUser)ÚcreateUserOnRequestÚ
createUserr5   r»   )r   r   r·   r   r=  r   r7  ¨  s    zWordsRealm.getUserc                    sH   ‡ fdd„}‡ ‡fdd„}ˆ   ¡ ‰ ˆ ˆ ¡}| ||¡ | ˆj¡ |S )Nc                    s   t  t ˆ ¡¡S r   )r   r    r   r@  r¿   rÇ   r   r   ÚcbLookup³  s    z'WordsRealm.createUser.<locals>.cbLookupc                    s   |   tj¡ ˆ ˆ ¡S r   )r®   r   rû   r+  r±   r=  r   r   ÚebLookup¶  s    z'WordsRealm.createUser.<locals>.ebLookup)r–   r»   rš   r8   r:  ©r   r   rC  rD  r:   r   r=  r   rB  ²  s    
zWordsRealm.createUserc                    sH   ‡ fdd„}‡ ‡fdd„}ˆ   ¡ ‰ ˆ ˆ ¡}| ||¡ | ˆj¡ |S )Nc                    s   t  t ˆ ¡¡S r   )r   r    r   r<  rÎ   rÇ   r   r   rC  Á  s    z(WordsRealm.createGroup.<locals>.cbLookupc                    s   |   tj¡ ˆ ˆ ¡S r   )r®   r   r¯   r,  r±   r=  r   r   rD  Ä  s    z(WordsRealm.createGroup.<locals>.ebLookup)r–   r¹   rš   r8   r;  rE  r   r=  r   r?  À  s    
zWordsRealm.createGroupN)rK   rL   rM   r6  r   r+  r,  r0  r8  r]   r>  rA  r»   r¹   r:  r;  rÒ   r7  rB  r?  r   r   r   r   r*  I  s"   

r*  c                       sD   e Zd Z‡ fdd„Zdd„ Zdd„ Zdd„ Zd	d
„ Zdd„ Z‡  Z	S )ÚInMemoryWordsRealmc                    s   t ƒ j||Ž i | _i | _d S r   )Úsuperr   r   rO   )r   Úaru   ©r  r   r   r   Ð  s    zInMemoryWordsRealm.__init__c                 C   s   t  | j ¡ ¡S r   )r	   r9   rO   r2   rA   r   r   r   r]   Õ  s    zInMemoryWordsRealm.itergroupsc                 C   s6   |j | jkr t t t ¡ ¡¡S || j|j < t |¡S r   )	r   r   r	   Úfailr   r    r   r@  r9   r÷   r   r   r   r:  Ø  s    zInMemoryWordsRealm.addUserc                 C   s6   |j | jkr t t t ¡ ¡¡S || j|j < t |¡S r   )	r   rO   r	   rJ  r   r    r   r<  r9   rô   r   r   r   r;  Þ  s    zInMemoryWordsRealm.addGroupc              
   C   sP   |  ¡ }z| j| }W n* tk
r@   t t t |¡¡¡ Y S X t 	|¡S d S r   )
r–   r   r=   r	   rJ  r   r    r   rû   r9   )r   r   r+   r   r   r   r»   ä  s    zInMemoryWordsRealm.lookupUserc              
   C   sP   |  ¡ }z| j| }W n* tk
r@   t t t |¡¡¡ Y S X t 	|¡S d S r   )
r–   rO   r=   r	   rJ  r   r    r   r¯   r9   )r   r   rW   r   r   r   r¹   í  s    zInMemoryWordsRealm.lookupGroup)
rK   rL   rM   r   r]   r:  r;  r»   r¹   Ú__classcell__r   r   rI  r   rF  Ï  s   	rF  N)6r  r   r   Zzope.interfacer   Ztwistedr   Ztwisted.credr   r   r¡   r   Ztwisted.internetr	   r
   Ztwisted.pythonr   r   r   Ztwisted.python.componentsr   Ztwisted.spreadr   Ztwisted.wordsr   r   Ztwisted.words.protocolsr   r~   r   r™   rN   rŠ   r.   rr   r`   ZServerFactoryr  ZReferenceabler  r  r  ZsetUnjellyableForClassr  r  r  r"  ZIPerspectiver&  ZIRealmZIChatServicer*  rF  Ú__all__r   r   r   r   Ú<module>   s\   M(     E!%
2 )ü