]>
code.delx.au - pymsnt/blob - 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
5 if(utils
.checkTwisted()):
6 from twisted
.xish
.domish
import Element
8 from tlib
.domish
import Element
10 from legacy
import glue
14 def getGroupNames(msnContact
, msnContactList
):
16 for groupID
in msnContact
.groups
:
18 groups
.append(msnContactList
.groups
[groupID
])
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
):
28 elif(lists
& msn
.REVERSE_LIST
):
30 elif(lists
& msn
.FORWARD_LIST
):
36 def jabsub2msnlist(sub
):
37 """ Converts a Jabber subscription state into the corresponding MSN contact lists ORed together """
39 return msn
.FORWARD_LIST
41 return msn
.REVERSE_LIST
43 return (msn
.FORWARD_LIST | msn
.REVERSE_LIST
)
49 class SubscriptionManager
:
50 def __init__(self
, session
):
51 self
.session
= session
52 self
.subscriptionBuffer
= []
55 self
.subscriptionBuffer
= None
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()
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
)
73 newXDB
= Element((None, "query"))
74 newXDB
.attributes
["xmlns"] = "jabber:iq:roster"
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):
83 oldLists
= oldContact
.lists
87 def updatePresence(ptype
): # Convienence
88 self
.session
.sendPresence(to
=self
.session
.jabberID
, fro
=glue
.msn2jid(contact
.userHandle
), ptype
=ptype
)
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
)
96 if(not (lists
& msn
.FORWARD_LIST
)):
97 # User has been removed from forward list
98 updatePresence("unsubscribed")
100 if(oldLists
& msn
.REVERSE_LIST
):
101 if(not (lists
& msn
.REVERSE_LIST
)):
102 # User has been removed from reverse list
103 updatePresence("unsubscribe")
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")
109 item
= newXDB
.addElement("item")
110 item
.attributes
["jid"] = contact
.userHandle
111 item
.attributes
["subscription"] = msnlist2jabsub(lists
)
114 self
.session
.pytrans
.xdb
.set(self
.session
.jabberID
, "jabber:iq:roster", newXDB
)
115 debug
.log("Subscriptions: Session \"%s\" finished syncJabberLegacyLists()" % (self
.session
.jabberID
))
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
))
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
):
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
)
137 # Send a subscription packet
138 source
= glue
.msn2jid(userHandle
)
139 self
.session
.sendPresence(to
=self
.session
.jabberID
, fro
=source
, ptype
="subscribe")
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
))
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
)
152 self
.session
.pytrans
.xdb
.set(self
.session
.jabberID
, "jabber:iq:roster", document
)
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")
159 def flushSubscriptionBuffer(self
):
160 for (to
, subtype
) in self
.subscriptionBuffer
:
161 self
.jabberSubscriptionReceived(to
, subtype
)
163 def jabberSubscriptionReceived(self
, to
, subtype
):
164 debug
.log("Subscriptions: Session \"%s\" - jabberSubscriptionReceived(\"%s\", \"%s\")" % (self
.session
.jabberID
, to
, subtype
))
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
))
171 def updatePresence(ptype
): # Convienence
172 self
.session
.sendPresence(to
=self
.session
.jabberID
, fro
=to
, ptype
=ptype
)
174 if(to
.find('@') > 0): # For contacts
175 userHandle
= glue
.jid2msn(to
)
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.
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
)
189 # Add the contact to the user's MSN list
191 updatePresence("subscribed")
192 self
.session
.legacycon
.addContact(msn
.FORWARD_LIST
, userHandle
).addCallback(cb
)
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
201 self
.session
.legacycon
.remContact(msn
.BLOCK_LIST
, userHandle
).addCallback(cb
)
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
)
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
213 self
.session
.legacycon
.remContact(msn
.FORWARD_LIST
, userHandle
).addCallback(cb
)
215 updatePresence("unsubscribed")
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
224 self
.session
.legacycon
.addContact(msn
.BLOCK_LIST
, userHandle
).addCallback(cb
)
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)
234 else: # The user wants to change subscription to the transport
235 if(subtype
== "subscribe"):
236 updatePresence("subscribed")
238 elif(subtype
== "subscribed"):
239 return # Nothing to do
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
))