PageRenderTime 23ms CodeModel.GetById 6ms app.highlight 14ms RepoModel.GetById 1ms app.codeStats 0ms

/src/contact.py

http://pyaimt.googlecode.com/
Python | 279 lines | 273 code | 3 blank | 3 comment | 2 complexity | 56ac1004e1bce515bc2e5630a6edb8e0 MD5 | raw file
  1# Copyright 2005-2006 Daniel Henninger <jadestorm@nc.rr.com>
  2# Licensed for distribution under the GPL version 2, check COPYING for details
  3
  4import utils
  5from twisted.internet import reactor
  6from twisted.words.xish.domish import Element
  7import jabw
  8import config
  9from debug import LogEvent, INFO, WARN, ERROR
 10import lang
 11import sha
 12import legacy
 13import globals
 14import base64
 15if not config.disableAvatars:
 16	import Image
 17import StringIO
 18
 19
 20class Contact:
 21	""" Represents a Jabber contact """
 22	def __init__(self, jid, sub, contactList):
 23		self.jid = jid
 24		self.contactList = contactList
 25		self.groups = []
 26		self.sub = sub
 27		self.nickname = ""
 28		self.avatar = None
 29		self.show = ""
 30		self.status = ""
 31		self.url = ""
 32		self.ptype = "unavailable"
 33	
 34	def removeMe(self):
 35		""" Destroys this object. Does not remove the contact from the server's list. """
 36		self.contactList = None
 37		self.avatar = None
 38	
 39	def syncContactGrantedAuth(self):
 40		""" Since last using the transport the user has been granted authorisation by this contact.
 41		Call this to synchronise the user's Jabber list with their legacy list after logon. """
 42		if self.sub == "none":
 43			self.sub = "to"
 44		elif self.sub == "from":
 45			self.sub = "both"
 46		else:
 47			return
 48		self.updateRoster("subscribe")
 49
 50	def syncContactRemovedAuth(self):
 51		""" Since last using the transport the user has been blocked by this contact.
 52		Call this to synchronise the user's Jabber list with their legacy list after logon. """
 53		if self.sub == "to":
 54			self.sub = "none"
 55		elif self.sub == "both":
 56			self.sub = "from"
 57		else:
 58			return
 59		self.updateRoster("unsubscribed")
 60	
 61	def syncUserGrantedAuth(self):
 62		""" Since last using the transport the user has granted authorisation to this contact.
 63		Call this to synchronise the user's Jabber list with their legacy list after logon. """
 64		if self.sub == "none":
 65			self.sub = "from"
 66		elif self.sub == "to":
 67			self.sub = "both"
 68		else:
 69			return
 70		self.updateRoster("subscribe")
 71	
 72	def syncUserRemovedAuth(self):
 73		""" Since last using the transport the user has removed this contact's authorisation.
 74		Call this to synchronise the user's Jabber list with their legacy list after logon. """
 75		if self.sub == "from":
 76			self.sub = "none"
 77		elif self.sub == "both":
 78			self.sub = "to"
 79		else:
 80			return
 81		self.updateRoster("unsubscribe")
 82
 83	def syncGroups(self, groups, push=True):
 84		""" Set the groups that this contact is in on the legacy service.
 85		By default this pushes the groups out with a presence subscribed packet. """
 86		self.groups = groups
 87		if push: self.updateRoster("subscribed");
 88	
 89	def contactGrantsAuth(self):
 90		""" Live roster event """
 91		if self.sub == "none":
 92			self.sub = "to"
 93		elif self.sub == "from":
 94			self.sub = "both"
 95		self.sendSub("subscribed")
 96		self.sendPresence()
 97	
 98	def contactRemovesAuth(self):
 99		""" Live roster event """
