o
    b                     @   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Z4g d'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   7/usr/lib/python3/dist-packages/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      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J d||j| jvrEg }|| j|j< | j D ]}||ur;t|j	| |}|j
| j|d || q t|| j td S )Nz{!r} is not a chat clientr#   )r   IChatClient
providedByformatr   r   valuesr	   maybeDeferred
userJoined
addErrbackr$   appendDeferredListaddCallbackr-   succeed)r   r,   	additionsr#   dr   r   r   add?   s   

z	Group.addNc                 C   s   z| j |j= W n	 ty   Y n.w g }| j  D ]}||ur4t|j| ||}|j| j|d |	| qt
|| j td S Nr.   )r   r   KeyErrorr2   r	   r3   userLeftr5   r$   r6   r7   r8   r-   r9   )r   r,   reason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]   r%   z
Group.sizec                 C   sp   || u sJ g }| j  D ]}||ur)t|j|| |}|j| j|d || qt|	| j
 td S r=   )r   r2   r	   r3   receiver5   r$   r6   r7   r8   r-   r9   )r   sender	recipientmessagereceivesr#   r;   r   r   r   rE   `   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   setsr#   r;   r   r   r   setMetadatak   s   
zGroup.setMetadatac                 C   s   t | j S r   )iterr   r2   rC   r   r   r   	iterusersu   s   zGroup.iterusersr   )__name__
__module____qualname__r   r$   r-   r<   r'   rD   rE   rL   rN   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         zUser.__init__c                 C   s   || _ || _t | _d S r   )realmmindr   signOn)r   rV   rW   r   r   r   loggedIn   rU   zUser.loggedInc                    s     fdd}  j|S )Nc                       j   | S r   )rS   r6   r+   groupr   r   r   cbJoin      zUser.join.<locals>.cbJoin)r<   rW   r8   )r   r]   r^   r   r\   r   join   s   z	User.joinc                    s"    fdd}  j||S )Nc                    rZ   r   )rS   r'   r[   r\   r   r   cbLeave   r_   zUser.leave.<locals>.cbLeave)r'   rW   r8   )r   r]   r@   ra   r   r\   r   leave   s   z
User.leavec                 C   s   t  | _|| j||S r   )r   rT   rE   rW   )r   rG   rH   r   r   r   send   s   z	User.sendc                 C   s
   t | jS r   )rM   rS   rC   r   r   r   
itergroups      
zUser.itergroupsc                 C   s"   | j d d  D ]}| | qd S r   )rS   rb   )r   gr   r   r   logout   s   zUser.logoutr   )rO   rP   rQ   rV   rW   r   rY   r`   rb   rc   rd   rg   r   r   r   r   rR   z   s    
rR   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#dPd*d+Z$dPd,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 )Q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factoryrV   r   hostnamerC   r   r   r   connectionMade   s   
zIRCUser.connectionMadec                 C   s    | j d ur|    d | _d S d S r   )rg   avatarr   r@   r   r   r   connectionLost   s   

zIRCUser.connectionLostc                 O   s   d|vr	| j |d< d|vr| j| j|d< | ||d gt| }g }|D ]}t|tr1|d}|| q%t	j
j|i | d S )Nprefixtori   )rm   r   encodeencodinglist
isinstancebytesdecoder6   r   IRCsendMessage)r   commandparameter_listkwarglistarglistUnicodeargr   r   r   r{      s   


zIRCUser.sendMessagec                 C   s,   |  |j d|j d| j d|j  d S )N!@#)r`   r   rm   r   r]   r,   r   r   r   r4      s   ,zIRCUser.userJoinedc                 C   s2   |  |j d|j d| j d|j |pd d S )Nr   r   r   leaving)partr   rm   r   r]   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 || qd S )Nr   textz<an unrepresentable message>r   r   )r   IGroupr0   r   get
splitlinesprivmsgrm   )r   rF   rG   rH   recipientNamer   Lr   r   r   rE      s   zIRCUser.receivec              
   C   sN   d|v r%|d }| dd}| | jd|j || d| d| j  d S d S )Nr   r   r   r   r   r   )r   r   r   rm   )r   r]   r   r   authorr   r   r   rJ      s   zIRCUser.groupMetaUpdatec                 C      |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   rr   paramsr   r   r   irc_PASS   s   zIRCUser.irc_PASSc                 C   s   |d }zt |tr|| j}W n ty)   | tt|d | j	  Y dS w || _
