]>
code.delx.au - pymsnt/blob - src/legacy/glue.py
1 # Copyright 2004-2005 James Bunton <james@delx.cjb.net>
2 # Licensed for distribution under the GPL version 2, check COPYING for details
6 from twisted
. internet
import task
7 from tlib
. xmlw
import Element
9 from debug
import LogEvent
, INFO
, WARN
, ERROR
20 url
= "http://msn-transport.jabberstudio.org"
21 version
= "0.11-dev" # The transport version
22 mangle
= True # XDB '@' -> '%' mangling
23 id = "msn" # The transport identifier
26 # Load the default avatars
27 f
= open ( os
. path
. join ( "data" , "defaultJabberAvatar.png" ), "rb" )
28 defaultJabberAvatarData
= f
. read ()
31 f
= open ( os
. path
. join ( "data" , "defaultMSNAvatar.png" ), "rb" )
32 defaultAvatarData
= f
. read ()
34 defaultAvatar
= avatar
. AvatarCache (). setAvatar ( defaultAvatarData
)
38 msn
. MSNConnection
. GETALLAVATARS
= config
. getAllAvatars
41 """ Returns True if the JID passed is a valid groupchat JID (for MSN, does not contain '%') """
42 return ( jid
. find ( '%' ) == - 1 )
46 # This should be set to the name space the registration entries are in, in the xdb spool
47 namespace
= "jabber:iq:register"
50 def formRegEntry ( username
, password
):
51 """ Returns a domish.Element representation of the data passed. This element will be written to the XDB spool file """
52 reginfo
= Element (( None , "query" ))
53 reginfo
. attributes
[ "xmlns" ] = "jabber:iq:register"
55 userEl
= reginfo
. addElement ( "username" )
56 userEl
. addContent ( username
)
58 passEl
= reginfo
. addElement ( "password" )
59 passEl
. addContent ( password
)
66 def getAttributes ( base
):
67 """ This function should, given a spool domish.Element, pull the username, password,
68 and out of it and return them """
71 for child
in base
. elements ():
73 if child
. name
== "username" :
74 username
= child
.__ str
__ ()
75 elif child
. name
== "password" :
76 password
= child
.__ str
__ ()
77 except AttributeError :
80 return username
, password
83 def startStats ( statistics
):
84 stats
= statistics
. stats
85 stats
[ "MessageCount" ] = 0
86 stats
[ "FailedMessageCount" ] = 0
87 stats
[ "AvatarCount" ] = 0
88 stats
[ "FailedAvatarCount" ] = 0
90 def updateStats ( statistics
):
91 stats
= statistics
. stats
93 #stats["AvatarCount"] = msnp2p.MSNP2P_Avatar.TRANSFER_COUNT
94 #stats["FailedAvatarCount"] = msnp2p.MSNP2P_Avatar.ERROR_COUNT
98 def msn2jid ( msnid
, withResource
):
99 """ Converts a MSN passport into a JID representation to be used with the transport """
103 if msn2jid_cache
. has_key ( msnid
):
104 jid
= msn2jid_cache
[ msnid
]
109 if msnid
. startswith ( "tel:+" ):
110 msnid
= msnid
. replace ( "tel:+" , "" ) + "%tel"
111 jid
= msnid
. replace ( '@' , '%' ) + "@" + config
. jid
+ ( withResource
and "/msn" or "" )
112 msn2jid_cache
[ msnid
] = jid
113 jid2msn_cache
[ jid
] = msnid
116 # Marks this as the function to be used in jabber:iq:gateway (Service ID Translation)
117 def translateAccount ( msnid
):
118 return msn2jid ( msnid
, False )
122 """ Converts a JID representation of a MSN passport into the original MSN passport """
126 if jid2msn_cache
. has_key ( jid
):
127 msnid
= jid2msn_cache
[ jid
]
130 if jid
. find ( "%tel@" ) > 0 :
131 jid
= "tel:+" + jid
. replace ( "%tel@" , "@" )
132 msnid
= unicode ( jid
[: jid
. find ( '@' )]. replace ( '%' , '@' )). split ( "/" )[ 0 ]
133 jid2msn_cache
[ jid
] = msnid
134 msn2jid_cache
[ msnid
] = jid
138 def presence2state ( show
, ptype
):
139 """ Converts a Jabber presence into an MSN status code """
140 if ptype
== "unavailable" :
141 return msn
. STATUS_OFFLINE
142 elif not show
or show
== "online" or show
== "chat" :
143 return msn
. STATUS_ONLINE
145 return msn
. STATUS_BUSY
146 elif show
== "away" or show
== "xa" :
147 return msn
. STATUS_AWAY
148 return msn
. STATUS_ONLINE
151 def state2presence ( state
):
152 """ Converts a MSN status code into a Jabber presence """
153 if state
== msn
. STATUS_ONLINE
:
155 elif state
== msn
. STATUS_BUSY
:
157 elif state
== msn
. STATUS_AWAY
:
158 return ( "away" , None )
159 elif state
== msn
. STATUS_IDLE
:
160 return ( "away" , None )
161 elif state
== msn
. STATUS_BRB
:
162 return ( "away" , None )
163 elif state
== msn
. STATUS_PHONE
:
165 elif state
== msn
. STATUS_LUNCH
:
166 return ( "away" , None )
168 return ( None , "unavailable" )
171 def getGroupNames ( msnContact
, msnContactList
):
172 """ Gets a list of groups that this contact is in """
174 for groupGUID
in msnContact
. groups
:
176 groups
. append ( msnContactList
. groups
[ groupGUID
])
181 def msnlist2jabsub ( lists
):
182 """ Converts MSN contact lists ORed together into the corresponding Jabber subscription state """
183 if lists
& msn
. FORWARD_LIST
and lists
& msn
. REVERSE_LIST
:
185 elif lists
& msn
. REVERSE_LIST
:
187 elif lists
& msn
. FORWARD_LIST
:
193 def jabsub2msnlist ( sub
):
194 """ Converts a Jabber subscription state into the corresponding MSN contact lists ORed together """
196 return msn
. FORWARD_LIST
198 return msn
. REVERSE_LIST
200 return ( msn
. FORWARD_LIST | msn
. REVERSE_LIST
)
208 # This class handles groupchats with the legacy protocol
209 class LegacyGroupchat ( groupchat
. BaseGroupchat
):
210 def __init__ ( self
, session
, resource
= None , ID
= None , switchboardSession
= None ):
211 """ Possible entry points for groupchat
212 - User starts an empty switchboard session by sending presence to a blank room
213 - An existing switchboard session is joined by another MSN user
214 - User invited to an existing switchboard session with more than one user
216 groupchat
. BaseGroupchat
.__ init
__ ( self
, session
, resource
, ID
)
217 if switchboardSession
:
218 self
. switchboardSession
= switchboardSession
220 self
. switchboardSession
= msn
. MultiSwitchboardSession ( self
. session
. legacycon
)
221 self
. switchboardSession
. groupchat
= self
223 LogEvent ( INFO
, self
. roomJID ())
226 if self
. switchboardSession
. transport
:
227 self
. switchboardSession
. transport
. loseConnection ()
228 self
. switchboardSession
. groupchat
= None
229 del self
. switchboardSession
230 groupchat
. BaseGroupchat
. removeMe ( self
)
231 LogEvent ( INFO
, self
. roomJID ())
233 def sendLegacyMessage ( self
, message
, noerror
):
234 LogEvent ( INFO
, self
. roomJID ())
235 self
. switchboardSession
. sendMessage ( message
. replace ( " \n " , " \r\n " ), noerror
)
237 def sendContactInvite ( self
, contactJID
):
238 LogEvent ( INFO
, self
. roomJID ())
239 userHandle
= jid2msn ( contactJID
)
240 self
. switchboardSession
. inviteUser ( userHandle
)
242 def gotMessage ( self
, userHandle
, text
):
243 LogEvent ( INFO
, self
. roomJID ())
244 self
. messageReceived ( userHandle
, text
)
248 # This class handles most interaction with the legacy protocol
249 class LegacyConnection ( msn
. MSNConnection
):
250 """ A glue class that connects to the legacy network """
251 def __init__ ( self
, username
, password
, session
):
252 self
. jabberID
= session
. jabberID
254 self
. session
= session
255 self
. listSynced
= False
256 self
. initialListVersion
= 0
259 self
. remoteStatus
= ""
263 msn
. MSNConnection
.__ init
__ ( self
, username
, password
, self
. jabberID
)
265 # User typing notification stuff
266 self
. userTyping
= dict () # Indexed by contact MSN ID, stores whether the user is typing to this contact
267 # Contact typing notification stuff
268 self
. contactTyping
= dict () # Indexed by contact MSN ID, stores an integer that is incremented at 5 second intervals. If it reaches 3 then the contact has stopped typing. It is set to zero whenever MSN typing notification messages are received
270 self
. userTypingSend
= task
. LoopingCall ( self
. sendTypingNotifications
)
271 self
. userTypingSend
. start ( 5.0 )
273 self
. legacyList
= LegacyList ( self
. session
)
275 LogEvent ( INFO
, self
. jabberID
)
278 LogEvent ( INFO
, self
. jabberID
)
280 self
. userTypingSend
. stop ()
282 self
. legacyList
. removeMe ()
283 self
. legacyList
= None
288 # Implemented from baseproto
289 def sendShowStatus ( self
, jid
= None ):
290 if not self
. session
: return
294 self
. session
. sendPresence ( to
= jid
, fro
= source
, show
= self
. remoteShow
, status
= self
. remoteStatus
, nickname
= self
. remoteNick
)
296 def resourceOffline ( self
, resource
):
299 def highestResource ( self
):
300 """ Returns highest priority resource """
301 return self
. session
. highestResource ()
303 def sendMessage ( self
, dest
, resource
, body
, noerror
):
305 if self
. userTyping
. has_key ( dest
):
306 del self
. userTyping
[ dest
]
308 msn
. MSNConnection
. sendMessage ( self
, dest
, body
, noerror
)
309 self
. session
. pytrans
. statistics
. stats
[ "MessageCount" ] += 1
311 self
. failedMessage ( dest
, body
)
314 def sendFile ( self
, dest
, ftSend
):
316 def continueSendFile1 (( msnFileSend
, d
)):
317 def continueSendFile2 (( success
, )):
319 ftSend
. accept ( msnFileSend
)
322 d
. addCallbacks ( continueSendFile2
, sendFileFail
)
327 d
= msn
. MSNConnection
. sendFile ( self
, dest
, ftSend
. filename
, ftSend
. filesize
)
328 d
. addCallbacks ( continueSendFile1
, sendFileFail
)
330 def setStatus ( self
, nickname
, show
, status
):
331 statusCode
= presence2state ( show
, None )
332 msn
. MSNConnection
. changeStatus ( self
, statusCode
, nickname
, status
)
334 def updateAvatar ( self
, av
= None ):
335 global defaultJabberAvatarData
338 msn
. MSNConnection
. changeAvatar ( self
, av
. getImageData ())
340 msn
. MSNConnection
. changeAvatar ( self
, defaultJabberAvatarData
)
342 def sendTypingNotifications ( self
):
343 if not self
. session
: return
345 # Send any typing notification messages to the user's contacts
346 for contact
in self
. userTyping
. keys ():
347 if self
. userTyping
[ contact
]:
348 self
. sendTypingToContact ( contact
)
350 # Send any typing notification messages from contacts to the user
351 for contact
in self
. contactTyping
. keys ():
352 self
. contactTyping
[ contact
] += 1
353 if self
. contactTyping
[ contact
] >= 3 :
354 self
. session
. sendTypingNotification ( self
. jabberID
, msn2jid ( contact
, True ), False )
355 del self
. contactTyping
[ contact
]
357 def userTypingNotification ( self
, dest
, resource
, composing
):
358 if not self
. session
: return
360 self
. userTyping
[ dest
] = composing
361 if composing
: # Make it instant
362 self
. sendTypingToContact ( dest
)
366 # Implement callbacks from msn.MSNConnection
367 def connectionFailed ( self
, reason
):
368 LogEvent ( INFO
, self
. jabberID
)
369 text
= lang
. get ( self
. session
. lang
). msnConnectFailed
% reason
370 self
. session
. sendMessage ( to
= self
. jabberID
, fro
= config
. jid
, body
= text
)
371 self
. session
. removeMe ()
373 def loginFailed ( self
, reason
):
374 LogEvent ( INFO
, self
. jabberID
)
375 text
= lang
. get ( self
. session
. lang
). msnLoginFailure
% ( self
. session
. username
)
376 self
. session
. sendErrorMessage ( to
= self
. jabberID
, fro
= config
. jid
, etype
= "auth" , condition
= "not-authorized" , explanation
= text
, body
= "Login Failure" )
377 self
. session
. removeMe ()
379 def connectionLost ( self
, reason
):
380 LogEvent ( INFO
, self
. jabberID
)
381 text
= lang
. get ( self
. session
. lang
). msnDisconnected
% reason
382 self
. session
. sendMessage ( to
= self
. jabberID
, fro
= config
. jid
, body
= text
)
383 self
. session
. removeMe () # Tear down the session
385 def multipleLogin ( self
):
386 LogEvent ( INFO
, self
. jabberID
)
387 self
. session
. sendMessage ( to
= self
. jabberID
, fro
= config
. jid
, body
= lang
. get ( self
. session
. lang
). msnMultipleLogin
)
388 self
. session
. removeMe ()
390 def serverGoingDown ( self
):
391 LogEvent ( INFO
, self
. jabberID
)
392 self
. session
. sendMessage ( to
= self
. jabberID
, fro
= config
. jid
, body
= lang
. get ( self
. session
. lang
). msnMaintenance
)
394 def accountNotVerified ( self
):
395 LogEvent ( INFO
, self
. jabberID
)
396 text
= lang
. get ( self
. session
. lang
). msnNotVerified
% ( self
. session
. username
)
397 self
. session
. sendMessage ( to
= self
. jabberID
, fro
= config
. jid
, body
= text
)
399 def userMapping ( self
, passport
, jid
):
400 LogEvent ( INFO
, self
. jabberID
)
401 text
= lang
. get ( self
. session
. lang
). userMapping
% ( passport
, jid
)
402 self
. session
. sendMessage ( to
= self
. jabberID
, fro
= msn2jid ( passport
, True ), body
= text
)
405 LogEvent ( INFO
, self
. jabberID
)
406 self
. session
. ready
= True
408 def listSynchronized ( self
):
409 LogEvent ( INFO
, self
. jabberID
)
410 self
. session
. sendPresence ( to
= self
. jabberID
, fro
= config
. jid
)
411 self
. legacyList
. syncJabberLegacyLists ()
412 self
. listSynced
= True
413 #self.legacyList.flushSubscriptionBuffer()
415 def ourStatusChanged ( self
, statusCode
, screenName
, personal
):
416 # Send out a new presence packet to the Jabber user so that the transport icon changes
417 LogEvent ( INFO
, self
. jabberID
)
418 self
. remoteShow
, ptype
= state2presence ( statusCode
)
419 self
. remoteStatus
= personal
420 self
. remoteNick
= screenName
421 self
. sendShowStatus ()
423 def gotMessage ( self
, remoteUser
, text
):
424 LogEvent ( INFO
, self
. jabberID
)
425 source
= msn2jid ( remoteUser
, True )
426 if self
. contactTyping
. has_key ( remoteUser
):
427 del self
. contactTyping
[ remoteUser
]
428 self
. session
. sendMessage ( self
. jabberID
, fro
= source
, body
= text
, mtype
= "chat" )
429 self
. session
. pytrans
. statistics
. stats
[ "MessageCount" ] += 1
431 def gotGroupchat ( self
, msnGroupchat
, userHandle
):
432 LogEvent ( INFO
, self
. jabberID
)
433 msnGroupchat
. groupchat
= LegacyGroupchat ( self
. session
, switchboardSession
= msnGroupchat
)
434 msnGroupchat
. groupchat
. sendUserInvite ( msn2jid ( userHandle
, True ))
436 def gotContactTyping ( self
, contact
):
437 LogEvent ( INFO
, self
. jabberID
)
438 # Check if the contact has only just started typing
439 if not self
. contactTyping
. has_key ( contact
):
440 self
. session
. sendTypingNotification ( self
. jabberID
, msn2jid ( contact
, True ), True )
443 self
. contactTyping
[ contact
] = 0
445 def failedMessage ( self
, remoteUser
, message
):
446 LogEvent ( INFO
, self
. jabberID
)
447 self
. session
. pytrans
. statistics
. stats
[ "FailedMessageCount" ] += 1
448 fro
= msn2jid ( remoteUser
, True )
449 self
. session
. sendErrorMessage ( to
= self
. jabberID
, fro
= fro
, etype
= "wait" , condition
= "recipient-unavailable" , explanation
= lang
. get ( self
. session
. lang
). msnFailedMessage
, body
= message
)
451 def contactAvatarChanged ( self
, userHandle
, hash ):
452 LogEvent ( INFO
, self
. jabberID
)
453 jid
= msn2jid ( userHandle
, False )
454 c
= self
. session
. contactList
. findContact ( jid
)
459 av
= self
. session
. pytrans
. avatarCache
. getAvatar ( hash )
461 msnContact
= self
. getContacts (). getContact ( userHandle
)
462 msnContact
. msnobjGot
= True
465 def updateAvatarCB (( imageData
,)):
466 av
= self
. session
. pytrans
. avatarCache
. setAvatar ( imageData
)
468 d
= self
. sendAvatarRequest ( userHandle
)
470 d
. addCallback ( updateAvatarCB
)
472 # They've turned off their avatar
474 c
. updateAvatar ( defaultAvatar
)
476 def contactStatusChanged ( self
, remoteUser
):
477 LogEvent ( INFO
, self
. jabberID
)
479 msnContact
= self
. getContacts (). getContact ( remoteUser
)
480 c
= self
. session
. contactList
. findContact ( msn2jid ( remoteUser
, False ))
481 if not ( c
and msnContact
): return
483 show
, ptype
= state2presence ( msnContact
. status
)
484 status
= msnContact
. personal
. decode ( "utf-8" )
485 screenName
= msnContact
. screenName
. decode ( "utf-8" )
487 c
. updateNickname ( screenName
, push
= False )
488 c
. updatePresence ( show
, status
, ptype
, force
= True )
490 def gotFileReceive ( self
, fileReceive
):
491 LogEvent ( INFO
, self
. jabberID
)
493 ft
. FTReceive ( self
. session
, msn2jid ( fileReceive
. userHandle
, True ), fileReceive
)
495 def contactAddedMe ( self
, userHandle
):
496 LogEvent ( INFO
, self
. jabberID
)
497 self
. session
. contactList
. getContact ( msn2jid ( userHandle
, False )). contactRequestsAuth ()
499 def contactRemovedMe ( self
, userHandle
):
500 LogEvent ( INFO
, self
. jabberID
)
501 c
= self
. session
. contactList
. getContact ( msn2jid ( userHandle
, True ))
502 c
. contactDerequestsAuth ()
503 c
. contactRemovesAuth ()
505 def gotInitialEmailNotification ( self
, inboxunread
, foldersunread
):
506 if config
. mailNotifications
:
507 LogEvent ( INFO
, self
. jabberID
)
508 text
= lang
. get ( self
. session
. lang
). msnInitialMail
% ( inboxunread
, foldersunread
)
509 self
. session
. sendMessage ( to
= self
. jabberID
, fro
= config
. jid
, body
= text
, mtype
= "headline" )
511 def gotRealtimeEmailNotification ( self
, mailfrom
, fromaddr
, subject
):
512 if config
. mailNotifications
:
513 LogEvent ( INFO
, self
. jabberID
)
514 text
= lang
. get ( self
. session
. lang
). msnRealtimeMail
% ( mailfrom
, fromaddr
, subject
)
515 self
. session
. sendMessage ( to
= self
. jabberID
, fro
= config
. jid
, body
= text
, mtype
= "headline" )
517 def gotMSNAlert ( self
, text
, actionurl
, subscrurl
):
518 LogEvent ( INFO
, self
. jabberID
)
520 el
= Element (( None , "message" ))
521 el
. attributes
[ "to" ] = self
. jabberID
522 el
. attributes
[ "from" ] = config
. jid
523 el
. attributes
[ "type" ] = "headline"
524 body
= el
. addElement ( "body" )
525 body
. addContent ( text
)
527 x
= el
. addElement ( "x" )
528 x
. attributes
[ "xmlns" ] = "jabber:x:oob"
529 x
. addElement ( "desc" ). addContent ( "More information on this notice." )
530 x
. addElement ( "url" ). addContent ( actionurl
)
532 x
= el
. addElement ( "x" )
533 x
. attributes
[ "xmlns" ] = "jabber:x:oob"
534 x
. addElement ( "desc" ). addContent ( "Manage subscriptions to alerts." )
535 x
. addElement ( "url" ). addContent ( subscrurl
)
537 self
. session
. pytrans
. send ( el
)
539 def gotAvatarImageData ( self
, userHandle
, imageData
):
540 LogEvent ( INFO
, self
. jabberID
)
541 av
= self
. session
. pytrans
. avatarCache
. setAvatar ( imageData
)
542 jid
= msn2jid ( userHandle
, False )
543 c
= self
. session
. contactList
. findContact ( jid
)
550 def __init__ ( self
, session
):
551 self
. jabberID
= session
. jabberID
552 self
. session
= session
553 self
. subscriptionBuffer
= []
556 self
. subscriptionBuffer
= None
559 def addContact ( self
, jid
):
560 LogEvent ( INFO
, self
. jabberID
)
561 userHandle
= jid2msn ( jid
)
562 self
. session
. legacycon
. addContact ( msn
. FORWARD_LIST
, userHandle
)
564 # Handle adding a contact that has previously been removed
565 msnContact
= self
. session
. legacycon
. getContacts (). getContact ( userHandle
)
566 if msnContact
. lists
& msn
. REVERSE_LIST
:
567 self
. session
. legacycon
. contactAddedMe ( userHandle
)
568 self
. authContact ( jid
)
569 self
. session
. contactList
. getContact ( jid
). contactGrantsAuth ()
571 def removeContact ( self
, jid
):
572 LogEvent ( INFO
, self
. jabberID
)
574 self
. session
. legacycon
. remContact ( msn
. FORWARD_LIST
, jid
)
577 def authContact ( self
, jid
):
578 LogEvent ( INFO
, self
. jabberID
)
579 userHandle
= jid2msn ( jid
)
580 d
= self
. session
. legacycon
. remContact ( msn
. PENDING_LIST
, userHandle
)
582 self
. session
. legacycon
. addContact ( msn
. REVERSE_LIST
, userHandle
)
583 self
. session
. legacycon
. remContact ( msn
. BLOCK_LIST
, userHandle
)
584 self
. session
. legacycon
. addContact ( msn
. ALLOW_LIST
, userHandle
)
586 def deauthContact ( self
, jid
):
587 LogEvent ( INFO
, self
. jabberID
)
589 self
. session
. legacycon
. remContact ( msn
. ALLOW_LIST
, jid
)
590 self
. session
. legacycon
. remContact ( msn
. PENDING_LIST
, jid
)
591 self
. session
. legacycon
. addContact ( msn
. BLOCK_LIST
, jid
)
595 def syncJabberLegacyLists ( self
):
596 """ Synchronises the MSN contact list on server with the Jabber contact list """
600 # We have to make an MSNContactList from the XDB data, then compare it with the one the server sent
601 # Any subscription changes must be sent to the client, as well as changed in the XDB
602 LogEvent ( INFO
, self
. jabberID
, "Start." )
603 result
= self
. session
. pytrans
. xdb
. request ( self
. jabberID
, disco
. IQROSTER
)
604 oldContactList
= msn
. MSNContactList ()
606 for item
in result
. elements ():
607 user
= item
. getAttribute ( "jid" )
608 sub
= item
. getAttribute ( "subscription" )
609 lists
= item
. getAttribute ( "lists" )
611 lists
= jabsub2msnlist ( sub
) # Backwards compatible
613 contact
= msn
. MSNContact ( userHandle
= user
, screenName
= "" , lists
= lists
)
614 oldContactList
. addContact ( contact
)
616 newXDB
= Element (( None , "query" ))
617 newXDB
. attributes
[ "xmlns" ] = disco
. IQROSTER
619 contactList
= self
. session
. legacycon
. getContacts ()
622 # Convienence functions
623 def addedToList ( num
):
624 return ( not ( oldLists
& num
) and ( lists
& num
))
625 def removedFromList ( num
):
626 return (( oldLists
& num
) and not ( lists
& num
))
628 for contact
in contactList
. contacts
. values ():
629 # Compare with the XDB <item/> entry
630 oldContact
= oldContactList
. getContact ( contact
. userHandle
)
631 if oldContact
== None :
634 oldLists
= oldContact
. lists
635 lists
= contact
. lists
637 # Create the Jabber representation of the
638 # contact base on the old list data and then
639 # sync it with current
640 jabContact
= self
. session
. contactList
. createContact ( msn2jid ( contact
. userHandle
, False ), msnlist2jabsub ( oldLists
))
641 jabContact
. updateAvatar ( defaultAvatar
, push
= False )
643 if addedToList ( msn
. FORWARD_LIST
):
644 jabContact
. syncGroups ( getGroupNames ( contact
, contactList
), push
= False )
645 jabContact
. syncContactGrantedAuth ()
647 if removedFromList ( msn
. FORWARD_LIST
):
648 jabContact
. syncContactRemovedAuth ()
650 if addedToList ( msn
. ALLOW_LIST
):
651 jabContact
. syncUserGrantedAuth ()
653 if addedToList ( msn
. BLOCK_LIST
) or removedFromList ( msn
. ALLOW_LIST
):
654 jabContact
. syncUserRemovedAuth ()
656 if ( not ( lists
& msn
. ALLOW_LIST
) and not ( lists
& msn
. BLOCK_LIST
) and ( lists
& msn
. REVERSE_LIST
)) or ( lists
& msn
. PENDING_LIST
):
657 jabContact
. contactRequestsAuth ()
659 if removedFromList ( msn
. REVERSE_LIST
):
660 jabContact
. contactDerequestsAuth ()
662 jabContact
. syncRoster ()
664 item
= newXDB
. addElement ( "item" )
665 item
. attributes
[ "jid" ] = contact
. userHandle
666 item
. attributes
[ "subscription" ] = msnlist2jabsub ( lists
)
667 item
. attributes
[ "lists" ] = str ( lists
)
670 self
. session
. pytrans
. xdb
. set ( self
. jabberID
, disco
. IQROSTER
, newXDB
)
671 LogEvent ( INFO
, self
. jabberID
, "End." )
673 def saveLegacyList ( self
):
674 contactList
= self
. session
. legacycon
. getContacts ()
675 if not contactList
: return
677 newXDB
= Element (( None , "query" ))
678 newXDB
. attributes
[ "xmlns" ] = disco
. IQROSTER
680 for contact
in contactList
. contacts
. values ():
681 item
= newXDB
. addElement ( "item" )
682 item
. attributes
[ "jid" ] = contact
. userHandle
683 item
. attributes
[ "subscription" ] = msnlist2jabsub ( contact
. lists
) # Backwards compat
684 item
. attributes
[ "lists" ] = str ( contact
. lists
)
686 self
. session
. pytrans
. xdb
. set ( self
. jabberID
, disco
. IQROSTER
, newXDB
)
687 LogEvent ( INFO
, self
. jabberID
, "Finished saving list." )