]>
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
, error
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 if reason
. type != error
. ConnectionDone
:
382 text
= lang
. get ( self
. session
. lang
). msnDisconnected
% reason
383 self
. session
. sendMessage ( to
= self
. jabberID
, fro
= config
. jid
, body
= text
)
384 self
. session
. removeMe () # Tear down the session
386 def multipleLogin ( self
):
387 LogEvent ( INFO
, self
. jabberID
)
388 self
. session
. sendMessage ( to
= self
. jabberID
, fro
= config
. jid
, body
= lang
. get ( self
. session
. lang
). msnMultipleLogin
)
389 self
. session
. removeMe ()
391 def serverGoingDown ( self
):
392 LogEvent ( INFO
, self
. jabberID
)
393 self
. session
. sendMessage ( to
= self
. jabberID
, fro
= config
. jid
, body
= lang
. get ( self
. session
. lang
). msnMaintenance
)
395 def accountNotVerified ( self
):
396 LogEvent ( INFO
, self
. jabberID
)
397 text
= lang
. get ( self
. session
. lang
). msnNotVerified
% ( self
. session
. username
)
398 self
. session
. sendMessage ( to
= self
. jabberID
, fro
= config
. jid
, body
= text
)
400 def userMapping ( self
, passport
, jid
):
401 LogEvent ( INFO
, self
. jabberID
)
402 text
= lang
. get ( self
. session
. lang
). userMapping
% ( passport
, jid
)
403 self
. session
. sendMessage ( to
= self
. jabberID
, fro
= msn2jid ( passport
, True ), body
= text
)
406 LogEvent ( INFO
, self
. jabberID
)
407 self
. session
. ready
= True
409 def listSynchronized ( self
):
410 LogEvent ( INFO
, self
. jabberID
)
411 self
. session
. sendPresence ( to
= self
. jabberID
, fro
= config
. jid
)
412 self
. legacyList
. syncJabberLegacyLists ()
413 self
. listSynced
= True
414 #self.legacyList.flushSubscriptionBuffer()
416 def ourStatusChanged ( self
, statusCode
, screenName
, personal
):
417 # Send out a new presence packet to the Jabber user so that the transport icon changes
418 LogEvent ( INFO
, self
. jabberID
)
419 self
. remoteShow
, ptype
= state2presence ( statusCode
)
420 self
. remoteStatus
= personal
421 self
. remoteNick
= screenName
422 self
. sendShowStatus ()
424 def gotMessage ( self
, remoteUser
, text
):
425 LogEvent ( INFO
, self
. jabberID
)
426 source
= msn2jid ( remoteUser
, True )
427 if self
. contactTyping
. has_key ( remoteUser
):
428 del self
. contactTyping
[ remoteUser
]
429 self
. session
. sendMessage ( self
. jabberID
, fro
= source
, body
= text
, mtype
= "chat" )
430 self
. session
. pytrans
. statistics
. stats
[ "MessageCount" ] += 1
432 def gotGroupchat ( self
, msnGroupchat
, userHandle
):
433 LogEvent ( INFO
, self
. jabberID
)
434 msnGroupchat
. groupchat
= LegacyGroupchat ( self
. session
, switchboardSession
= msnGroupchat
)
435 msnGroupchat
. groupchat
. sendUserInvite ( msn2jid ( userHandle
, True ))
437 def gotContactTyping ( self
, contact
):
438 LogEvent ( INFO
, self
. jabberID
)
439 # Check if the contact has only just started typing
440 if not self
. contactTyping
. has_key ( contact
):
441 self
. session
. sendTypingNotification ( self
. jabberID
, msn2jid ( contact
, True ), True )
444 self
. contactTyping
[ contact
] = 0
446 def failedMessage ( self
, remoteUser
, message
):
447 LogEvent ( INFO
, self
. jabberID
)
448 self
. session
. pytrans
. statistics
. stats
[ "FailedMessageCount" ] += 1
449 fro
= msn2jid ( remoteUser
, True )
450 self
. session
. sendErrorMessage ( to
= self
. jabberID
, fro
= fro
, etype
= "wait" , condition
= "recipient-unavailable" , explanation
= lang
. get ( self
. session
. lang
). msnFailedMessage
, body
= message
)
452 def contactAvatarChanged ( self
, userHandle
, hash ):
453 LogEvent ( INFO
, self
. jabberID
)
454 jid
= msn2jid ( userHandle
, False )
455 c
= self
. session
. contactList
. findContact ( jid
)
460 av
= self
. session
. pytrans
. avatarCache
. getAvatar ( hash )
462 msnContact
= self
. getContacts (). getContact ( userHandle
)
463 msnContact
. msnobjGot
= True
466 def updateAvatarCB (( imageData
,)):
467 av
= self
. session
. pytrans
. avatarCache
. setAvatar ( imageData
)
469 d
= self
. sendAvatarRequest ( userHandle
)
471 d
. addCallback ( updateAvatarCB
)
473 # They've turned off their avatar
475 c
. updateAvatar ( defaultAvatar
)
477 def contactStatusChanged ( self
, remoteUser
):
478 LogEvent ( INFO
, self
. jabberID
)
480 msnContact
= self
. getContacts (). getContact ( remoteUser
)
481 c
= self
. session
. contactList
. findContact ( msn2jid ( remoteUser
, False ))
482 if not ( c
and msnContact
): return
484 show
, ptype
= state2presence ( msnContact
. status
)
485 status
= msnContact
. personal
. decode ( "utf-8" )
486 screenName
= msnContact
. screenName
. decode ( "utf-8" )
488 c
. updateNickname ( screenName
, push
= False )
489 c
. updatePresence ( show
, status
, ptype
, force
= True )
491 def gotFileReceive ( self
, fileReceive
):
492 LogEvent ( INFO
, self
. jabberID
)
494 ft
. FTReceive ( self
. session
, msn2jid ( fileReceive
. userHandle
, True ), fileReceive
)
496 def contactAddedMe ( self
, userHandle
):
497 LogEvent ( INFO
, self
. jabberID
)
498 self
. session
. contactList
. getContact ( msn2jid ( userHandle
, False )). contactRequestsAuth ()
500 def contactRemovedMe ( self
, userHandle
):
501 LogEvent ( INFO
, self
. jabberID
)
502 c
= self
. session
. contactList
. getContact ( msn2jid ( userHandle
, True ))
503 c
. contactDerequestsAuth ()
504 c
. contactRemovesAuth ()
506 def gotInitialEmailNotification ( self
, inboxunread
, foldersunread
):
507 if config
. mailNotifications
:
508 LogEvent ( INFO
, self
. jabberID
)
509 text
= lang
. get ( self
. session
. lang
). msnInitialMail
% ( inboxunread
, foldersunread
)
510 self
. session
. sendMessage ( to
= self
. jabberID
, fro
= config
. jid
, body
= text
, mtype
= "headline" )
512 def gotRealtimeEmailNotification ( self
, mailfrom
, fromaddr
, subject
):
513 if config
. mailNotifications
:
514 LogEvent ( INFO
, self
. jabberID
)
515 text
= lang
. get ( self
. session
. lang
). msnRealtimeMail
% ( mailfrom
, fromaddr
, subject
)
516 self
. session
. sendMessage ( to
= self
. jabberID
, fro
= config
. jid
, body
= text
, mtype
= "headline" )
518 def gotMSNAlert ( self
, text
, actionurl
, subscrurl
):
519 LogEvent ( INFO
, self
. jabberID
)
521 el
= Element (( None , "message" ))
522 el
. attributes
[ "to" ] = self
. jabberID
523 el
. attributes
[ "from" ] = config
. jid
524 el
. attributes
[ "type" ] = "headline"
525 body
= el
. addElement ( "body" )
526 body
. addContent ( text
)
528 x
= el
. addElement ( "x" )
529 x
. attributes
[ "xmlns" ] = "jabber:x:oob"
530 x
. addElement ( "desc" ). addContent ( "More information on this notice." )
531 x
. addElement ( "url" ). addContent ( actionurl
)
533 x
= el
. addElement ( "x" )
534 x
. attributes
[ "xmlns" ] = "jabber:x:oob"
535 x
. addElement ( "desc" ). addContent ( "Manage subscriptions to alerts." )
536 x
. addElement ( "url" ). addContent ( subscrurl
)
538 self
. session
. pytrans
. send ( el
)
540 def gotAvatarImageData ( self
, userHandle
, imageData
):
541 LogEvent ( INFO
, self
. jabberID
)
542 av
= self
. session
. pytrans
. avatarCache
. setAvatar ( imageData
)
543 jid
= msn2jid ( userHandle
, False )
544 c
= self
. session
. contactList
. findContact ( jid
)
551 def __init__ ( self
, session
):
552 self
. jabberID
= session
. jabberID
553 self
. session
= session
558 def addContact ( self
, jid
):
559 LogEvent ( INFO
, self
. jabberID
)
560 userHandle
= jid2msn ( jid
)
561 self
. session
. legacycon
. addContact ( msn
. FORWARD_LIST
, userHandle
)
563 # Handle adding a contact that has previously been removed
564 msnContact
= self
. session
. legacycon
. getContacts (). getContact ( userHandle
)
565 if msnContact
and msnContact
. lists
& msn
. REVERSE_LIST
:
566 self
. session
. legacycon
. contactAddedMe ( userHandle
)
567 self
. authContact ( jid
)
568 self
. session
. contactList
. getContact ( jid
). contactGrantsAuth ()
570 def removeContact ( self
, jid
):
571 LogEvent ( INFO
, self
. jabberID
)
573 self
. session
. legacycon
. remContact ( msn
. FORWARD_LIST
, jid
)
576 def authContact ( self
, jid
):
577 LogEvent ( INFO
, self
. jabberID
)
578 userHandle
= jid2msn ( jid
)
579 d
= self
. session
. legacycon
. remContact ( msn
. PENDING_LIST
, userHandle
)
581 self
. session
. legacycon
. addContact ( msn
. REVERSE_LIST
, userHandle
)
582 self
. session
. legacycon
. remContact ( msn
. BLOCK_LIST
, userHandle
)
583 self
. session
. legacycon
. addContact ( msn
. ALLOW_LIST
, userHandle
)
585 def deauthContact ( self
, jid
):
586 LogEvent ( INFO
, self
. jabberID
)
588 self
. session
. legacycon
. remContact ( msn
. ALLOW_LIST
, jid
)
589 self
. session
. legacycon
. remContact ( msn
. PENDING_LIST
, jid
)
590 self
. session
. legacycon
. addContact ( msn
. BLOCK_LIST
, jid
)
594 def syncJabberLegacyLists ( self
):
595 """ Synchronises the MSN contact list on server with the Jabber contact list """
599 # We have to make an MSNContactList from the XDB data, then compare it with the one the server sent
600 # Any subscription changes must be sent to the client, as well as changed in the XDB
601 LogEvent ( INFO
, self
. jabberID
, "Start." )
602 result
= self
. session
. pytrans
. xdb
. request ( self
. jabberID
, disco
. IQROSTER
)
603 oldContactList
= msn
. MSNContactList ()
605 for item
in result
. elements ():
606 user
= item
. getAttribute ( "jid" )
607 sub
= item
. getAttribute ( "subscription" )
608 lists
= item
. getAttribute ( "lists" )
610 lists
= jabsub2msnlist ( sub
) # Backwards compatible
612 contact
= msn
. MSNContact ( userHandle
= user
, screenName
= "" , lists
= lists
)
613 oldContactList
. addContact ( contact
)
615 newXDB
= Element (( None , "query" ))
616 newXDB
. attributes
[ "xmlns" ] = disco
. IQROSTER
618 contactList
= self
. session
. legacycon
. getContacts ()
621 # Convienence functions
622 def addedToList ( num
):
623 return ( not ( oldLists
& num
) and ( lists
& num
))
624 def removedFromList ( num
):
625 return (( oldLists
& num
) and not ( lists
& num
))
627 for contact
in contactList
. contacts
. values ():
628 # Compare with the XDB <item/> entry
629 oldContact
= oldContactList
. getContact ( contact
. userHandle
)
630 if oldContact
== None :
633 oldLists
= oldContact
. lists
634 lists
= contact
. lists
636 # Create the Jabber representation of the
637 # contact base on the old list data and then
638 # sync it with current
639 jabContact
= self
. session
. contactList
. createContact ( msn2jid ( contact
. userHandle
, False ), msnlist2jabsub ( oldLists
))
640 jabContact
. updateAvatar ( defaultAvatar
, push
= False )
642 if addedToList ( msn
. FORWARD_LIST
):
643 jabContact
. syncGroups ( getGroupNames ( contact
, contactList
), push
= False )
644 jabContact
. syncContactGrantedAuth ()
646 if removedFromList ( msn
. FORWARD_LIST
):
647 jabContact
. syncContactRemovedAuth ()
649 if addedToList ( msn
. ALLOW_LIST
):
650 jabContact
. syncUserGrantedAuth ()
652 if addedToList ( msn
. BLOCK_LIST
) or removedFromList ( msn
. ALLOW_LIST
):
653 jabContact
. syncUserRemovedAuth ()
655 if ( not ( lists
& msn
. ALLOW_LIST
) and not ( lists
& msn
. BLOCK_LIST
) and ( lists
& msn
. REVERSE_LIST
)) or ( lists
& msn
. PENDING_LIST
):
656 jabContact
. contactRequestsAuth ()
658 if removedFromList ( msn
. REVERSE_LIST
):
659 jabContact
. contactDerequestsAuth ()
661 jabContact
. syncRoster ()
663 item
= newXDB
. addElement ( "item" )
664 item
. attributes
[ "jid" ] = contact
. userHandle
665 item
. attributes
[ "subscription" ] = msnlist2jabsub ( lists
)
666 item
. attributes
[ "lists" ] = str ( lists
)
669 self
. session
. pytrans
. xdb
. set ( self
. jabberID
, disco
. IQROSTER
, newXDB
)
670 LogEvent ( INFO
, self
. jabberID
, "End." )
672 def saveLegacyList ( self
):
673 contactList
= self
. session
. legacycon
. getContacts ()
674 if not contactList
: return
676 newXDB
= Element (( None , "query" ))
677 newXDB
. attributes
[ "xmlns" ] = disco
. IQROSTER
679 for contact
in contactList
. contacts
. values ():
680 item
= newXDB
. addElement ( "item" )
681 item
. attributes
[ "jid" ] = contact
. userHandle
682 item
. attributes
[ "subscription" ] = msnlist2jabsub ( contact
. lists
) # Backwards compat
683 item
. attributes
[ "lists" ] = str ( contact
. lists
)
685 self
. session
. pytrans
. xdb
. set ( self
. jabberID
, disco
. IQROSTER
, newXDB
)
686 LogEvent ( INFO
, self
. jabberID
, "Finished saving list." )