]> code.delx.au - pymsnt/blob - src/legacy/subscription.py
Reimporting (0.9.5)
[pymsnt] / src / legacy / subscription.py
1 # Copyright 2004 James Bunton <james@delx.cjb.net>
2 # Licensed for distribution under the GPL version 2, check COPYING for details
3
4 import utils
5 if(utils.checkTwisted()):
6 from twisted.xish.domish import Element
7 else:
8 from tlib.domish import Element
9 from tlib import msn
10 from legacy import glue
11 import debug
12
13
14 def getGroupNames(msnContact, msnContactList):
15 groups = []
16 for groupID in msnContact.groups:
17 try:
18 groups.append(msnContactList.groups[groupID])
19 except:
20 pass
21 return groups
22
23
24 def msnlist2jabsub(lists):
25 """ Converts MSN contact lists ORed together into the corresponding Jabber subscription state """
26 if(lists & msn.FORWARD_LIST and lists & msn.REVERSE_LIST):
27 return "both"
28 elif(lists & msn.REVERSE_LIST):
29 return "from"
30 elif(lists & msn.FORWARD_LIST):
31 return "to"
32 else:
33 return "none"
34
35
36 def jabsub2msnlist(sub):
37 """ Converts a Jabber subscription state into the corresponding MSN contact lists ORed together """
38 if(sub == "to"):
39 return msn.FORWARD_LIST
40 elif(sub == "from"):
41 return msn.REVERSE_LIST
42 elif(sub == "both"):
43 return (msn.FORWARD_LIST | msn.REVERSE_LIST)
44 else:
45 return 0
46
47
48
49 class SubscriptionManager:
50 def __init__(self, session):
51 self.session = session
52 self.subscriptionBuffer = []
53
54 def removeMe(self):
55 self.subscriptionBuffer = None
56 self.session = None
57
58 def syncJabberLegacyLists(self):
59 """ Synchronises the MSN contact list on server with the Jabber contact list """
60 # We have to make an MSNContactList from the XDB data, then compare it with the one the server sent
61 # Any subscription changes must be sent to the client, as well as changed in the XDB
62 debug.log("Subscriptions: Session \"%s\" starting syncJabberLegacyLists()" % (self.session.jabberID))
63 result = self.session.pytrans.xdb.request(self.session.jabberID, "jabber:iq:roster")
64 oldContactList = msn.MSNContactList()
65 if(result):
66 for item in result.elements():
67 user = item.getAttribute("jid")
68 sub = item.getAttribute("subscription")
69 lists = jabsub2msnlist(sub)
70 contact = msn.MSNContact(userHandle=user, screenName="", lists=lists)
71 oldContactList.addContact(contact)
72
73 newXDB = Element((None, "query"))
74 newXDB.attributes["xmlns"] = "jabber:iq:roster"
75
76 contactList = self.session.legacycon.getContacts()
77 for contact in contactList.contacts.values():
78 # Compare with the XDB <item/> entry
79 oldContact = oldContactList.getContact(contact.userHandle)
80 if(oldContact == None):
81 oldLists = 0
82 else:
83 oldLists = oldContact.lists
84 lists = contact.lists
85
86
87 def updatePresence(ptype): # Convienence
88 self.session.sendPresence(to=self.session.jabberID, fro=glue.msn2jid(contact.userHandle), ptype=ptype)
89
90 if(not (oldLists & msn.FORWARD_LIST)):
91 if(lists & msn.FORWARD_LIST):
92 # User has been added to forward list
93 groups = getGroupNames(contact, self.session.legacycon.getContacts())
94 self.session.sendRosterImport(glue.msn2jid(contact.userHandle), "subscribe", "both", contact.screenName, groups)
95 else:
96 if(not (lists & msn.FORWARD_LIST)):
97 # User has been removed from forward list
98 updatePresence("unsubscribed")
99
100 if(oldLists & msn.REVERSE_LIST):
101 if(not (lists & msn.REVERSE_LIST)):
102 # User has been removed from reverse list
103 updatePresence("unsubscribe")
104
105 if(not (lists & msn.ALLOW_LIST) and not (lists & msn.BLOCK_LIST) and (lists & msn.REVERSE_LIST)):
106 # User isn't blocked, and isn't currently allowed, so will subscribe to your presence
107 updatePresence("subscribe")
108
109 item = newXDB.addElement("item")
110 item.attributes["jid"] = contact.userHandle
111 item.attributes["subscription"] = msnlist2jabsub(lists)
112
113 # Update the XDB
114 self.session.pytrans.xdb.set(self.session.jabberID, "jabber:iq:roster", newXDB)
115 debug.log("Subscriptions: Session \"%s\" finished syncJabberLegacyLists()" % (self.session.jabberID))
116
117
118
119 def msnContactAddedMe(self, userHandle):
120 # User has been added to our reverse list (we are now on their forward list)
121 debug.log("Subscriptions: Session \"%s\" msnContactAddedMe(\"%s\")" % (self.session.jabberID, userHandle))
122
123 # Update the XDB if needed
124 document = self.session.pytrans.xdb.request(self.session.jabberID, "jabber:iq:roster")
125 if(not document): return # We can ignore this error. It will get fixed at next logon. It's fixed better in the next version :)
126 for item in document.elements():
127 user = item.getAttribute("jid")
128 if(user == userHandle):
129 break
130 else:
131 # Not found, so we need to add it
132 item = document.addElement("item")
133 item.attributes["jid"] = userHandle
134 item.attributes["subscription"] = "from"
135 self.session.pytrans.xdb.set(self.session.jabberID, "jabber:iq:roster", document)
136
137 # Send a subscription packet
138 source = glue.msn2jid(userHandle)
139 self.session.sendPresence(to=self.session.jabberID, fro=source, ptype="subscribe")
140
141 def msnContactRemovedMe(self, userHandle):
142 # User has been removed from our reverse list (we are no longer on their forward list)
143 debug.log("Subscriptions: Session \"%s\" msnContactRemovedMe(\"%s\")" % (self.session.jabberID, userHandle))
144
145 # Update the XDB
146 document = self.session.pytrans.xdb.request(self.session.jabberID, "jabber:iq:roster")
147 for item in document.elements():
148 user = item.getAttribute("jid")
149 if(user == userHandle):
150 document.children.remove(item)
151 break
152 self.session.pytrans.xdb.set(self.session.jabberID, "jabber:iq:roster", document)
153
154 # Send an unsubscribe packet (the contact is no longer viewing the user's presence)
155 source = glue.msn2jid(userHandle)
156 self.session.sendPresence(to=self.session.jabberID, fro=source, ptype="unsubscribe")
157
158
159 def flushSubscriptionBuffer(self):
160 for (to, subtype) in self.subscriptionBuffer:
161 self.jabberSubscriptionReceived(to, subtype)
162
163 def jabberSubscriptionReceived(self, to, subtype):
164 debug.log("Subscriptions: Session \"%s\" - jabberSubscriptionReceived(\"%s\", \"%s\")" % (self.session.jabberID, to, subtype))
165
166 if(not (self.session.ready and self.session.legacycon.getContacts())):
167 # Buffer until we have received the MSN contact list
168 self.subscriptionBuffer.append((to, subtype))
169 return
170
171 def updatePresence(ptype): # Convienence
172 self.session.sendPresence(to=self.session.jabberID, fro=to, ptype=ptype)
173
174 if(to.find('@') > 0): # For contacts
175 userHandle = glue.jid2msn(to)
176
177 msnContact = self.session.legacycon.getContacts().getContact(userHandle)
178 lists = 0 # Lists default to none
179 if(msnContact and msnContact.lists):
180 lists = msnContact.lists # We know extra information about what lists they're in.
181
182 if(subtype == "subscribe"):
183 # User wants to subscribe to contact's presence
184 if(lists & msn.FORWARD_LIST):
185 # The contact is already on the user's MSN list, so tell the user that this is so
186 groups = getGroupNames(msnContact, self.session.legacycon.getContacts())
187 self.session.sendRosterImport(glue.msn2jid(msnContact.userHandle), "subscribed", "both", msnContact.screenName, groups)
188 else:
189 # Add the contact to the user's MSN list
190 def cb(arg=None):
191 updatePresence("subscribed")
192 self.session.legacycon.addContact(msn.FORWARD_LIST, userHandle).addCallback(cb)
193
194 elif(subtype == "subscribed"):
195 # The user has granted this contact subscription.
196 def remFromBlockList(arg=None):
197 if(lists & msn.BLOCK_LIST):
198 # If they were on the block list remove them
199 def cb(arg=None):
200 pass
201 self.session.legacycon.remContact(msn.BLOCK_LIST, userHandle).addCallback(cb)
202
203 if(not (lists & msn.ALLOW_LIST)):
204 # We add the contact to the allow list
205 self.session.legacycon.addContact(msn.ALLOW_LIST, userHandle).addCallback(remFromBlockList)
206
207 elif(subtype == "unsubscribe"):
208 # User wants to unsubscribe to this contact's presence. (User is removing the contact from their list)
209 if(lists & msn.FORWARD_LIST):
210 # Contact is in the forward list, so remove them
211 def cb(arg=None):
212 pass
213 self.session.legacycon.remContact(msn.FORWARD_LIST, userHandle).addCallback(cb)
214 else:
215 updatePresence("unsubscribed")
216
217 elif(subtype == "unsubscribed"):
218 # The user wants to remove this contact's authorisation. Contact will no longer be able to see user
219 def addToBlockList(arg=None):
220 if(not (lists & msn.BLOCK_LIST)):
221 # If they're not on the block list then add them to it
222 def cb(arg=None):
223 pass
224 self.session.legacycon.addContact(msn.BLOCK_LIST, userHandle).addCallback(cb)
225
226 if(lists & msn.ALLOW_LIST):
227 # If they're currently on the allow list then remove them
228 # Should we add them to the block list?
229 # Yes we should. The MSN client seems to. So we'll follow their lead.
230 self.session.legacycon.remContact(msn.ALLOW_LIST, userHandle)#.addCallback(addToBlockList)
231 else:
232 addToBlockList()
233
234 else: # The user wants to change subscription to the transport
235 if(subtype == "subscribe"):
236 updatePresence("subscribed")
237
238 elif(subtype == "subscribed"):
239 return # Nothing to do
240
241 elif(subtype == "unsubscribe" or subtype == "unsubscribed"):
242 # They want to unregister. Ok, we can do that
243 jid = self.session.jabberID
244 debug.log("Subscriptions: Session \"%s\" is about to be unregistered" % (jid))
245 self.session.pytrans.registermanager.removeRegInfo(jid)
246 debug.log("Subscriptions: Session \"%s\" has been unregistered" % (jid))
247