]>
code.delx.au - pymsnt/blob - src/session.py
1 # Copyright 2004-2005 James Bunton <james@delx.cjb.net>
2 # Licensed for distribution under the GPL version 2, check COPYING for details
4 from tlib
. xmlw
import jid
14 from debug
import LogEvent
, INFO
, WARN
, ERROR
18 def makeSession ( pytrans
, jabberID
, ulang
):
19 """ Tries to create a session object for the corresponding JabberID. Retrieves information
20 from XDB to create the session. If it fails, then the user is most likely not registered with
22 LogEvent ( INFO
, jabberID
)
23 if pytrans
. sessions
. has_key ( jabberID
):
24 LogEvent ( INFO
, jabberID
, "Removing existing session." )
25 pytrans
. sessions
[ jabberID
]. removeMe ()
26 result
= pytrans
. registermanager
. getRegInfo ( jabberID
)
28 username
, password
= result
29 return Session ( pytrans
, jabberID
, username
, password
, ulang
)
35 class Session ( jabw
. JabberConnection
):
36 """ A class to represent each registered user's session with the legacy network. Exists as long as there
37 is a Jabber resource for the user available """
39 def __init__ ( self
, pytrans
, jabberID
, username
, password
, ulang
):
40 """ Initialises the session object and connects to the legacy network """
41 jabw
. JabberConnection
.__ init
__ ( self
, pytrans
, jabberID
)
42 LogEvent ( INFO
, jabberID
)
44 self
. pytrans
= pytrans
46 self
. ready
= False # Only ready when we're logged into the legacy service
47 self
. jabberID
= jabberID
# the JabberID of the Session's user
48 self
. username
= username
# the legacy network ID of the Session's user
49 self
. password
= password
57 self
. resourceList
= {}
60 self
. legacycon
= legacy
. LegacyConnection ( self
. username
, self
. password
, self
)
61 self
. contactList
= contact
. ContactList ( self
)
62 self
. contactList
. legacyList
= self
. legacycon
. legacyList
64 if config
. sessionGreeting
:
65 self
. sendMessage ( to
= self
. jabberID
, fro
= config
. jid
, body
= config
. sessionGreeting
)
67 self
. updateNickname ( "" )
69 LogEvent ( INFO
, self
. jabberID
, "Created!" )
72 """ Safely removes the session object, including sending <presence type="unavailable"/> messages for each legacy related item on the user's contact list """
73 # Send offline presence to Jabber ID
74 # Delete all objects cleanly
75 # Remove this Session object from the pytrans
77 LogEvent ( INFO
, self
. jabberID
)
83 # Send offline presence to the user
85 self
. sendPresence ( to
= self
. jabberID
, fro
= config
. jid
, ptype
= "unavailable" )
87 # Clean up stuff on the legacy service end (including sending offline presences for all contacts)
89 self
. legacycon
. removeMe ()
93 self
. contactList
. removeMe ()
94 self
. contactList
= None
96 # Remove any groupchats we may be in
97 for groupchat
in self
. groupchats
[:]:
101 # Remove us from the session list
102 del self
. pytrans
. sessions
[ self
. jabberID
]
103 # Clean up the no longer needed reference
106 LogEvent ( INFO
, self
. jabberID
, "Removed!" )
108 def doVCardUpdate ( self
):
109 def vCardReceived ( el
):
110 if not self
. alive
: return
111 LogEvent ( INFO
, self
. jabberID
)
113 for e
in el
. elements ():
114 if e
. name
== "vCard" and e
. defaultUri
== disco
. VCARDTEMP
:
118 self
. legacycon
. updateAvatar () # Default avatar
121 for e
in vCard
. elements ():
122 if e
. name
== "NICKNAME" :
123 self
. updateNickname ( e
.__ str
__ ())
124 if e
. name
== "PHOTO" :
125 imageData
= avatar
. parsePhotoEl ( e
)
127 errback () # Possibly it wasn't in a supported format?
128 self
. avatar
= self
. pytrans
. avatarCache
. setAvatar ( imageData
)
129 self
. legacycon
. updateAvatar ( self
. avatar
)
132 self
. legacycon
. updateAvatar () # Default avatar
134 def errback ( args
= None ):
135 LogEvent ( INFO
, self
. jabberID
, "Error fetching avatar." )
137 self
. legacycon
. updateAvatar ()
139 LogEvent ( INFO
, self
. jabberID
, "Fetching avatar." )
140 d
= self
. sendVCardRequest ( to
= self
. jabberID
, fro
= config
. jid
)
141 d
. addCallback ( vCardReceived
)
142 d
. addErrback ( errback
)
144 def updateNickname ( self
, nickname
):
145 self
. nickname
= nickname
146 if not self
. nickname
:
147 j
= jid
. intern ( self
. jabberID
)
148 self
. nickname
= j
. user
149 self
. setStatus ( self
. show
, self
. status
)
151 def setStatus ( self
, show
, status
):
154 self
. legacycon
. setStatus ( self
. nickname
, show
, status
)
156 def sendNotReadyError ( self
, source
, resource
, dest
, body
):
157 self
. sendErrorMessage ( source
+ '/' + resource
, dest
, "wait" , "not-allowed" , lang
. get ( self
. lang
). waitForLogin
, body
)
159 def findGroupchat ( self
, to
):
166 for groupchat
in self
. groupchats
:
167 if groupchat
. ID
== roomID
:
172 def nicknameReceived ( self
, source
, dest
, nickname
):
173 if dest
. find ( '@' ) > 0 : return # Ignore presence packets sent to users
175 self
. updateNickname ( nickname
)
177 def avatarHashReceived ( self
, source
, dest
, avatarHash
):
178 if dest
. find ( '@' ) > 0 : return # Ignore presence packets sent to users
180 if avatarHash
== " " : # Setting no avatar
181 self
. legacycon
. updateAvatar () # Default
182 elif ( not self
. avatar
) or ( self
. avatar
and self
. avatar
. getImageHash () != avatarHash
):
183 imageData
= self
. pytrans
. avatarCache
. getAvatar ( avatarHash
)
185 self
. avatar
= avatar
. Avatar ( imageData
, self
. pytrans
. avatarCache
) # Stuff in the cache is always PNG
186 self
. legacycon
. updateAvatar ( self
. avatar
)
190 def messageReceived ( self
, source
, resource
, dest
, destr
, mtype
, body
, noerror
):
191 if dest
== config
. jid
:
192 if body
. lower (). startswith ( "end" ):
193 LogEvent ( INFO
, self
. jabberID
, "Received 'end' request." )
198 self
. sendNotReadyError ( source
, resource
, dest
, body
)
201 # Sends the message to the legacy translator
202 groupchat
= self
. findGroupchat ( dest
)
204 # It's for a groupchat
205 if destr
and len ( destr
) > 0 and not noerror
:
206 self
. sendErrorMessage ( to
=( source
+ "/" + resource
), fro
= dest
, etype
= "cancel" , condition
= "not-allowed" , explanation
= lang
. get ( self
. lang
). groupchatPrivateError
, body
= body
)
208 LogEvent ( INFO
, self
. jabberID
, "Groupchat." )
209 groupchat
. sendMessage ( body
, noerror
)
211 LogEvent ( INFO
, self
. jabberID
, "Message." )
212 self
. legacycon
. sendMessage ( dest
, resource
, body
, noerror
)
214 def inviteReceived ( self
, source
, resource
, dest
, destr
, roomjid
):
216 self
. sendNotReadyError ( source
, resource
, dest
, roomjid
)
219 if not roomjid
. endswith ( '@' + config
. jid
): # Inviting a MSN user to a Jabber chatroom
220 message
= lang
. get ( self
. lang
). groupchatAdvocacy
% ( self
. jabberID
, config
. website
)
221 self
. legacycon
. sendMessage ( dest
, resource
, message
, True )
224 groupchat
= self
. findGroupchat ( roomjid
)
226 LogEvent ( INFO
, self
. jabberID
, "Groupchat invitation." )
227 groupchat
. sendContactInvite ( dest
)
229 def typingNotificationReceived ( self
, dest
, resource
, composing
):
230 """ The user has sent typing notification to a contact on the legacy service """
231 self
. legacycon
. userTypingNotification ( dest
, resource
, composing
)
233 def presenceReceived ( self
, source
, resource
, to
, tor
, priority
, ptype
, show
, status
):
234 # Checks resources and priorities so that the highest priority resource always appears as the
235 # legacy services status. If there are no more resources then the session is deleted
236 # Additionally checks if the presence is to a groupchat room
237 groupchat
= self
. findGroupchat ( to
)
239 # It's for an existing groupchat
240 if ptype
== "unavailable" :
242 LogEvent ( INFO
, self
. jabberID
, "Killing groupchat." )
245 if source
== self
. jabberID
:
246 LogEvent ( INFO
, self
. jabberID
, "Groupchat presence." )
250 groupchat
. userJoined ( tor
)
252 LogEvent ( INFO
, self
. jabberID
, "Sending groupchat error presence." )
253 self
. sendPresence ( to
=( source
+ "/" + resource
), fro
= to
, ptype
= "error" )
255 elif legacy
. isGroupJID ( to
) and to
!= config
. jid
and not ptype
:
256 # Its to a groupchat JID, and the presence type is available
258 self
. sendNotReadyError ( source
, resource
, to
, to
)
261 # It's a new groupchat
262 gcID
= to
[: to
. find ( '@' )] # Grab the room name
263 LogEvent ( INFO
, self
. jabberID
, "Creating a new groupchat." )
264 groupchat
= legacy
. LegacyGroupchat ( self
, resource
, gcID
) # Creates an empty groupchat
265 groupchat
. userJoined ( tor
)
269 self
. handleResourcePresence ( source
, resource
, to
, tor
, priority
, ptype
, show
, status
)
272 def handleResourcePresence ( self
, source
, resource
, to
, tor
, priority
, ptype
, show
, status
):
273 if ptype
and ptype
!= "unavailable" : return # Ignore presence errors, probes, etc
274 if to
. find ( '@' ) > 0 : return # Ignore presence packets sent to users
276 existing
= self
. resourceList
. has_key ( resource
)
277 if ptype
== "unavailable" :
279 LogEvent ( INFO
, self
. jabberID
, "Resource gone offline." )
280 self
. resourceOffline ( resource
)
282 return # I don't know the resource, and they're leaving, so it's all good
285 LogEvent ( INFO
, self
. jabberID
, "Resource came online." )
286 self
. contactList
. resendLists ( source
+ "/" + resource
)
287 LogEvent ( INFO
, self
. jabberID
, "Setting status." )
288 self
. resourceList
[ resource
] = SessionResource ( show
, status
, priority
)
290 highestActive
= self
. highestResource ()
293 # If we're the highest active resource, we should update the legacy service
294 LogEvent ( INFO
, self
. jabberID
, "Updating status on legacy service." )
295 r
= self
. resourceList
[ highestActive
]
296 self
. setStatus ( r
. show
, r
. status
)
298 LogEvent ( INFO
, self
. jabberID
, "Last resource died. Calling removeMe in 0 seconds." )
299 #reactor.callLater(0, self.removeMe)
301 #FIXME Which of the above?
303 def highestResource ( self
):
304 """ Returns the highest priority resource """
306 for checkR
in self
. resourceList
. keys ():
307 if highestActive
== None or self
. resourceList
[ checkR
]. priority
> self
. resourceList
[ highestActive
]. priority
:
308 highestActive
= checkR
311 # debug.log("Session %s - highest active resource is \"%s\" at %d" % (self.jabberID, highestActive, self.resourceList[highestActive].priority))
316 def resourceOffline ( self
, resource
):
317 del self
. resourceList
[ resource
]
318 self
. legacycon
. resourceOffline ( resource
)
320 def subscriptionReceived ( self
, to
, subtype
):
321 """ Sends the subscription request to the legacy services handler """
323 LogEvent ( INFO
, self
. jabberID
, "Passing subscription to legacy service." )
324 self
. contactList
. jabberSubscriptionReceived ( to
, subtype
)
326 if subtype
== "subscribe" :
327 self
. sendPresence ( to
= self
. jabberID
, fro
= config
. jid
, ptype
= "subscribed" )
328 elif subtype
. startswith ( "unsubscribe" ):
329 # They want to unregister.
331 LogEvent ( INFO
, jid
, "About to unregister." )
332 self
. pytrans
. registermanager
. removeRegInfo ( jid
)
333 LogEvent ( INFO
, jid
, "Just unregistered." )
341 class SessionResource
:
342 """ A convienence class to allow comparisons of Jabber resources """
343 def __init__ ( self
, show
= None , status
= None , priority
= None ):
348 self
. priority
= int ( priority
)
349 except TypeError : pass
350 except ValueError : pass