]> code.delx.au - pymsnt/blobdiff - src/contact.py
Reimport and tags (0.10.1)
[pymsnt] / src / contact.py
diff --git a/src/contact.py b/src/contact.py
new file mode 100644 (file)
index 0000000..48cb184
--- /dev/null
@@ -0,0 +1,225 @@
+# Copyright 2005 James Bunton <james@delx.cjb.net>
+# Licensed for distribution under the GPL version 2, check COPYING for details
+
+import utils
+from twisted.internet import reactor
+if(utils.checkTwisted()):
+       from twisted.xish.domish import Element
+else:
+       from tlib.domish import Element
+from debug import LogEvent, INFO, WARN, ERROR
+import disco
+import legacy
+import jabw
+import config
+import lang
+import sha
+
+
+class Contact:
+       """ Represents a Jabber contact """
+       def __init__(self, jid, sub, contactList):
+               self.jid = jid
+               self.contactList = contactList
+               self.groups = []
+               self.sub = sub
+               self.nickname = ""
+               self.avatar = None
+               self.show = ""
+               self.status = ""
+               self.ptype = "unavailable"
+       
+       def removeMe(self):
+               """ Destroys this object. Does not remove the contact from the server's list. """
+               self.contactList = None
+               self.avatar = None
+       
+       def syncContactGrantedAuth(self):
+               """ Since last using the transport the user has been granted authorisation by this contact.
+               Call this to synchronise the user's Jabber list with their legacy list after logon. """
+               if(self.sub == "none"):
+                       self.sub = "to"
+               elif(self.sub == "from"):
+                       self.sub = "both"
+               else:
+                       return
+               self.updateRoster("subscribe")
+
+       def syncContactRemovedAuth(self):
+               """ Since last using the transport the user has been blocked by this contact.
+               Call this to synchronise the user's Jabber list with their legacy list after logon. """
+               if(self.sub == "to"):
+                       self.sub = "none"
+               elif(self.sub == "both"):
+                       self.sub = "from"
+               else:
+                       return
+               self.updateRoster("unsubscribed")
+       
+       def syncUserGrantedAuth(self):
+               """ Since last using the transport the user has granted authorisation to this contact.
+               Call this to synchronise the user's Jabber list with their legacy list after logon. """
+               if(self.sub == "none"):
+                       self.sub = "from"
+               elif(self.sub == "to"):
+                       self.sub = "both"
+               else:
+                       return
+               self.updateRoster("subscribe")
+       
+       def syncUserRemovedAuth(self):
+               """ Since last using the transport the user has removed this contact's authorisation.
+               Call this to synchronise the user's Jabber list with their legacy list after logon. """
+               if(self.sub == "from"):
+                       self.sub = "none"
+               elif(self.sub == "both"):
+                       self.sub = "to"
+               else:
+                       return
+               self.updateRoster("unsubscribe")
+       
+       def syncGroups(self, groups, push=True):
+               """ Set the groups that this contact is in on the legacy service.
+               By default this pushes the groups out with a presence subscribed packet. """
+               self.groups = groups
+               if push: self.updateRoster("subscribed");
+       
+       def contactGrantsAuth(self):
+               """ Live roster event """
+               if(self.sub == "none"):
+                       self.sub = "to"
+               elif(self.sub == "from"):
+                       self.sub = "both"
+               self.sendSub("subscribed")
+               self.sendPresence()
+       
+       def contactRemovesAuth(self):
+               """ Live roster event """
+               if(self.sub == "to"):
+                       self.sub = "none"
+               elif(self.sub == "both"):
+                       self.sub = "from"
+               self.sendSub("unsubscribed")
+       
+       def contactRequestsAuth(self):
+               """ Live roster event """
+               self.sendSub("subscribe")
+       
+       def contactDerequestsAuth(self):
+               """ Live roster event """
+               self.sendSub("unsubscribe")
+       
+       def jabberSubscriptionReceived(self, subtype):
+               """ Updates the subscription state internally and pushes the update to the legacy server """
+               if subtype == "subscribe":
+                       if self.sub == "to" or self.sub == "both":
+                               self.sendSub("subscribed")
+                       self.contactList.legacyList.addContact(self.jid)
+
+               elif subtype == "subscribed":
+                       if self.sub == "none":
+                               self.sub = "from"
+                       if self.sub == "to":
+                               self.sub = "both"
+                       self.contactList.legacyList.authContact(self.jid)
+
+               elif subtype == "unsubscribe":
+                       if self.sub == "none" or self.sub == "from":
+                               self.sendSub("unsubscribed")
+                       if self.sub == "both":
+                               self.sub = "from"
+                       if self.sub == "to":
+                               self.sub = "none"
+                       self.contactList.legacyList.removeContact(self.jid)
+
+               elif(subtype == "unsubscribed"):
+                       if(self.sub == "both"):
+                               self.sub = "to"
+                       if(self.sub == "from"):
+                               self.sub = "none"
+                       self.contactList.legacyList.deauthContact(self.jid)
+
+       def updateNickname(self, nickname, push=True):
+               if(self.nickname != nickname):
+                       self.nickname = nickname
+                       if(push): self.sendPresence()
+       
+       def updatePresence(self, show, status, ptype, force=False):
+               updateFlag = (self.show != show or self.status != status or self.ptype != ptype or force)
+               self.show = show
+               self.status = status
+               self.ptype = ptype
+               if(updateFlag):
+                       self.sendPresence()
+       
+       def updateAvatar(self, avatar=None, push=True):
+               if(self.avatar == avatar): return
+               self.avatar = avatar
+               if(push): self.sendPresence()
+       
+       def sendSub(self, ptype):
+               self.contactList.session.sendPresence(to=self.contactList.session.jabberID, fro=self.jid, ptype=ptype)
+       
+       def sendPresence(self, tojid=""):
+               avatarHash = ""
+               if(self.avatar):
+                       avatarHash = self.avatar.getImageHash()
+               caps = Element((None, "c"))
+               caps.attributes["xmlns"] = disco.CAPS
+               caps.attributes["node"] = legacy.url + "/protocol/caps"
+               caps.attributes["ver"] = legacy.version
+               if not tojid:
+                       tojid=self.contactList.session.jabberID
+               self.contactList.session.sendPresence(to=tojid, fro=self.jid, ptype=self.ptype, show=self.show, status=self.status, avatarHash=avatarHash, nickname=self.nickname, payload=[caps])
+       
+       def updateRoster(self, ptype):
+               self.contactList.session.sendRosterImport(jid=self.jid, ptype=ptype, sub=self.sub, groups=self.groups, name=self.nickname)
+
+
+class ContactList:
+       """ Represents the Jabber contact list """
+       def __init__(self, session):
+               LogEvent(INFO, session.jabberID)
+               self.session = session
+               self.contacts = {}
+       
+       def removeMe(self):
+               """ Cleanly removes the object """
+               LogEvent(INFO, self.session.jabberID)
+               for jid in self.contacts:
+                       self.contacts[jid].updatePresence("", "", "unavailable")
+                       self.contacts[jid].removeMe()
+               self.contacts = {}
+               self.session = None
+               self.legacyList = None
+       
+       def resendLists(self, tojid=""):
+               for jid in self.contacts:
+                       if(self.contacts[jid].status != "unavailable"):
+                               self.contacts[jid].sendPresence(tojid)
+               LogEvent(INFO, self.session.jabberID)
+       
+       def createContact(self, jid, sub):
+               """ Creates a contact object. Use this to initialise the contact list
+               Returns a Contact object which you can call sync* methods on to synchronise
+               the user's legacy contact list with their Jabber list """
+               LogEvent(INFO, self.session.jabberID)
+               c = Contact(jid, sub, self)
+               self.contacts[jid] = c
+               return c
+       
+       def getContact(self, jid):
+               """ Finds the contact. If one doesn't exist then a new one is created, with sub set to "none" """
+               if(not self.contacts.has_key(jid)):
+                       self.contacts[jid] = Contact(jid, "none", self)
+               return self.contacts[jid]
+       
+       def findContact(self, jid):
+               if(self.contacts.has_key(jid)):
+                       return self.contacts[jid]
+               return None
+       
+       def jabberSubscriptionReceived(self, jid, subtype):
+               self.getContact(jid).jabberSubscriptionReceived(subtype)
+       
+