|| _| jD ]\}}| ||| jj  q3| jdu rP| t|d dS | 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?)rw   rx   ry   ru   UnicodeDecodeErrorr   NICKSERVrepr	transportloseConnectionnicknamer   _motdMessagesr{   rl   _serverInfor   logInAs)r   rr   r   r   coder   r   r   r   r   irc_NICK  s.   

	
zIRCUser.irc_NICKc                 C   r   )zk
        User message -- Set your realname.

        Parameters: <user> <mode> <unused> <realname>
        r   N)realnamer   r   r   r   irc_USER/  s   	zIRCUser.irc_USERc                 C   sd   |d }|d }| j du r| j  dS | dkr$| t| j d dS | j }d| _ | || dS )^
        Send a (private) message.

        Parameters: <msgtarget> <text to be sent>
        r   r   Nnickservz1Denied.  Please send me (NickServ) your password.)r   r   r   lowerr   r   r   )r   rr   r   targetr   r   r   r   r   rj   :  s   
zIRCUser.irc_NICKSERV_PRIVMSGc                 C   s6   | j jt||| tj}|j| j| j	|fd d S )N)errbackArgs)
rl   r   loginr   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u sJ d|| `|| _|| _| jD ]\}}| ||| jj  qd S )NzRealm is buggy, got )	r   r   rk   ro   rg   _welcomeMessagesr{   rl   r   )r   r+   ifacero   rg   r   r   r   r   r   r   n  s   
zIRCUser._cbLoginc                 C   sh   | tjr| t|d n| tjr| 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   ecredUnauthorizedLoginr   msgr"   r   r   )r   r"   r   r   r   r   r   z  s   

zIRCUser._ebLoginc                 C   s    | j dur| d| j dS dS )zK
        Ping message

        Parameters: <server1> [ <server2> ]
        NPONG)rV   r{   rm   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   s0   |r|  tjd d S | | jd|j d d S )N:Unknown MODE flag.r   +)r{   r   ERR_UNKNOWNMODEchannelModer   )r   r]   modesargsr   r   r   _channelMode  s   zIRCUser._channelModec                 C   sD   |r|  tjd d S || ju r|  tjd d S |  tjd d S )Nr   r   z(:You can't look at someone else's modes.)r{   r   r   ro   RPL_UMODEISERR_USERSDONTMATCH)r   r,   r   r   r   r   	_userMode  s   
zIRCUser._userModec                    s   z d }t |tr|j}W n ty%   tj d d Y dS w |drM fdd}j	
|dd }|jj|t dd d dS 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!)Nr   c                    $   |  tj tj d d d S )Nr   :That channel doesn't exist.trapr   NoSuchGroupr{   r   ERR_NOSUCHCHANNELr"   r   r   r   r   ebGroup  s   z!IRCUser.irc_MODE.<locals>.ebGroup   )callbackArgsc                    s     tjd d S )Nz:No such nickname.r{   r   ERR_NOSUCHNICKr   rC   r   r   ebUser     z IRCUser.irc_MODE.<locals>.ebUser)rw   rx   ry   ru   r   r{   r   r   
startswithrV   lookupGroupr   r   tuple
lookupUserr   )r   rr   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y%   tj|d d Y dS w |d  dr: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   r   r   c                 S   s   | j S r   )rW   r,   r   r   r   <lambda>  s    z%IRCUser.irc_PRIVMSG.<locals>.<lambda>c                    s   | d urj | d iS d S )Nr   )ro   rc   )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     z%IRCUser.irc_PRIVMSG.<locals>.ebTarget)rw   rx   ry   ru   r   r{   r   r   r   rV   r   r   r8   r   )r   rr   r   r   r   r   r   )r   r   r   r   rk     s,   

zIRCUser.irc_PRIVMSGc                       z|d  t  tr j W n ty%   tj|d d Y dS w  dr1 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!)Nr   r   c                    s     fdd}j  |S )Nc                    s>      jd j dd   D    d S )Nr   c                 S      g | ]}|j qS r   r   .0r,   r   r   r   
<listcomp>      zEIRCUser.irc_JOIN.<locals>.cbGroup.<locals>.cbJoin.<locals>.<listcomp>)r4   namesr   rN   
_sendTopic)ignr\   r   r   r^     s   z1IRCUser.irc_JOIN.<locals>.cbGroup.<locals>.cbJoinro   r`   r8   )r]   r^   rC   r]   r   cbGroup  s   	z!IRCUser.irc_JOIN.<locals>.cbGroupc                    s    tjd  d d S )Nr   z:No such channel.)r{   r   r   r   	groupNamer   r   r   r     s   z!IRCUser.irc_JOIN.<locals>.ebGroup)rw   rx   ry   ru   r   r{   r   r   r   rV   getGroupr   r   rr   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y)   tj|d d Y dS w  dr5 dd  t	|dkrJ|d t trI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!Nr   r   ri   c                    s$    fdd}j  |S )Nc                    s      d S r   )r?   r[   )r]   r@   r   r   r   ra   @  r   z2IRCUser.irc_PART.<locals>.cbGroup.<locals>.cbLeave)ro   rb   r8   )r]   ra   )r@   r   r   r   r   ?  s   z!IRCUser.irc_PART.<locals>.cbGroupc                    s,   |  tj tjd  d|    d S )Nr   :)r   r   r   r{   r   ERR_NOTONCHANNELr(   r   r   r   r   r   E  s   z!IRCUser.irc_PART.<locals>.ebGroup)rw   rx   ry   ru   r   r{   r   r   r   rB   rV   r   r   r   r   )r   r@   r   r   irc_PART%  s,   


zIRCUser.irc_PARTc                    r   )
zb
        Names message

        Parameters: [ <channel> *( "," <channel> ) [ <target> ] ]
        r   r   Nr   r   c                    s(      jd| j dd |  D  d S )Nr   c                 S   r   r   r   r   r   r   r   r   g  r   z6IRCUser.irc_NAMES.<locals>.cbGroup.<locals>.<listcomp>)r   r   rN   r   rC   r   r   r   e  s   z"IRCUser.irc_NAMES.<locals>.cbGroupc                    s$   |  tj jd  g  d S )Nr   )r   r   r   r   r   r   channelr   r   r   r   j  s   z"IRCUser.irc_NAMES.<locals>.ebGroup)rw   rx   ry   ru   r   r{   r   r   r   rV   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y$   | tjd Y dS w |dr0|dd }t	|dkr@| 
