]> code.delx.au - pymsnt/blob - src/contact.py
Reimport and tags (0.10.1)
[pymsnt] / src / contact.py
1 # Copyright 2005 James Bunton <james@delx.cjb.net>
2 # Licensed for distribution under the GPL version 2, check COPYING for details
3
4 import utils
5 from twisted.internet import reactor
6 if(utils.checkTwisted()):
7 from twisted.xish.domish import Element
8 else:
9 from tlib.domish import Element
10 from debug import LogEvent, INFO, WARN, ERROR
11 import disco
12 import legacy
13 import jabw
14 import config
15 import lang
16 import sha
17
18
19 class Contact:
20 """ Represents a Jabber contact """
21 def __init__(self, jid, sub, contactList):
22 self.jid = jid
23 self.contactList = contactList
24 self.groups = []
25 self.sub = sub
26 self.nickname = ""
27 self.avatar = None
28 self.show = ""
29 self.status = ""
30 self.ptype = "unavailable"
31
32 def removeMe(self):
33 """ Destroys this object. Does not remove the contact from the server's list. """
34 self.contactList = None
35 self.avatar = None
36
37 def syncContactGrantedAuth(self):
38 """ Since last using the transport the user has been granted authorisation by this contact.
39 Call this to synchronise the user's Jabber list with their legacy list after logon. """
40 if(self.sub == "none"):
41 self.sub = "to"
42 elif(self.sub == "from"):
43 self.sub = "both"
44 else:
45 return
46 self.updateRoster("subscribe")
47
48 def syncContactRemovedAuth(self):
49 """ Since last using the transport the user has been blocked by this contact.
50 Call this to synchronise the user's Jabber list with their legacy list after logon. """
51 if(self.sub == "to"):
52 self.sub = "none"
53 elif(self.sub == "both"):
54 self.sub = "from"
55 else:
56 return
57 self.updateRoster("unsubscribed")
58
59 def syncUserGrantedAuth(self):
60 """ Since last using the transport the user has granted authorisation to this contact.
61 Call this to synchronise the user's Jabber list with their legacy list after logon. """
62 if(self.sub == "none"):
63 self.sub = "from"
64 elif(self.sub == "to"):
65 self.sub = "both"
66 else:
67 return
68 self.updateRoster("subscribe")
69
70 def syncUserRemovedAuth(self):
71 """ Since last using the transport the user has removed this contact's authorisation.
72 Call this to synchronise the user's Jabber list with their legacy list after logon. """
73 if(self.sub == "from"):
74 self.sub = "none"
75 elif(self.sub == "both"):
76 self.sub = "to"
77 else:
78 return
79 self.updateRoster("unsubscribe")
80
81 def syncGroups(self, groups, push=True):
82 """ Set the groups that this contact is in on the legacy service.
83 By default this pushes the groups out with a presence subscribed packet. """
84 self.groups = groups
85 if push: self.updateRoster("subscribed");
86
87 def contactGrantsAuth(self):
88 """ Live roster event """
89 if(self.sub == "none"):
90 self.sub = "to"
91 elif(self.sub == "from"):
92 self.sub = "both"
93 self.sendSub("subscribed")
94 self.sendPresence()
95
96 def contactRemovesAuth(self):
97 """ Live roster event """
98 if(self.sub == "to"):
99 self.sub = "none"
100 elif(self.sub == "both"):
101 self.sub = "from"
102 self.sendSub("unsubscribed")
103
104 def contactRequestsAuth(self):
105 """ Live roster event """
106 self.sendSub("subscribe")
107
108 def contactDerequestsAuth(self):
109 """ Live roster event """
110 self.sendSub("unsubscribe")
111
112 def jabberSubscriptionReceived(self, subtype):
113 """ Updates the subscription state internally and pushes the update to the legacy server """
114 if subtype == "subscribe":
115 if self.sub == "to" or self.sub == "both":
116 self.sendSub("subscribed")
117 self.contactList.legacyList.addContact(self.jid)
118
119 elif subtype == "subscribed":
120 if self.sub == "none":
121 self.sub = "from"
122 if self.sub == "to":
123 self.sub = "both"
124 self.contactList.legacyList.authContact(self.jid)
125
126 elif subtype == "unsubscribe":
127 if self.sub == "none" or self.sub == "from":
128 self.sendSub("unsubscribed")
129 if self.sub == "both":
130 self.sub = "from"
131 if self.sub == "to":
132 self.sub = "none"
133 self.contactList.legacyList.removeContact(self.jid)
134
135 elif(subtype == "unsubscribed"):
136 if(self.sub == "both"):
137 self.sub = "to"
138 if(self.sub == "from"):
139 self.sub = "none"
140 self.contactList.legacyList.deauthContact(self.jid)
141
142 def updateNickname(self, nickname, push=True):
143 if(self.nickname != nickname):
144 self.nickname = nickname
145 if(push): self.sendPresence()
146
147 def updatePresence(self, show, status, ptype, force=False):
148 updateFlag = (self.show != show or self.status != status or self.ptype != ptype or force)
149 self.show = show
150 self.status = status
151 self.ptype = ptype
152 if(updateFlag):
153 self.sendPresence()
154
155 def updateAvatar(self, avatar=None, push=True):
156 if(self.avatar == avatar): return
157 self.avatar = avatar
158 if(push): self.sendPresence()
159
160 def sendSub(self, ptype):
161 self.contactList.session.sendPresence(to=self.contactList.session.jabberID, fro=self.jid, ptype=ptype)
162
163 def sendPresence(self, tojid=""):
164 avatarHash = ""
165 if(self.avatar):
166 avatarHash = self.avatar.getImageHash()
167 caps = Element((None, "c"))
168 caps.attributes["xmlns"] = disco.CAPS
169 caps.attributes["node"] = legacy.url + "/protocol/caps"
170 caps.attributes["ver"] = legacy.version
171 if not tojid:
172 tojid=self.contactList.session.jabberID
173 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])
174
175 def updateRoster(self, ptype):
176 self.contactList.session.sendRosterImport(jid=self.jid, ptype=ptype, sub=self.sub, groups=self.groups, name=self.nickname)
177
178
179 class ContactList:
180 """ Represents the Jabber contact list """
181 def __init__(self, session):
182 LogEvent(INFO, session.jabberID)
183 self.session = session
184 self.contacts = {}
185
186 def removeMe(self):
187 """ Cleanly removes the object """
188 LogEvent(INFO, self.session.jabberID)
189 for jid in self.contacts:
190 self.contacts[jid].updatePresence("", "", "unavailable")
191 self.contacts[jid].removeMe()
192 self.contacts = {}
193 self.session = None
194 self.legacyList = None
195
196 def resendLists(self, tojid=""):
197 for jid in self.contacts:
198 if(self.contacts[jid].status != "unavailable"):
199 self.contacts[jid].sendPresence(tojid)
200 LogEvent(INFO, self.session.jabberID)
201
202 def createContact(self, jid, sub):
203 """ Creates a contact object. Use this to initialise the contact list
204 Returns a Contact object which you can call sync* methods on to synchronise
205 the user's legacy contact list with their Jabber list """
206 LogEvent(INFO, self.session.jabberID)
207 c = Contact(jid, sub, self)
208 self.contacts[jid] = c
209 return c
210
211 def getContact(self, jid):
212 """ Finds the contact. If one doesn't exist then a new one is created, with sub set to "none" """
213 if(not self.contacts.has_key(jid)):
214 self.contacts[jid] = Contact(jid, "none", self)
215 return self.contacts[jid]
216
217 def findContact(self, jid):
218 if(self.contacts.has_key(jid)):
219 return self.contacts[jid]
220 return None
221
222 def jabberSubscriptionReceived(self, jid, subtype):
223 self.getContact(jid).jabberSubscriptionReceived(subtype)
224
225