100		if self.sub == "to":
101			self.sub = "none"
102		elif self.sub == "both":
103			self.sub = "from"
104		self.sendSub("unsubscribed")
105	
106	def contactRequestsAuth(self):
107		""" Live roster event """
108		self.sendSub("subscribe")
109	
110	def contactDerequestsAuth(self):
111		""" Live roster event """
112		self.sendSub("unsubscribe")
113	
114	def jabberSubscriptionReceived(self, subtype):
115		""" Updates the subscription state internally and pushes the update to the legacy server """
116		if subtype == "subscribe":
117			if self.sub == "to" or self.sub == "both":
118				self.sendSub("subscribed")
119			self.contactList.legacyList.addContact(self.jid)
120
121		elif subtype == "subscribed":
122			if self.sub == "none":
123				self.sub = "from"
124			if self.sub == "to":
125				self.sub = "both"
126			self.contactList.legacyList.authContact(self.jid)
127
128		elif(subtype == "unsubscribe"):
129			if self.sub == "none" and self.sub == "from":
130				self.sendSub("unsubscribed")
131			if self.sub == "both":
132				self.sub = "from"
133			if self.sub == "to":
134				self.sub = "none"
135			self.contactList.legacyList.removeContact(self.jid)
136
137		elif(subtype == "unsubscribed"):
138			if self.sub == "both":
139				self.sub = "to"
140			if self.sub == "from":
141				self.sub = "none"
142			self.contactList.legacyList.deauthContact(self.jid)
143
144	def updateNickname(self, nickname, push=True):
145		if self.nickname != nickname:
146			self.nickname = nickname
147			# will re-remove this if it's removed from JEP-0172.
148			#self.sendNickname()
149			if push: self.sendPresence()
150
151			#n = Element((None, "nick"))
152			#n.attributes["xmlns"] = globals.NICK
153			#n.addContent(nickname)
154			#self.contactList.session.pytrans.pubsub.localPublish(self.jid, globals.NICK, "current", n)
155	
156	def updatePresence(self, show, status, ptype, force=False, tojid=None, url=None):
157		updateFlag = (self.show != show or self.status != status or self.ptype != ptype or force)
158		self.show = show
159		self.status = status
160		self.ptype = ptype
161		self.url = url
162		if updateFlag:
163			self.sendPresence(tojid)
164	
165	def updateAvatar(self, avatar=None, push=True):
166		if config.disableAvatars: return
167		if self.avatar == avatar: return
168		self.avatar = avatar
169		if push: self.sendPresence()
170
171		#if self.avatar and not config.disableAvatars and not config.disablePEPAvatars:
172			#avatarHash = self.avatar.getImageHash()
173			#avatarData = self.avatar.getImageData()
174			#inbuff = StringIO.StringIO(avatarData)
175                        #img = Image.open(inbuff)
176
177			#d = Element((None, "data"))
178			#d.attributes["xmlns"] = globals.AVATARDATA
179			#d.addContent(base64.encodestring(avatarData).replace("\n",""))
180			#self.contactList.session.pytrans.pubsub.localPublish(self.jid, globals.AVATARDATA, avatarHash, d)
181
182			#m = Element((None, "metadata"))
183			#m.attributes["xmlns"] = globals.AVATARMETADATA
184			#mi = m.addElement("info")
185			#mi.attributes["id"] = avatarHash
186			#mi.attributes["type"] = "image/png"
187			#mi.attributes["bytes"] = str(len(avatarData))
188			#mi.attributes["height"] = str(img.size[0])
189			#mi.attributes["width"] = str(img.size[1])
190			#self.contactList.session.pytrans.pubsub.localPublish(self.jid, globals.AVATARMETADATA, avatarHash, m)
191	
192	def sendSub(self, ptype):
193		self.contactList.session.sendPresence(to=self.contactList.session.jabberID, fro=self.jid, ptype=ptype)
194
195	def sendNickname(self, tojid=None):
196		if not tojid:
197			tojid=self.contactList.session.jabberID
198		if self.nickname:
199			el = Element((None, "message"))
200			el.attributes["to"] = tojid
201			el.attributes["from"] = self.jid
202			nick = el.addElement("nick")
203			nick.attributes["xmlns"] = globals.NICK
204			nick.addContent(self.nickname)
205			self.contactList.session.pytrans.send(el)
206	
207	def sendPresence(self, tojid=None):
208		avatarHash = ""
209		if self.avatar and not config.disableAvatars:
210			avatarHash = self.avatar.getImageHash()
211		caps = Element((None, "c"))
212		caps.attributes["xmlns"] = globals.CAPS
213		caps.attributes["node"] = legacy.url + "/protocol/caps"
214		caps.attributes["ver"] = legacy.version
215		if not tojid:
216			tojid=self.contactList.session.jabberID
217		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], url=self.url)
218	
219	def updateRoster(self, ptype):
220		self.contactList.session.sendRosterImport(jid=self.jid, ptype=ptype, sub=self.sub, groups=self.groups)
221
222	def fillvCard(self, vCard, jid):
223		if self.nickname:
224			NICKNAME = vCard.addElement("NICKNAME")
225			NICKNAME.addContent(self.nickname)
226		if self.avatar and not config.disableAvatars and not config.disableVCardAvatars:
227			PHOTO = self.avatar.makePhotoElement()
228			vCard.addChild(PHOTO)
229		user = jid.split('@')[0]
230		return self.contactList.session.legacycon.jabberVCardRequest(vCard, user)
231
232
233class ContactList:
234	""" Represents the Jabber contact list """
235	def __init__(self, session):
236		LogEvent(INFO, session.jabberID)
237		self.session = session
238		self.contacts = {}
239	
240	def removeMe(self):
241		""" Cleanly removes the object """
242		LogEvent(INFO, self.session.jabberID)
243		for jid in self.contacts:
244			self.contacts[jid].updatePresence("", "", "unavailable")
245			self.contacts[jid].removeMe()
246		self.contacts = {}
247		self.session = None
248		self.legacyList = None
249	
250	def resendLists(self, tojid=None):
251		for jid in self.contacts:
252			if self.contacts[jid].status != "unavailable":
253				self.contacts[jid].sendPresence(tojid)
254		LogEvent(INFO, self.session.jabberID)
255	
256	def createContact(self, jid, sub):
257		""" Creates a contact object. Use this to initialise the contact list
258		Returns a Contact object which you can call sync* methods on to synchronise
259		the user's legacy contact list with their Jabber list """
260		LogEvent(INFO, self.session.jabberID)
261		c = Contact(jid, sub, self)
262		self.contacts[jid] = c
263		return c
264	
265	def getContact(self, jid):
266		""" Finds the contact. If one doesn't exist then a new one is created, with sub set to "none" """
267		if not self.contacts.has_key(jid):
268			self.contacts[jid] = Contact(jid, "none", self)
269		return self.contacts[jid]
270	
271	def findContact(self, jid):
272		if self.contacts.has_key(jid):
273			return self.contacts[jid]
274		return None
275	
276	def jabberSubscriptionReceived(self, jid, subtype):
277		self.getContact(jid).jabberSubscriptionReceived(subtype)
278	
279