||d  dS | | dS )zJ
        Topic message

        Parameters: <channel> [ <topic> ]
        r   z<:That channel doesn't exist (could not decode your unicode!)Nr   r   )rw   rx   ry   ru   r   r{   r   r   r   rB   	_setTopic	_getTopic)r   rr   r   r   r   r   r   	irc_TOPICq  s"   
zIRCUser.irc_TOPICc                 C   sd   |j d}|r0|j dpd}|j dd}| | jd|j | | | jd|j || dS dS )zP
        Send the topic of the given group to this user, if it has one.
        r   r   z<noone>
topic_dater   r   N)r   r   r   r   topicAuthor)r   r]   r   r   dater   r   r   r     s   zIRCUser._sendTopicc                    s(    fdd}j  j| d S )Nc                    "   |  tj tjd d d S N=r   r   r   r   r   r   r        
z"IRCUser._getTopic.<locals>.ebGroup)rV   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 )Nr   z.:You need to be a channel operator to do that.)r{   r   ERR_CHANOPRIVSNEEDEDr   r   r\   r   r   ebSet  s
   z1IRCUser._setTopic.<locals>.cbGroup.<locals>.ebSet)r   copyr   intr   rL   r5   )r]   newMetar  )r   r   r   r   r     s   

z"IRCUser._setTopic.<locals>.cbGroupc                    r   r  r   r   r   r   r   r     r  z"IRCUser._setTopic.<locals>.ebGroup)rV   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)r{   r   RPL_LISTstrRPL_LISTEND)r   channelsr   rD   r   r   r   r   rv     s   zIRCUser.listc                    s   |rWz|d }t |tr| j}|d}W n ty,    tj|d d Y dS w g }|D ]}|	dr>|dd }|
 j| q1t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   Nr   r   T)consumeErrorsc                 S   s   dd | D S )Nc                 S      g | ]\}}|r|qS r   r   r   srr   r   r   r         z6IRCUser.irc_LIST.<locals>.<lambda>.<locals>.<listcomp>r   )gsr   r   r   r     s    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   )rD   r]   r   r   r   gotSize  r   z3IRCUser.irc_LIST.<locals>.cbGroups.<locals>.gotSizec                    s   g | ]
}|   |qS r   )rD   r8   r   r]   r  r   r   r     s    z6IRCUser.irc_LIST.<locals>.cbGroups.<locals>.<listcomp>c                    s     dd | D S )Nc                 S   r  r   r   r  r   r   r   r     r  zHIRCUser.irc_LIST.<locals>.cbGroups.<locals>.<lambda>.<locals>.<listcomp>)rv   )r)   rC   r   r   r     s    z4IRCUser.irc_LIST.<locals>.cbGroups.<locals>.<lambda>)r	   r7   r8   )rS   r;   rC   r  r   cbGroups  s   z"IRCUser.irc_LIST.<locals>.cbGroups)rw   rx   ry   ru   splitr   r{   r   r   r   r6   rV   r   r	   r7   r8   rd   )r   rr   r   allChannelsr  rS   chr  r   rC   r   irc_LIST  s0   



