]>
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
12 from debug
import LogEvent
, INFO
, WARN
, ERROR
16 def makeSession ( pytrans
, jabberID
, ulang
):
17 """ Tries to create a session object for the corresponding JabberID. Retrieves information
18 from XDB to create the session. If it fails, then the user is most likely not registered with
20 LogEvent ( INFO
, jabberID
)
21 if pytrans
. sessions
. has_key ( jabberID
):
22 LogEvent ( INFO
, jabberID
, "Removing existing session." )
23 pytrans
. sessions
[ jabberID
]. removeMe ()
24 result
= pytrans
. registermanager
. getRegInfo ( jabberID
)
26 username
, password
= result
27 return Session ( pytrans
, jabberID
, username
, password
, ulang
)
33 class Session ( jabw
. JabberConnection
):
34 """ A class to represent each registered user's session with the legacy network. Exists as long as there
35 is a Jabber resource for the user available """
37 def __init__ ( self
, pytrans
, jabberID
, username
, password
, ulang
):
38 """ Initialises the session object and connects to the legacy network """
39 jabw
. JabberConnection
.__ init
__ ( self
, pytrans
, jabberID
)
40 LogEvent ( INFO
, jabberID
)
42 self
. pytrans
= pytrans
44 self
. ready
= False # Only ready when we're logged into the legacy service
45 self
. jabberID
= jabberID
# the JabberID of the Session's user
46 self
. username
= username
# the legacy network ID of the Session's user
47 self
. password
= password
55 self
. resourceList
= {}
58 self
. legacycon
= legacy
. LegacyConnection ( self
. username
, self
. password
, self
)
59 self
. contactList
= contact
. ContactList ( self
)
60 self
. contactList
. legacyList
= self
. legacycon
. legacyList
62 if config
. sessionGreeting
:
63 self
. sendMessage ( to
= self
. jabberID
, fro
= config
. jid
, body
= config
. sessionGreeting
)
65 self
. updateNickname ( "" )
67 LogEvent ( INFO
, self
. jabberID
, "Created!" )
70 """ Safely removes the session object, including sending <presence type="unavailable"/> messages for each legacy related item on the user's contact list """
71 # Send offline presence to Jabber ID
72 # Delete all objects cleanly
73 # Remove this Session object from the pytrans
75 LogEvent ( INFO
, self
. jabberID
)
81 # Send offline presence to the user
83 self
. sendPresence ( to
= self
. jabberID
, fro
= config
. jid
, ptype
= "unavailable" )
85 # Clean up stuff on the legacy service end (including sending offline presences for all contacts)
87 self
. legacycon
. removeMe ()
91 self
. contactList
. removeMe ()
92 self
. contactList
= None
94 # Remove any groupchats we may be in
95 for groupchat
in self
. groupchats
[:]:
99 # Remove us from the session list
100 del self
. pytrans
. sessions
[ self
. jabberID
]
101 # Clean up the no longer needed reference
104 LogEvent ( INFO
, self
. jabberID
, "Removed!" )
106 def doVCardUpdate ( self
):
107 def vCardReceived ( el
):
108 if not self
. alive
: return
109 LogEvent ( INFO
, self
. jabberID
)
111 for e
in el
. elements ():
112 if e
. name
== "vCard" and e
. defaultUri
== disco
. VCARDTEMP
:
116 self
. legacycon
. updateAvatar () # Default avatar
119 for e
in vCard
. elements ():
120 if e
. name
== "NICKNAME" :
121 self
. updateNickname ( e
.__ str
__ ())
122 if e
. name
== "PHOTO" :
123 imageData
= avatar
. parsePhotoEl ( e
)
125 errback () # Possibly it wasn't in a supported format?
126 self
. avatar
= self
. pytrans
. avatarCache
. setAvatar ( imageData
)
127 self
. legacycon
. updateAvatar ( self
. avatar
)
130 self
. legacycon
. updateAvatar () # Default avatar
132 def errback ( args
= None ):
133 LogEvent ( INFO
, self
. jabberID
, "Error fetching avatar." )
135 self
. legacycon
. updateAvatar ()
137 LogEvent ( INFO
, self
. jabberID
, "Fetching avatar." )
138 d
= self
. sendVCardRequest ( to
= self
. jabberID
, fro
= config
. jid
)
139 d
. addCallback ( vCardReceived
)
140 d
. addErrback ( errback
)
142 def updateNickname ( self
, nickname
):
143 self
. nickname
= nickname
144 if not self
. nickname
:
145 j
= utils
. jid ( self
. jabberID
)
146 self
. nickname
= j
. user
147 self
. setStatus ( self
. show
, self
. status
)
149 def setStatus ( self
, show
, status
):
152 self
. legacycon
. setStatus ( self
. nickname
, show
, status
)
154 def sendNotReadyError ( self
, source
, resource
, dest
, body
):
155 self
. sendErrorMessage ( source
+ '/' + resource
, dest
, "wait" , "not-allowed" , lang
. get ( self
. lang
). waitForLogin
, body
)
157 def findGroupchat ( self
, to
):
164 for groupchat
in self
. groupchats
:
165 if groupchat
. ID
== roomID
:
170 def nicknameReceived ( self
, source
, dest
, nickname
):
171 if dest
. find ( '@' ) > 0 : return # Ignore presence packets sent to users
173 self
. updateNickname ( nickname
)
175 def avatarHashReceived ( self
, source
, dest
, avatarHash
):
176 if dest
. find ( '@' ) > 0 : return # Ignore presence packets sent to users
178 if avatarHash
== " " : # Setting no avatar
179 self
. legacycon
. updateAvatar () # Default
180 elif ( not self
. avatar
) or ( self
. avatar
and self
. avatar
. getImageHash () != avatarHash
):
181 imageData
= self
. pytrans
. avatarCache
. getAvatar ( avatarHash
)
183 self
. avatar
= avatar
. Avatar ( imageData
, self
. pytrans
. avatarCache
) # Stuff in the cache is always PNG
184 self
. legacycon
. updateAvatar ( self
. avatar
)
188 def messageReceived ( self
, source
, resource
, dest
, destr
, mtype
, body
, noerror
):
189 if dest
== config
. jid
:
190 if body
. lower (). startswith ( "end" ):
191 LogEvent ( INFO
, self
. jabberID
, "Received 'end' request." )
196 self
. sendNotReadyError ( source
, resource
, dest
, body
)
199 # Sends the message to the legacy translator
200 groupchat
= self
. findGroupchat ( dest
)
202 # It's for a groupchat
203 if destr
and len ( destr
) > 0 and not noerror
:
204 self
. sendErrorMessage ( to
=( source
+ "/" + resource
), fro
= dest
, etype
= "cancel" , condition
= "not-allowed" , explanation
= lang
. get ( self
. lang
). groupchatPrivateError
, body
= body
)
206 LogEvent ( INFO
, self
. jabberID
, "Groupchat." )
207 groupchat
. sendMessage ( body
, noerror
)
209 LogEvent ( INFO
, self
. jabberID
, "Message." )
210 self
. legacycon
. sendMessage ( dest
, resource
, body
, noerror
)
212 def inviteReceived ( self
, source
, resource
, dest
, destr
, roomjid
):
214 self
. sendNotReadyError ( source
, resource
, dest
, roomjid
)
217 if not roomjid
. endswith ( '@' + config
. jid
): # Inviting a MSN user to a Jabber chatroom
218 message
= lang
. get ( self
. lang
). groupchatAdvocacy
% ( self
. jabberID
, config
. website
)
219 self
. legacycon
. sendMessage ( dest
, resource
, message
, True )
222 groupchat
= self
. findGroupchat ( roomjid
)
224 LogEvent ( INFO
, self
. jabberID
, "Groupchat invitation." )
225 groupchat
. sendContactInvite ( dest
)
227 def typingNotificationReceived ( self
, dest
, resource
, composing
):
228 """ The user has sent typing notification to a contact on the legacy service """
229 self
. legacycon
. userTypingNotification ( dest
, resource
, composing
)
231 def presenceReceived ( self
, source
, resource
, to
, tor
, priority
, ptype
, show
, status
):
232 # Checks resources and priorities so that the highest priority resource always appears as the
233 # legacy services status. If there are no more resources then the session is deleted
234 # Additionally checks if the presence is to a groupchat room
235 groupchat
= self
. findGroupchat ( to
)
237 # It's for an existing groupchat
238 if ptype
== "unavailable" :
240 LogEvent ( INFO
, self
. jabberID
, "Killing groupchat." )
243 if source
== self
. jabberID
:
244 LogEvent ( INFO
, self
. jabberID
, "Groupchat presence." )
248 groupchat
. userJoined ( tor
)
250 LogEvent ( INFO
, self
. jabberID
, "Sending groupchat error presence." )
251 self
. sendPresence ( to
=( source
+ "/" + resource
), fro
= to
, ptype
= "error" )
253 elif legacy
. isGroupJID ( to
) and to
!= config
. jid
and not ptype
:
254 # Its to a groupchat JID, and the presence type is available
256 self
. sendNotReadyError ( source
, resource
, to
, to
)
259 # It's a new groupchat
260 gcID
= to
[: to
. find ( '@' )] # Grab the room name
261 LogEvent ( INFO
, self
. jabberID
, "Creating a new groupchat." )
262 groupchat
= legacy
. LegacyGroupchat ( self
, resource
, gcID
) # Creates an empty groupchat
263 groupchat
. userJoined ( tor
)
267 self
. handleResourcePresence ( source
, resource
, to
, tor
, priority
, ptype
, show
, status
)
270 def handleResourcePresence ( self
, source
, resource
, to
, tor
, priority
, ptype
, show
, status
):
271 if ptype
and ptype
!= "unavailable" : return # Ignore presence errors, probes, etc
272 if to
. find ( '@' ) > 0 : return # Ignore presence packets sent to users
274 existing
= self
. resourceList
. has_key ( resource
)
275 if ptype
== "unavailable" :
277 LogEvent ( INFO
, self
. jabberID
, "Resource gone offline." )
278 self
. resourceOffline ( resource
)
280 return # I don't know the resource, and they're leaving, so it's all good
283 LogEvent ( INFO
, self
. jabberID
, "Resource came online." )
284 self
. contactList
. resendLists ( source
+ "/" + resource
)
285 LogEvent ( INFO
, self
. jabberID
, "Setting status." )
286 self
. resourceList
[ resource
] = SessionResource ( show
, status
, priority
)
288 highestActive
= self
. highestResource ()
291 # If we're the highest active resource, we should update the legacy service
292 LogEvent ( INFO
, self
. jabberID
, "Updating status on legacy service." )
293 r
= self
. resourceList
[ highestActive
]
294 self
. setStatus ( r
. show
, r
. status
)
296 LogEvent ( INFO
, self
. jabberID
, "Last resource died. Calling removeMe in 0 seconds." )
297 #reactor.callLater(0, self.removeMe)
299 #FIXME Which of the above?
301 def highestResource ( self
):
302 """ Returns the highest priority resource """
304 for checkR
in self
. resourceList
. keys ():
305 if highestActive
== None or self
. resourceList
[ checkR
]. priority
> self
. resourceList
[ highestActive
]. priority
:
306 highestActive
= checkR
309 # debug.log("Session %s - highest active resource is \"%s\" at %d" % (self.jabberID, highestActive, self.resourceList[highestActive].priority))
314 def resourceOffline ( self
, resource
):
315 del self
. resourceList
[ resource
]
316 self
. legacycon
. resourceOffline ( resource
)
318 def subscriptionReceived ( self
, to
, subtype
):
319 """ Sends the subscription request to the legacy services handler """
321 LogEvent ( INFO
, self
. jabberID
, "Passing subscription to legacy service." )
322 self
. contactList
. jabberSubscriptionReceived ( to
, subtype
)
324 if subtype
== "subscribe" :
325 self
. sendPresence ( to
= self
. jabberID
, fro
= config
. jid
, ptype
= "subscribed" )
326 elif subtype
. startswith ( "unsubscribe" ):
327 # They want to unregister.
329 LogEvent ( INFO
, jid
, "About to unregister." )
330 self
. pytrans
. registermanager
. removeRegInfo ( jid
)
331 LogEvent ( INFO
, jid
, "Just unregistered." )
339 class SessionResource
:
340 """ A convienence class to allow comparisons of Jabber resources """
341 def __init__ ( self
, show
= None , status
= None , priority
= None ):
346 self
. priority
= int ( priority
)
347 except TypeError : pass
348 except ValueError : pass