| # -*- Python -*- |
| # Copyright (c) 2008 Twisted Matrix Laboratories. |
| # See LICENSE for details. |
| |
| """ |
| Pan-protocol chat client. |
| """ |
| |
| from zope.interface import Interface, Attribute |
| |
| from twisted.words.im import locals |
| |
| # (Random musings, may not reflect on current state of code:) |
| # |
| # Accounts have Protocol components (clients) |
| # Persons have Conversation components |
| # Groups have GroupConversation components |
| # Persons and Groups are associated with specific Accounts |
| # At run-time, Clients/Accounts are slaved to a User Interface |
| # (Note: User may be a bot, so don't assume all UIs are built on gui toolkits) |
| |
| |
| class IAccount(Interface): |
| """ |
| I represent a user's account with a chat service. |
| """ |
| |
| client = Attribute('The L{IClient} currently connecting to this account, if any.') |
| gatewayType = Attribute('A C{str} that identifies the protocol used by this account.') |
| |
| def __init__(accountName, autoLogin, username, password, host, port): |
| """ |
| @type accountName: string |
| @param accountName: A name to refer to the account by locally. |
| @type autoLogin: boolean |
| @type username: string |
| @type password: string |
| @type host: string |
| @type port: integer |
| """ |
| |
| def isOnline(): |
| """ |
| Am I online? |
| |
| @rtype: boolean |
| """ |
| |
| def logOn(chatui): |
| """ |
| Go on-line. |
| |
| @type chatui: Implementor of C{IChatUI} |
| |
| @rtype: L{Deferred} L{Client} |
| """ |
| |
| def logOff(): |
| """ |
| Sign off. |
| """ |
| |
| def getGroup(groupName): |
| """ |
| @rtype: L{Group<IGroup>} |
| """ |
| |
| def getPerson(personName): |
| """ |
| @rtype: L{Person<IPerson>} |
| """ |
| |
| class IClient(Interface): |
| |
| account = Attribute('The L{IAccount} I am a Client for') |
| |
| def __init__(account, chatui, logonDeferred): |
| """ |
| @type account: L{IAccount} |
| @type chatui: L{IChatUI} |
| @param logonDeferred: Will be called back once I am logged on. |
| @type logonDeferred: L{Deferred<twisted.internet.defer.Deferred>} |
| """ |
| |
| def joinGroup(groupName): |
| """ |
| @param groupName: The name of the group to join. |
| @type groupName: string |
| """ |
| |
| def leaveGroup(groupName): |
| """ |
| @param groupName: The name of the group to leave. |
| @type groupName: string |
| """ |
| |
| def getGroupConversation(name, hide=0): |
| pass |
| |
| def getPerson(name): |
| pass |
| |
| |
| class IPerson(Interface): |
| |
| def __init__(name, account): |
| """ |
| Initialize me. |
| |
| @param name: My name, as the server knows me. |
| @type name: string |
| @param account: The account I am accessed through. |
| @type account: I{Account} |
| """ |
| |
| def isOnline(): |
| """ |
| Am I online right now? |
| |
| @rtype: boolean |
| """ |
| |
| def getStatus(): |
| """ |
| What is my on-line status? |
| |
| @return: L{locals.StatusEnum} |
| """ |
| |
| def getIdleTime(): |
| """ |
| @rtype: string (XXX: How about a scalar?) |
| """ |
| |
| def sendMessage(text, metadata=None): |
| """ |
| Send a message to this person. |
| |
| @type text: string |
| @type metadata: dict |
| """ |
| |
| |
| class IGroup(Interface): |
| """ |
| A group which you may have a conversation with. |
| |
| Groups generally have a loosely-defined set of members, who may |
| leave and join at any time. |
| """ |
| |
| name = Attribute('My C{str} name, as the server knows me.') |
| account = Attribute('The L{Account<IAccount>} I am accessed through.') |
| |
| def __init__(name, account): |
| """ |
| Initialize me. |
| |
| @param name: My name, as the server knows me. |
| @type name: str |
| @param account: The account I am accessed through. |
| @type account: L{Account<IAccount>} |
| """ |
| |
| def setTopic(text): |
| """ |
| Set this Groups topic on the server. |
| |
| @type text: string |
| """ |
| |
| def sendGroupMessage(text, metadata=None): |
| """ |
| Send a message to this group. |
| |
| @type text: str |
| |
| @type metadata: dict |
| @param metadata: Valid keys for this dictionary include: |
| |
| - C{'style'}: associated with one of: |
| - C{'emote'}: indicates this is an action |
| """ |
| |
| def join(): |
| """ |
| Join this group. |
| """ |
| |
| def leave(): |
| """ |
| Depart this group. |
| """ |
| |
| |
| class IConversation(Interface): |
| """ |
| A conversation with a specific person. |
| """ |
| |
| def __init__(person, chatui): |
| """ |
| @type person: L{IPerson} |
| """ |
| |
| def show(): |
| """ |
| doesn't seem like it belongs in this interface. |
| """ |
| |
| def hide(): |
| """ |
| nor this neither. |
| """ |
| |
| def sendText(text, metadata): |
| pass |
| |
| def showMessage(text, metadata): |
| pass |
| |
| def changedNick(person, newnick): |
| """ |
| @param person: XXX Shouldn't this always be Conversation.person? |
| """ |
| |
| class IGroupConversation(Interface): |
| |
| def show(): |
| """ |
| doesn't seem like it belongs in this interface. |
| """ |
| |
| def hide(): |
| """ |
| nor this neither. |
| """ |
| |
| def sendText(text, metadata): |
| pass |
| |
| def showGroupMessage(sender, text, metadata): |
| pass |
| |
| def setGroupMembers(members): |
| """ |
| Sets the list of members in the group and displays it to the user. |
| """ |
| |
| def setTopic(topic, author): |
| """ |
| Displays the topic (from the server) for the group conversation window. |
| |
| @type topic: string |
| @type author: string (XXX: Not Person?) |
| """ |
| |
| def memberJoined(member): |
| """ |
| Adds the given member to the list of members in the group conversation |
| and displays this to the user, |
| |
| @type member: string (XXX: Not Person?) |
| """ |
| |
| def memberChangedNick(oldnick, newnick): |
| """ |
| Changes the oldnick in the list of members to C{newnick} and displays this |
| change to the user, |
| |
| @type oldnick: string (XXX: Not Person?) |
| @type newnick: string |
| """ |
| |
| def memberLeft(member): |
| """ |
| Deletes the given member from the list of members in the group |
| conversation and displays the change to the user. |
| |
| @type member: string (XXX: Not Person?) |
| """ |
| |
| |
| class IChatUI(Interface): |
| |
| def registerAccountClient(client): |
| """ |
| Notifies user that an account has been signed on to. |
| |
| @type client: L{Client<IClient>} |
| """ |
| |
| def unregisterAccountClient(client): |
| """ |
| Notifies user that an account has been signed off or disconnected. |
| |
| @type client: L{Client<IClient>} |
| """ |
| |
| def getContactsList(): |
| """ |
| @rtype: L{ContactsList} |
| """ |
| |
| # WARNING: You'll want to be polymorphed into something with |
| # intrinsic stoning resistance before continuing. |
| |
| def getConversation(person, Class, stayHidden=0): |
| """ |
| For the given person object, returns the conversation window |
| or creates and returns a new conversation window if one does not exist. |
| |
| @type person: L{Person<IPerson>} |
| @type Class: L{Conversation<IConversation>} class |
| @type stayHidden: boolean |
| |
| @rtype: L{Conversation<IConversation>} |
| """ |
| |
| def getGroupConversation(group, Class, stayHidden=0): |
| """ |
| For the given group object, returns the group conversation window or |
| creates and returns a new group conversation window if it doesn't exist. |
| |
| @type group: L{Group<interfaces.IGroup>} |
| @type Class: L{Conversation<interfaces.IConversation>} class |
| @type stayHidden: boolean |
| |
| @rtype: L{GroupConversation<interfaces.IGroupConversation>} |
| """ |
| |
| def getPerson(name, client): |
| """ |
| Get a Person for a client. |
| |
| Duplicates L{IAccount.getPerson}. |
| |
| @type name: string |
| @type client: L{Client<IClient>} |
| |
| @rtype: L{Person<IPerson>} |
| """ |
| |
| def getGroup(name, client): |
| """ |
| Get a Group for a client. |
| |
| Duplicates L{IAccount.getGroup}. |
| |
| @type name: string |
| @type client: L{Client<IClient>} |
| |
| @rtype: L{Group<IGroup>} |
| """ |
| |
| def contactChangedNick(oldnick, newnick): |
| """ |
| For the given person, changes the person's name to newnick, and |
| tells the contact list and any conversation windows with that person |
| to change as well. |
| |
| @type oldnick: string |
| @type newnick: string |
| """ |