zIRCUser.irc_LISTc                    s,      jd|j  fdd| D  d S )Nr   c              	      s*   g | ]}|j  j jj |j d d|j fqS )Hr   )r   rm   rV   )r   mrC   r   r   r      s    z'IRCUser._channelWho.<locals>.<listcomp>)whor   rN   r   r]   r   rC   r   _channelWho  s   
zIRCUser._channelWhoc                 C   s   |  tjd d S )Nz:User /WHO not implemented)r{   r   RPL_ENDOFWHOr   r,   r   r   r   _userWho  r   zIRCUser._userWhoc                    s   |s tjd dS z|d  t tr j W n ty0    tj|d d Y dS w  drP fdd}j	
 dd }|j| dS  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!)r   c                        |  tj tj d d S Nz:End of /WHO list.)r   r   r   r{   r   r"  r   r   r   r   r   r   *     z IRCUser.irc_WHO.<locals>.ebGroupr   c                    r%  r&  )r   r   
NoSuchUserr{   r   r"  r   r'  r   r   r   2  r(  zIRCUser.irc_WHO.<locals>.ebUser)r{   r   r"  rw   rx   ry   ru   r   r   rV   r   r   r!  r   r$  )r   rr   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y2   tj d d Y dS w 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 )r   r   r  r   r   r   r   L  s    z5IRCUser.irc_WHOIS.<locals>.cbUser.<locals>.<listcomp>)whoisr   rV   r  r   rT   rX   rd   r   rC   r   r   cbUser@  s   z!IRCUser.irc_WHOIS.<locals>.cbUserc                    r   )Nr   :No such nick/channel)r   r   r)  r{   r   r   r   r   r   r   r   O  s   z!IRCUser.irc_WHOIS.<locals>.ebUserr   r-  N)rw   rx   ry   ru   r   r{   r   r   rV   r   r   )r   rr   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)r{   r   ERR_NOOPERHOSTr   r   r   r   irc_OPER^  s   zIRCUser.irc_OPERr   )7rO   rP   rQ   __doc__rS   rg   ro   rV   ru   rn   rq   r{   r4   r?   rE   rJ   r   r   r   r   r   rj   r   r   RPL_WELCOMERPL_YOURHOSTRPL_CREATED
RPL_MYINFOr   RPL_MOTDSTARTRPL_ENDOFMOTDr   r   r   r   r   r   r   r   r   rk   r   r   r   r   r   r   r   rv   r  r!  r$  r*  r.  r0  r   r   r   r   rh      sp    
"	


&
#(($4
0%rh   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)serviceNameserviceVersioncreationDate)rV   r   r   r   versionr   r   )r   rV   r   r   r   r   r   s  s   zIRCFactory.__init__N)rO   rP   rQ   r1  rh   r
   r   r   r   r   r   r8  g  s    	r8  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      d S r   r   rC   r   r   r   r   ~     zPBMind.__init__c                 C   s.   t t}t|tr|d}||j| fS Nri   )r   qualr=  rw   r
  rt   invokerregisterReferencer   jellierrA  r   r   r   jellyFor  s   


zPBMind.jellyForc                 C   r>  r   r   )r   r,   r]   r   r   r   remote_userJoined  r?  zPBMind.remote_userJoinedc                 C   r>  r   r   )r   r,   r]   r@   r   r   r   remote_userLeft  r?  zPBMind.remote_userLeftc                 C   r>  r   r   r   rF   rG   rH   r   r   r   remote_receive  r?  zPBMind.remote_receivec                 C   r>  r   r   r   r]   r   r   r   r   remote_groupMetaUpdate  r?  zPBMind.remote_groupMetaUpdateN)	rO   rP   rQ   r   rF  rG  rH  rJ  rL  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 )NrE   )r   r   r0   PBGrouprV   ro   PBUser
callRemote)r   rF   rG   rH   recr   r   r   rE     s   zPBMindReference.receivec                 C   s   |  dt| j| j||S )NrJ   )rP  rN  rV   ro   rK  r   r   r   rJ     s   zPBMindReference.groupMetaUpdatec                 C   s&   |  dt| j| j|t| j| j|S )Nr4   rP  rN  rV   ro   rO  r   r   r   r   r4     s
   zPBMindReference.userJoinedNc                 C   s(   |  dt| j| j|t| j| j||S )Nr?   rR  r   r   r   r   r?     s   zPBMindReference.userLeftr   )rO   rP   rQ   r   rE   rJ   r4   r?   r   r   r   r   rM    s    	rM  c                   @   s6   e Zd Zdd Zdd Zdd Zddd	Zd
d ZdS )rN  c                 C      || _ || _|| _d S r   )rV   ro   r]   )r   rV   ro   r]   r   r   r   r        
zPBGroup.__init__c                 C      t | jj| jj| jjfS r   )hashrV   r   ro   r]   rC   r   r   r   processUniqueID     zPBGroup.processUniqueIDc                 C   sN   t | j}t|tr|d}| jj}t|tr|d}|||j	| fS r@  )
r   rA  	__class__rw   r
  rt   r]   r   rB  rC  )r   rE  rA  r]   r   r   r   rF    s   



zPBGroup.jellyForNc                 C      | j | j|S r   )ro   rb   r]   rp   r   r   r   remote_leave  r%   zPBGroup.remote_leavec                 C   rZ  r   )ro   rc   r]   r   rH   r   r   r   remote_send  r%   zPBGroup.remote_sendr   )rO   rP   rQ   r   rW  rF  r[  r]  r   r   r   r   rN    s    
	rN  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   sF   |\}}}|| _ ttkrt| j tr| j d| _ tj| |||gS r@  )r   rx   r
  rw   ry   r   RemoteReference
unjellyFor)r   	unjellierunjellyListclsNamer   refr   r   r   r`    s
   
zPBGroupReference.unjellyForNc                 C      |  d|S )Nrb   rP  rp   r   r   r   rb        zPBGroupReference.leavec                 C   re  )Nrc   rf  r\  r   r   r   rc     rg  zPBGroupReference.sendc                 C   r>  r   r   r#  r   r   r   r<        zPBGroupReference.addc                 C   r>  r   r   rC   r   r   r   rN     rh  zPBGroupReference.iterusersc                 C   r>  r   r   rI  r   r   r   rE     rh  zPBGroupReference.receivec                 C   r>  r   r   )r   r,   r@   r   r   r   r'     rh  zPBGroupReference.removec                 C   r>  r   r   )r   r   r   r   r   rL     rh  zPBGroupReference.setMetadatac                 C   r>  r   r   rC   r   r   r   rD     rh  zPBGroupReference.sizer   )rO   rP   rQ   r`  rb   rc   r<   rN   rE   r'   rL   rD   r   r   r   r   r^    s    

r^  c                   @      e Zd Zdd Zdd ZdS )rO  c                 C   rS  r   )rV   ro   r,   )r   rV   ro   r,   r   r   r   r     rT  zPBUser.__init__c                 C   rU  r   )rV  rV   r   ro   r,   rC   r   r   r   rW    rX  zPBUser.processUniqueIDN)rO   rP   rQ   r   rW  r   r   r   r   rO    s    rO  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   
   || _ d S r   )ro   )r   ro   r   r   r   r   
  re   zChatAvatar.__init__c                 C   s0   t | j}t|tr|d}||j| fS r@  )r   rA  rY  rw   r
  rt   rB  rC  rD  r   r   r   rF    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   )rN  ro   rV   )ignoredr\   r   r   r^     r   z7ChatAvatar.remote_join.<locals>.cbGroup.<locals>.cbJoinr   )r]   r^   r;   rC   r   r   r     s   
z'ChatAvatar.remote_join.<locals>.cbGroup)ro   rV   r   r8   )r   r   r   r;   r   rC   r   remote_join  s   
zChatAvatar.remote_joinc                 C   r>  r   r   rC   r   r   r   r         zChatAvatar.namec                 C   r>  r   r   )r   r&   r   r   r   r   %  rn  c                 C   r>  r   r   rK  r   r   r   rJ   *  rh  zChatAvatar.groupMetaUpdatec                 C   r>  r   r   rI  r   r   r   rE   .  rh  zChatAvatar.receivec                 C   r>  r   r   r   r   r   r   r4   2  rh  zChatAvatar.userJoinedNc                 C   r>  r   r   r   r   r   r   r?   6  rh  zChatAvatar.userLeftr   )rO   rP   rQ   r   rF  rm  propertyr   setterrJ   rE   r4   r?   r   r   r   r   rj    s    

rj  c                   @   ri  )AvatarReferencec                 C   re  )Nr`   rf  )r   r   r   r   r   r`   ?  rg  zAvatarReference.joinc                    s,   t   | j fdd | jj   S )Nc                      s
     d S r   )callbackr   r;   r   r   r   D  s   
 z&AvatarReference.quit.<locals>.<lambda>)r	   DeferredbrokernotifyOnDisconnectr   r   rC   r   rs  r   quitB  s   zAvatarReference.quitN)rO   rP   rQ   r`   rw  r   r   r   r   rq  >  s    rq  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 )!
WordsRealmri   c                 C   rk  r   r   r   r   r   r   r   P  re   zWordsRealm.__init__c                 C      t |S r   )rR   r   r   r   r   userFactoryS     zWordsRealm.userFactoryc                 C   ry  r   )r   r   r   r   r   groupFactoryV  r{  zWordsRealm.groupFactoryc                    s    fdd}|S )Nc                      s"   t ddd   d   _ _d S )Nrg   c                   S   r>  r   r   r   r   r   r   r   \  s    z:WordsRealm.logoutFactory.<locals>.logout.<locals>.<lambda>)getattrrV   rW   r   ro   facetr   r   rg   Z  s   z(WordsRealm.logoutFactory.<locals>.logoutr   )r   ro   r  rg   r   r~  r   logoutFactoryY  s   zWordsRealm.logoutFactoryc                    s8   t  tr j  fdd} |S )Nc                    sl   | j d ur	t D ]%}|| d }|d ur0|   __ | _||| |f  S qtr   )rV   r   r   rY   r   ro   r  NotImplementedError)ro   r   r  avatarId
interfacesrW   r   r   r   	gotAvatare  s   


z+WordsRealm.requestAvatar.<locals>.gotAvatar)rw   rx   ry   	_encodinggetUserr8   )r   r  rW   r  r  r   r  r   requestAvatara  s   
zWordsRealm.requestAvatarc                 C   r>  r   r   rC   r   r   r   rd   t  rh  zWordsRealm.itergroupsFTc                 C      t r   r  r   r   r   r   r   |  r?  zWordsRealm.lookupUserc                 C   r  r   r  r   r   r   r   r     r?  zWordsRealm.lookupGroupc                 C   r  )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.
        r  r#  r   r   r   addUser  s   zWordsRealm.addUserc                 C   r  )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.
        r  r   r   r   r   addGroup  s   zWordsRealm.addGroupc                    .   j r fdd} |S  S )Nc                       |  tj  S r   )r   r   DuplicateGroupr   r   r   r   r   r   r        
z$WordsRealm.getGroup.<locals>.ebGroup)createGroupOnRequestcreateGroupr5   r   )r   r   r   r   r  r   r        
zWordsRealm.getGroupc                    r  )Nc                    r  r   )r   r   DuplicateUserr   r   r  r   r   r     r  z"WordsRealm.getUser.<locals>.ebUser)createUserOnRequest
createUserr5   r   )r   r   r   r   r  r   r    r  zWordsRealm.getUserc                    H    fdd} fdd}     }||| |j |S )Nc                       t t S r   )r   r    r   r  r   r   r   r   cbLookup  r%   z'WordsRealm.createUser.<locals>.cbLookupc                    r  r   )r   r   r)  rz  r   r  r   r   ebLookup  r  z'WordsRealm.createUser.<locals>.ebLookup)r   r   r   r8   r  r   r   r  r  r;   r   r  r   r       
zWordsRealm.createUserc                    r  )Nc                    r  r   )r   r    r   r  r   r   r   r   r    r%   z(WordsRealm.createGroup.<locals>.cbLookupc                    r  r   )r   r   r   r|  r   r  r   r   r    r  z(WordsRealm.createGroup.<locals>.ebLookup)r   r   r   r8   r  r  r   r  r   r    r  zWordsRealm.createGroupN)rO   rP   rQ   r  r   rz  r|  r  r  rd   r  r  r   r   r  r  r   r  r  r  r   r   r   r   rx  L  s$    

rx  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 | _i | _d S r   )superr   r   rS   )r   ar~   rY  r   r   r     s   
zInMemoryWordsRealm.__init__c                 C   s   t | j S r   )r	   r9   rS   r2   rC   r   r   r   rd     r%   zInMemoryWordsRealm.itergroupsc                 C   6   |j | jv rttt S || j|j < t|S r   )	r   r   r	   failr   r    r   r  r9   r#  r   r   r   r       
zInMemoryWordsRealm.addUserc                 C   r  r   )	r   rS   r	   r  r   r    r   r  r9   r   r   r   r   r    r  zInMemoryWordsRealm.addGroupc              
   C   J   |  }z| j| }W n ty   ttt| Y S w t	|S r   )
r   r   r>   r	   r  r   r    r   r)  r9   )r   r   r,   r   r   r   r        
zInMemoryWordsRealm.lookupUserc              
   C   r  r   )
r   rS   r>   r	   r  r   r    r   r   r9   )r   r   r]   r   r   r   r     r  zInMemoryWordsRealm.lookupGroup)
rO   rP   rQ   r   rd   r  r  r   r   __classcell__r   r   r  r   r    s    	r  )r   rR   rx  r  N)6r1  r   r   zope.interfacer   twistedr   twisted.credr   r   r   r   twisted.internetr	   r
   twisted.pythonr   r   r   twisted.python.componentsr   twisted.spreadr   twisted.wordsr   r   twisted.words.protocolsr   r   r   r   rR   r   r/   rz   rh   ServerFactoryr8  Referenceabler=  r_  rM  setUnjellyableForClassrN  r^  rO  rj  IPerspectiverq  IRealmIChatServicerx  r  __all__r   r   r   r   <module>   sV   M(     E"'
2 (