comparison src/core/sat_main.py @ 589:d1b4805124a1

Fix pep8 support in src/core.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Fri, 18 Jan 2013 17:55:35 +0100
parents 952322b1d490
children 6fd1095b2b7b
comparison
equal deleted inserted replaced
588:beaf6bec2fcd 589:d1b4805124a1
48 try: 48 try:
49 from twisted.words.protocols.xmlstream import XMPPHandler 49 from twisted.words.protocols.xmlstream import XMPPHandler
50 except ImportError: 50 except ImportError:
51 from wokkel.subprotocols import XMPPHandler 51 from wokkel.subprotocols import XMPPHandler
52 52
53
54 ### logging configuration FIXME: put this elsewhere ### 53 ### logging configuration FIXME: put this elsewhere ###
55 logging.basicConfig(level=logging.DEBUG, 54 logging.basicConfig(level=logging.DEBUG,
56 format='%(message)s') 55 format='%(message)s')
57 ### 56 ###
58 57
59
60 sat_id = 0 58 sat_id = 0
59
61 60
62 def sat_next_id(): 61 def sat_next_id():
63 global sat_id 62 global sat_id
64 sat_id+=1 63 sat_id += 1
65 return "sat_id_"+str(sat_id) 64 return "sat_id_" + str(sat_id)
65
66 66
67 class SAT(service.Service): 67 class SAT(service.Service):
68 68
69 def get_next_id(self): 69 def get_next_id(self):
70 return sat_next_id() 70 return sat_next_id()
72 def get_const(self, name): 72 def get_const(self, name):
73 """Return a constant""" 73 """Return a constant"""
74 try: 74 try:
75 _const = os.environ['SAT_CONST_%s' % name] 75 _const = os.environ['SAT_CONST_%s' % name]
76 if _const: 76 if _const:
77 debug(_("Constant %(name)s overrided with [%(value)s]") % {'name':name, 'value': _const}) 77 debug(_("Constant %(name)s overrided with [%(value)s]") % {'name': name, 'value': _const})
78 return _const 78 return _const
79 except KeyError: 79 except KeyError:
80 pass 80 pass
81 if not CONST.has_key(name): 81 if name not in CONST:
82 error(_('Trying to access an undefined constant')) 82 error(_('Trying to access an undefined constant'))
83 raise Exception 83 raise Exception
84 return CONST[name] 84 return CONST[name]
85 85
86 def set_const(self, name, value): 86 def set_const(self, name, value):
87 """Save a constant""" 87 """Save a constant"""
88 if CONST.has_key(name): 88 if name in CONST:
89 error(_('Trying to redefine a constant')) 89 error(_('Trying to redefine a constant'))
90 raise Exception 90 raise Exception
91 CONST[name] = value 91 CONST[name] = value
92 92
93 def __init__(self): 93 def __init__(self):
94 #TODO: standardize callback system 94 #TODO: standardize callback system
95 95
96 self.__general_cb_map = {} #callback called for general reasons (key = name) 96 self.__general_cb_map = {} # callback called for general reasons (key = name)
97 self.__private_data = {} #used for internal callbacks (key = id) 97 self.__private_data = {} # used for internal callbacks (key = id)
98 self.profiles = {} 98 self.profiles = {}
99 self.plugins = {} 99 self.plugins = {}
100 self.menus = {} #used to know which new menus are wanted by plugins 100 self.menus = {} # used to know which new menus are wanted by plugins
101 101
102 self.memory=Memory(self) 102 self.memory = Memory(self)
103 103
104 local_dir = self.memory.getConfig('', 'local_dir') 104 local_dir = self.memory.getConfig('', 'local_dir')
105 if not os.path.exists(local_dir): 105 if not os.path.exists(local_dir):
106 os.makedirs(local_dir) 106 os.makedirs(local_dir)
107 107
108 self.trigger = TriggerManager() #trigger are used to change SàT behaviour 108 self.trigger = TriggerManager() # trigger are used to change SàT behaviour
109 109
110 self.bridge=DBusBridge() 110 self.bridge = DBusBridge()
111 self.bridge.register("getVersion", lambda: self.get_const('client_version')) 111 self.bridge.register("getVersion", lambda: self.get_const('client_version'))
112 self.bridge.register("getProfileName", self.memory.getProfileName) 112 self.bridge.register("getProfileName", self.memory.getProfileName)
113 self.bridge.register("getProfilesList", self.memory.getProfilesList) 113 self.bridge.register("getProfilesList", self.memory.getProfilesList)
114 self.bridge.register("getEntityData", lambda _jid, keys, profile: self.memory.getEntityData(jid.JID(_jid), keys, profile)) 114 self.bridge.register("getEntityData", lambda _jid, keys, profile: self.memory.getEntityData(jid.JID(_jid), keys, profile))
115 self.bridge.register("createProfile", self.memory.createProfile) 115 self.bridge.register("createProfile", self.memory.createProfile)
153 def _postMemoryInit(self, ignore): 153 def _postMemoryInit(self, ignore):
154 """Method called after memory initialization is done""" 154 """Method called after memory initialization is done"""
155 info(_("Memory initialised")) 155 info(_("Memory initialised"))
156 self._import_plugins() 156 self._import_plugins()
157 157
158
159 def _import_plugins(self): 158 def _import_plugins(self):
160 """Import all plugins found in plugins directory""" 159 """Import all plugins found in plugins directory"""
161 import sat.plugins 160 import sat.plugins
162 plugins_path = os.path.dirname(sat.plugins.__file__) 161 plugins_path = os.path.dirname(sat.plugins.__file__)
163 plug_lst = [os.path.splitext(plugin)[0] for plugin in map(os.path.basename,glob(os.path.join(plugins_path,"plugin*.py")))] 162 plug_lst = [os.path.splitext(plugin)[0] for plugin in map(os.path.basename, glob(os.path.join(plugins_path, "plugin*.py")))]
164 __plugins_to_import = {} #plugins we still have to import 163 __plugins_to_import = {} # plugins we still have to import
165 for plug in plug_lst: 164 for plug in plug_lst:
166 plugin_path = 'sat.plugins.'+plug 165 plugin_path = 'sat.plugins.' + plug
167 __import__(plugin_path) 166 __import__(plugin_path)
168 mod = sys.modules[plugin_path] 167 mod = sys.modules[plugin_path]
169 plugin_info = mod.PLUGIN_INFO 168 plugin_info = mod.PLUGIN_INFO
170 __plugins_to_import[plugin_info['import_name']] = (plugin_path, mod, plugin_info) 169 __plugins_to_import[plugin_info['import_name']] = (plugin_path, mod, plugin_info)
171 while True: 170 while True:
174 break 173 break
175 174
176 def _import_plugins_from_dict(self, plugins_to_import, import_name=None): 175 def _import_plugins_from_dict(self, plugins_to_import, import_name=None):
177 """Recursively import and their dependencies in the right order 176 """Recursively import and their dependencies in the right order
178 @param plugins_to_import: dict where key=import_name and values= (plugin_path, module, plugin_info)""" 177 @param plugins_to_import: dict where key=import_name and values= (plugin_path, module, plugin_info)"""
179 if self.plugins.has_key(import_name): 178 if import_name in self.plugins:
180 debug('Plugin [%s] already imported, passing' % import_name) 179 debug('Plugin [%s] already imported, passing' % import_name)
181 return 180 return
182 if not import_name: 181 if not import_name:
183 import_name,(plugin_path, mod, plugin_info) = plugins_to_import.popitem() 182 import_name, (plugin_path, mod, plugin_info) = plugins_to_import.popitem()
184 else: 183 else:
185 if not import_name in plugins_to_import: 184 if not import_name in plugins_to_import:
186 raise ImportError(_('Dependency plugin not found: [%s]') % import_name) 185 raise ImportError(_('Dependency plugin not found: [%s]') % import_name)
187 plugin_path, mod, plugin_info = plugins_to_import.pop(import_name) 186 plugin_path, mod, plugin_info = plugins_to_import.pop(import_name)
188 dependencies = plugin_info.setdefault("dependencies",[]) 187 dependencies = plugin_info.setdefault("dependencies", [])
189 for dependency in dependencies: 188 for dependency in dependencies:
190 if not self.plugins.has_key(dependency): 189 if dependency not in self.plugins:
191 debug('Recursively import dependency of [%s]: [%s]' % (import_name, dependency)) 190 debug('Recursively import dependency of [%s]: [%s]' % (import_name, dependency))
192 self._import_plugins_from_dict(plugins_to_import, dependency) 191 self._import_plugins_from_dict(plugins_to_import, dependency)
193 info (_("importing plugin: %s"), plugin_info['name']) 192 info(_("importing plugin: %s"), plugin_info['name'])
194 self.plugins[import_name] = getattr(mod, plugin_info['main'])(self) 193 self.plugins[import_name] = getattr(mod, plugin_info['main'])(self)
195 if plugin_info.has_key('handler') and plugin_info['handler'] == 'yes': 194 if 'handler' in plugin_info and plugin_info['handler'] == 'yes':
196 self.plugins[import_name].is_handler = True 195 self.plugins[import_name].is_handler = True
197 else: 196 else:
198 self.plugins[import_name].is_handler = False 197 self.plugins[import_name].is_handler = False
199 #TODO: test xmppclient presence and register handler parent 198 #TODO: test xmppclient presence and register handler parent
200 199
201 200 def connect(self, profile_key='@DEFAULT@'):
202 def connect(self, profile_key = '@DEFAULT@'):
203 """Connect to jabber server""" 201 """Connect to jabber server"""
204 self.asyncConnect(profile_key) 202 self.asyncConnect(profile_key)
205 203
206 def asyncConnect(self, profile_key = '@DEFAULT@'): 204 def asyncConnect(self, profile_key='@DEFAULT@'):
207 """Connect to jabber server with asynchronous reply 205 """Connect to jabber server with asynchronous reply
208 @param profile_key: %(doc_profile)s 206 @param profile_key: %(doc_profile)s
209 """ 207 """
210 208
211 profile = self.memory.getProfileName(profile_key) 209 profile = self.memory.getProfileName(profile_key)
212 if not profile: 210 if not profile:
213 error (_('Trying to connect a non-exsitant profile')) 211 error(_('Trying to connect a non-exsitant profile'))
214 raise ProfileUnknownError(profile_key) 212 raise ProfileUnknownError(profile_key)
215 213
216 if (self.isConnected(profile)): 214 if self.isConnected(profile):
217 info(_("already connected !")) 215 info(_("already connected !"))
218 return defer.succeed("None") 216 return defer.succeed("None")
219 217
220 def afterMemoryInit(ignore): 218 def afterMemoryInit(ignore):
221 """This part must be called when we have loaded individual parameters from memory""" 219 """This part must be called when we have loaded individual parameters from memory"""
222 try: 220 try:
223 port = int(self.memory.getParamA("Port", "Connection", profile_key = profile)) 221 port = int(self.memory.getParamA("Port", "Connection", profile_key=profile))
224 except ValueError: 222 except ValueError:
225 error(_("Can't parse port value, using default value")) 223 error(_("Can't parse port value, using default value"))
226 port = 5222 224 port = 5222
227 current = self.profiles[profile] = xmpp.SatXMPPClient(self, profile, 225 current = self.profiles[profile] = xmpp.SatXMPPClient(
228 jid.JID(self.memory.getParamA("JabberID", "Connection", profile_key = profile), profile), 226 self, profile,
229 self.memory.getParamA("Password", "Connection", profile_key = profile), 227 jid.JID(self.memory.getParamA("JabberID", "Connection", profile_key=profile), profile),
230 self.memory.getParamA("Server", "Connection", profile_key = profile), 228 self.memory.getParamA("Password", "Connection", profile_key=profile),
229 self.memory.getParamA("Server", "Connection", profile_key=profile),
231 port) 230 port)
232 231
233 current.messageProt = xmpp.SatMessageProtocol(self) 232 current.messageProt = xmpp.SatMessageProtocol(self)
234 current.messageProt.setHandlerParent(current) 233 current.messageProt.setHandlerParent(current)
235 234
241 240
242 current.fallBack = xmpp.SatFallbackHandler(self) 241 current.fallBack = xmpp.SatFallbackHandler(self)
243 current.fallBack.setHandlerParent(current) 242 current.fallBack.setHandlerParent(current)
244 243
245 current.versionHandler = xmpp.SatVersionHandler(self.get_const('client_name'), 244 current.versionHandler = xmpp.SatVersionHandler(self.get_const('client_name'),
246 self.get_const('client_version')) 245 self.get_const('client_version'))
247 current.versionHandler.setHandlerParent(current) 246 current.versionHandler.setHandlerParent(current)
248 247
249 debug (_("setting plugins parents")) 248 debug(_("setting plugins parents"))
250 249
251 for plugin in self.plugins.iteritems(): 250 for plugin in self.plugins.iteritems():
252 if plugin[1].is_handler: 251 if plugin[1].is_handler:
253 plugin[1].getHandler(profile).setHandlerParent(current) 252 plugin[1].getHandler(profile).setHandlerParent(current)
254 connected_cb = getattr(plugin[1], "profileConnected", None) 253 connected_cb = getattr(plugin[1], "profileConnected", None)
256 connected_cb(profile) 255 connected_cb(profile)
257 256
258 current.startService() 257 current.startService()
259 258
260 d = current.getConnectionDeferred() 259 d = current.getConnectionDeferred()
261 d.addCallback(lambda x: current.roster.got_roster) #we want to be sure that we got the roster 260 d.addCallback(lambda x: current.roster.got_roster) # we want to be sure that we got the roster
262 return d 261 return d
263 262
264 self.memory.startProfileSession(profile) 263 self.memory.startProfileSession(profile)
265 return self.memory.loadIndividualParams(profile).addCallback(afterMemoryInit) 264 return self.memory.loadIndividualParams(profile).addCallback(afterMemoryInit)
266 265
267 def disconnect(self, profile_key): 266 def disconnect(self, profile_key):
268 """disconnect from jabber server""" 267 """disconnect from jabber server"""
269 if (not self.isConnected(profile_key)): 268 if not self.isConnected(profile_key):
270 info(_("not connected !")) 269 info(_("not connected !"))
271 return 270 return
272 profile = self.memory.getProfileName(profile_key) 271 profile = self.memory.getProfileName(profile_key)
273 info(_("Disconnecting...")) 272 info(_("Disconnecting..."))
274 self.profiles[profile].stopService() 273 self.profiles[profile].stopService()
280 def getContacts(self, profile_key): 279 def getContacts(self, profile_key):
281 client = self.getClient(profile_key) 280 client = self.getClient(profile_key)
282 if not client: 281 if not client:
283 raise ProfileUnknownError(_('Asking contacts for a non-existant profile')) 282 raise ProfileUnknownError(_('Asking contacts for a non-existant profile'))
284 ret = [] 283 ret = []
285 for item in client.roster.getItems(): #we get all items for client's roster 284 for item in client.roster.getItems(): # we get all items for client's roster
286 #and convert them to expected format 285 # and convert them to expected format
287 attr = client.roster.getAttributes(item) 286 attr = client.roster.getAttributes(item)
288 ret.append([item.jid.userhost(), attr, item.groups]) 287 ret.append([item.jid.userhost(), attr, item.groups])
289 return ret 288 return ret
290 289
291 def getContactsFromGroup(self, group, profile_key): 290 def getContactsFromGroup(self, group, profile_key):
336 profile = self.memory.getProfileName(profile_key) 335 profile = self.memory.getProfileName(profile_key)
337 if not profile: 336 if not profile:
338 return None 337 return None
339 return self.profiles[profile] 338 return self.profiles[profile]
340 339
341 def registerNewAccount(self, login, password, email, server, port = 5222, id = None, profile_key = '@DEFAULT@'): 340 def registerNewAccount(self, login, password, email, server, port=5222, id=None, profile_key='@DEFAULT@'):
342 """Connect to a server and create a new account using in-band registration""" 341 """Connect to a server and create a new account using in-band registration"""
343 profile = self.memory.getProfileName(profile_key) 342 profile = self.memory.getProfileName(profile_key)
344 assert(profile) 343 assert(profile)
345 344
346 next_id = id or sat_next_id() #the id is used to send server's answer 345 next_id = id or sat_next_id() # the id is used to send server's answer
347 serverRegistrer = xmlstream.XmlStreamFactory(xmpp.RegisteringAuthenticator(self, server, login, password, email, next_id, profile)) 346 serverRegistrer = xmlstream.XmlStreamFactory(xmpp.RegisteringAuthenticator(self, server, login, password, email, next_id, profile))
348 connector = reactor.connectTCP(server, port, serverRegistrer) 347 connector = reactor.connectTCP(server, port, serverRegistrer)
349 serverRegistrer.clientConnectionLost = lambda conn, reason: connector.disconnect() 348 serverRegistrer.clientConnectionLost = lambda conn, reason: connector.disconnect()
350 349
351 return next_id 350 return next_id
354 user = jid.parse(self.memory.getParamA("JabberID", "Connection", profile_key=profile))[0] 353 user = jid.parse(self.memory.getParamA("JabberID", "Connection", profile_key=profile))[0]
355 password = self.memory.getParamA("Password", "Connection", profile_key=profile) 354 password = self.memory.getParamA("Password", "Connection", profile_key=profile)
356 server = self.memory.getParamA("Server", "Connection", profile_key=profile) 355 server = self.memory.getParamA("Server", "Connection", profile_key=profile)
357 356
358 if not user or not password or not server: 357 if not user or not password or not server:
359 info (_('No user or server given')) 358 info(_('No user or server given'))
360 #TODO: a proper error message must be sent to frontend 359 #TODO: a proper error message must be sent to frontend
361 self.actionResult(id, "ERROR", {'message':_("No user, password or server given, can't register new account.")}, profile) 360 self.actionResult(id, "ERROR", {'message': _("No user, password or server given, can't register new account.")}, profile)
362 return 361 return
363 362
364 confirm_id = sat_next_id() 363 confirm_id = sat_next_id()
365 self.__private_data[confirm_id]=(id,profile) 364 self.__private_data[confirm_id] = (id, profile)
366 365
367 self.askConfirmation(confirm_id, "YES/NO", 366 self.askConfirmation(
368 {"message":_("Are you sure to register new account [%(user)s] to server %(server)s ?") % {'user':user, 'server':server, 'profile':profile}}, 367 confirm_id, "YES/NO",
368 {"message": _("Are you sure to register new account [%(user)s] to server %(server)s ?") % {'user': user, 'server': server, 'profile': profile}},
369 self.regisConfirmCB, profile) 369 self.regisConfirmCB, profile)
370 print ("===============+++++++++++ REGISTER NEW ACCOUNT++++++++++++++============") 370 print "===============+++++++++++ REGISTER NEW ACCOUNT++++++++++++++============"
371 print "id=",id 371 print "id=", id
372 print "data=",data 372 print "data=", data
373 373
374 def regisConfirmCB(self, id, accepted, data, profile): 374 def regisConfirmCB(self, id, accepted, data, profile):
375 print _("register Confirmation CB ! (%s)") % str(accepted) 375 print _("register Confirmation CB ! (%s)") % str(accepted)
376 action_id,profile = self.__private_data[id] 376 action_id, profile = self.__private_data[id]
377 del self.__private_data[id] 377 del self.__private_data[id]
378 if accepted: 378 if accepted:
379 user = jid.parse(self.memory.getParamA("JabberID", "Connection", profile_key=profile))[0] 379 user = jid.parse(self.memory.getParamA("JabberID", "Connection", profile_key=profile))[0]
380 password = self.memory.getParamA("Password", "Connection", profile_key=profile) 380 password = self.memory.getParamA("Password", "Connection", profile_key=profile)
381 server = self.memory.getParamA("Server", "Connection", profile_key=profile) 381 server = self.memory.getParamA("Server", "Connection", profile_key=profile)
396 396
397 iq = compat.IQ(self.profiles[profile].xmlstream, 'set') 397 iq = compat.IQ(self.profiles[profile].xmlstream, 'set')
398 iq["to"] = target 398 iq["to"] = target
399 iq["from"] = self.profiles[profile].jid.full() 399 iq["from"] = self.profiles[profile].jid.full()
400 query = iq.addElement(('jabber:iq:register', 'query')) 400 query = iq.addElement(('jabber:iq:register', 'query'))
401 if action=='SUBMIT': 401 if action == 'SUBMIT':
402 form = tupleList2dataForm(fields) 402 form = tupleList2dataForm(fields)
403 query.addChild(form.toElement()) 403 query.addChild(form.toElement())
404 elif action=='CANCEL': 404 elif action == 'CANCEL':
405 query.addElement('remove') 405 query.addElement('remove')
406 else: 406 else:
407 error (_("FIXME FIXME FIXME: Unmanaged action (%s) in submitForm") % action) 407 error(_("FIXME FIXME FIXME: Unmanaged action (%s) in submitForm") % action)
408 raise NotImplementedError 408 raise NotImplementedError
409 409
410 deferred = iq.send(target) 410 deferred = iq.send(target)
411 return (iq['id'], deferred) 411 return (iq['id'], deferred)
412 412
413 ## Client management ## 413 ## Client management ##
414 414
415 def setParam(self, name, value, category, profile_key): 415 def setParam(self, name, value, category, profile_key):
416 """set wanted paramater and notice observers""" 416 """set wanted paramater and notice observers"""
417 info (_("setting param: %(name)s=%(value)s in category %(category)s") % {'name':name, 'value':value, 'category':category}) 417 info(_("setting param: %(name)s=%(value)s in category %(category)s") % {'name': name, 'value': value, 'category': category})
418 self.memory.setParam(name, value, category, profile_key) 418 self.memory.setParam(name, value, category, profile_key)
419 419
420 def isConnected(self, profile_key): 420 def isConnected(self, profile_key):
421 """Return connection status of profile 421 """Return connection status of profile
422 @param profile_key: key_word or profile name to determine profile name 422 @param profile_key: key_word or profile name to determine profile name
423 @return True if connected 423 @return True if connected
424 """ 424 """
425 profile = self.memory.getProfileName(profile_key) 425 profile = self.memory.getProfileName(profile_key)
426 if not profile: 426 if not profile:
427 error (_('asking connection status for a non-existant profile')) 427 error(_('asking connection status for a non-existant profile'))
428 return 428 return
429 if not self.profiles.has_key(profile): 429 if profile not in self.profiles:
430 return False 430 return False
431 return self.profiles[profile].isConnected() 431 return self.profiles[profile].isConnected()
432 432
433 def launchAction(self, type, data, profile_key): 433 def launchAction(self, type, data, profile_key):
434 """Launch a specific action asked by client 434 """Launch a specific action asked by client
437 437
438 @return: action id for result, or empty string in case or error 438 @return: action id for result, or empty string in case or error
439 """ 439 """
440 profile = self.memory.getProfileName(profile_key) 440 profile = self.memory.getProfileName(profile_key)
441 if not profile: 441 if not profile:
442 error (_('trying to launch action with a non-existant profile')) 442 error(_('trying to launch action with a non-existant profile'))
443 raise Exception #TODO: raise a proper exception 443 raise Exception # TODO: raise a proper exception
444 if type=="button": 444 if type == "button":
445 try: 445 try:
446 cb_name = data['callback_id'] 446 cb_name = data['callback_id']
447 except KeyError: 447 except KeyError:
448 error (_("Incomplete data")) 448 error(_("Incomplete data"))
449 return "" 449 return ""
450 id = sat_next_id() 450 id = sat_next_id()
451 self.callGeneralCB(cb_name, id, data, profile = profile) 451 self.callGeneralCB(cb_name, id, data, profile=profile)
452 return id 452 return id
453 else: 453 else:
454 error (_("Unknown action type")) 454 error(_("Unknown action type"))
455 return "" 455 return ""
456
457 456
458 ## jabber methods ## 457 ## jabber methods ##
459 458
460 def getWaitingConf(self, profile_key=None): 459 def getWaitingConf(self, profile_key=None):
461 assert(profile_key) 460 assert(profile_key)
472 #FIXME: check validity of recipient 471 #FIXME: check validity of recipient
473 profile = self.memory.getProfileName(profile_key) 472 profile = self.memory.getProfileName(profile_key)
474 assert(profile) 473 assert(profile)
475 client = self.profiles[profile] 474 client = self.profiles[profile]
476 current_jid = client.jid 475 current_jid = client.jid
477 mess_data = { #we put data in a dict, so trigger methods can change them 476 mess_data = { # we put data in a dict, so trigger methods can change them
478 "to": jid.JID(to), 477 "to": jid.JID(to),
479 "message": msg, 478 "message": msg,
480 "subject": subject, 479 "subject": subject,
481 "type": mess_type 480 "type": mess_type
482 } 481 }
483 482
484 if mess_data["type"] == "auto": 483 if mess_data["type"] == "auto":
485 # we try to guess the type 484 # we try to guess the type
486 if mess_data["subject"]: 485 if mess_data["subject"]:
487 mess_data["type"] = 'normal' 486 mess_data["type"] = 'normal'
488 elif not mess_data["to"].resource: #if to JID has a resource, the type is not 'groupchat' 487 elif not mess_data["to"].resource: # if to JID has a resource, the type is not 'groupchat'
489 #we may have a groupchat message, we check if the we know this jid 488 # we may have a groupchat message, we check if the we know this jid
490 try: 489 try:
491 entity_type = self.memory.getEntityData(mess_data["to"], ['type'], profile)["type"] 490 entity_type = self.memory.getEntityData(mess_data["to"], ['type'], profile)["type"]
492 #FIXME: should entity_type manage ressources ? 491 #FIXME: should entity_type manage ressources ?
493 except (UnknownEntityError, KeyError): 492 except (UnknownEntityError, KeyError):
494 entity_type = "contact" 493 entity_type = "contact"
503 502
504 if not self.trigger.point("sendMessage", mess_data, profile): 503 if not self.trigger.point("sendMessage", mess_data, profile):
505 return 504 return
506 505
507 debug(_("Sending jabber message of type [%(type)s] to %(to)s...") % {"type": mess_data["type"], "to": to}) 506 debug(_("Sending jabber message of type [%(type)s] to %(to)s...") % {"type": mess_data["type"], "to": to})
508 message = domish.Element((None,'message')) 507 message = domish.Element((None, 'message'))
509 message["to"] = mess_data["to"].full() 508 message["to"] = mess_data["to"].full()
510 message["from"] = current_jid.full() 509 message["from"] = current_jid.full()
511 message["type"] = mess_data["type"] 510 message["type"] = mess_data["type"]
512 if mess_data["subject"]: 511 if mess_data["subject"]:
513 message.addElement("subject", None, subject) 512 message.addElement("subject", None, subject)
514 message.addElement("body", None, mess_data["message"]) 513 message.addElement("body", None, mess_data["message"])
515 client.xmlstream.send(message) 514 client.xmlstream.send(message)
516 if mess_data["type"]!="groupchat": 515 if mess_data["type"] != "groupchat":
517 self.memory.addToHistory(current_jid, jid.JID(to), unicode(mess_data["message"]), unicode(mess_data["type"]), profile=profile) #we don't add groupchat message to history, as we get them back 516 self.memory.addToHistory(current_jid, jid.JID(to), unicode(mess_data["message"]), unicode(mess_data["type"]), profile=profile) # we don't add groupchat message to history, as we get them back
518 #and they will be added then 517 # and they will be added then
519 self.bridge.newMessage(message['from'], unicode(mess_data["message"]), mess_type=mess_data["type"], to_jid=message['to'], extra={}, profile=profile) #We send back the message, so all clients are aware of it 518 self.bridge.newMessage(message['from'], unicode(mess_data["message"]), mess_type=mess_data["type"], to_jid=message['to'], extra={}, profile=profile) # We send back the message, so all clients are aware of it
520 519
521 520 def setPresence(self, to="", show="", priority=0, statuses={}, profile_key='@DEFAULT@'):
522 def setPresence(self, to="", show="", priority = 0, statuses={}, profile_key='@DEFAULT@'):
523 """Send our presence information""" 521 """Send our presence information"""
524 profile = self.memory.getProfileName(profile_key) 522 profile = self.memory.getProfileName(profile_key)
525 assert(profile) 523 assert(profile)
526 to_jid = jid.JID(to) if to else None 524 to_jid = jid.JID(to) if to else None
527 self.profiles[profile].presence.available(to_jid, show, statuses, priority) 525 self.profiles[profile].presence.available(to_jid, show, statuses, priority)
528 #XXX: FIXME: temporary fix to work around openfire 3.7.0 bug (presence is not broadcasted to generating resource) 526 #XXX: FIXME: temporary fix to work around openfire 3.7.0 bug (presence is not broadcasted to generating resource)
529 if statuses.has_key(''): 527 if '' in statuses:
530 statuses['default'] = statuses[''] 528 statuses['default'] = statuses['']
531 del statuses[''] 529 del statuses['']
532 self.bridge.presenceUpdate(self.profiles[profile].jid.full(), show, 530 self.bridge.presenceUpdate(self.profiles[profile].jid.full(), show,
533 int(priority), statuses, profile) 531 int(priority), statuses, profile)
534
535 532
536 def subscription(self, subs_type, raw_jid, profile_key): 533 def subscription(self, subs_type, raw_jid, profile_key):
537 """Called to manage subscription 534 """Called to manage subscription
538 @param subs_type: subsciption type (cf RFC 3921) 535 @param subs_type: subsciption type (cf RFC 3921)
539 @param raw_jid: unicode entity's jid 536 @param raw_jid: unicode entity's jid
540 @param profile_key: profile""" 537 @param profile_key: profile"""
541 profile = self.memory.getProfileName(profile_key) 538 profile = self.memory.getProfileName(profile_key)
542 assert(profile) 539 assert(profile)
543 to_jid = jid.JID(raw_jid) 540 to_jid = jid.JID(raw_jid)
544 debug (_('subsciption request [%(subs_type)s] for %(jid)s') % {'subs_type':subs_type, 'jid':to_jid.full()}) 541 debug(_('subsciption request [%(subs_type)s] for %(jid)s') % {'subs_type': subs_type, 'jid': to_jid.full()})
545 if subs_type=="subscribe": 542 if subs_type == "subscribe":
546 self.profiles[profile].presence.subscribe(to_jid) 543 self.profiles[profile].presence.subscribe(to_jid)
547 elif subs_type=="subscribed": 544 elif subs_type == "subscribed":
548 self.profiles[profile].presence.subscribed(to_jid) 545 self.profiles[profile].presence.subscribed(to_jid)
549 elif subs_type=="unsubscribe": 546 elif subs_type == "unsubscribe":
550 self.profiles[profile].presence.unsubscribe(to_jid) 547 self.profiles[profile].presence.unsubscribe(to_jid)
551 elif subs_type=="unsubscribed": 548 elif subs_type == "unsubscribed":
552 self.profiles[profile].presence.unsubscribed(to_jid) 549 self.profiles[profile].presence.unsubscribed(to_jid)
553 550
554 def addContact(self, to, profile_key): 551 def addContact(self, to, profile_key):
555 """Add a contact in roster list""" 552 """Add a contact in roster list"""
556 profile = self.memory.getProfileName(profile_key) 553 profile = self.memory.getProfileName(profile_key)
557 assert(profile) 554 assert(profile)
558 to_jid=jid.JID(to) 555 to_jid = jid.JID(to)
559 #self.profiles[profile].roster.addItem(to_jid) XXX: disabled (cf http://wokkel.ik.nu/ticket/56)) 556 #self.profiles[profile].roster.addItem(to_jid) #XXX: disabled (cf http://wokkel.ik.nu/ticket/56))
560 self.profiles[profile].presence.subscribe(to_jid) 557 self.profiles[profile].presence.subscribe(to_jid)
561 558
562 def updateContact(self, to, name, groups, profile_key): 559 def updateContact(self, to, name, groups, profile_key):
563 """update a contact in roster list""" 560 """update a contact in roster list"""
564 profile = self.memory.getProfileName(profile_key) 561 profile = self.memory.getProfileName(profile_key)
572 569
573 def delContact(self, to, profile_key): 570 def delContact(self, to, profile_key):
574 """Remove contact from roster list""" 571 """Remove contact from roster list"""
575 profile = self.memory.getProfileName(profile_key) 572 profile = self.memory.getProfileName(profile_key)
576 assert(profile) 573 assert(profile)
577 to_jid=jid.JID(to) 574 to_jid = jid.JID(to)
578 self.profiles[profile].roster.removeItem(to_jid) 575 self.profiles[profile].roster.removeItem(to_jid)
579 self.profiles[profile].presence.unsubscribe(to_jid) 576 self.profiles[profile].presence.unsubscribe(to_jid)
580
581 577
582 ## callbacks ## 578 ## callbacks ##
583 579
584 def serverDisco(self, disco, profile): 580 def serverDisco(self, disco, profile):
585 """xep-0030 Discovery Protocol.""" 581 """xep-0030 Discovery Protocol."""
586 for feature in disco.features: 582 for feature in disco.features:
587 debug (_("Feature found: %s"),feature) 583 debug(_("Feature found: %s"), feature)
588 self.memory.addServerFeature(feature, profile) 584 self.memory.addServerFeature(feature, profile)
589 for cat, type in disco.identities: 585 for cat, type in disco.identities:
590 debug (_("Identity found: [%(category)s/%(type)s] %(identity)s") % {'category':cat, 'type':type, 'identity':disco.identities[(cat,type)]}) 586 debug(_("Identity found: [%(category)s/%(type)s] %(identity)s") % {'category': cat, 'type': type, 'identity': disco.identities[(cat, type)]})
591 587
592 def serverDiscoItems(self, disco_result, disco_client, profile, initialized): 588 def serverDiscoItems(self, disco_result, disco_client, profile, initialized):
593 """xep-0030 Discovery Protocol. 589 """xep-0030 Discovery Protocol.
594 @param disco_result: result of the disco item querry 590 @param disco_result: result of the disco item querry
595 @param disco_client: SatDiscoProtocol instance 591 @param disco_client: SatDiscoProtocol instance
596 @param profile: profile of the user 592 @param profile: profile of the user
597 @param initialized: deferred which must be chained when everything is done""" 593 @param initialized: deferred which must be chained when everything is done"""
598 594
599 def _check_entity_cb(result, entity, profile): 595 def _check_entity_cb(result, entity, profile):
600 for category, type in result.identities: 596 for category, type in result.identities:
601 debug (_('Identity added: (%(category)s,%(type)s) ==> %(entity)s [%(profile)s]') % { 597 debug(_('Identity added: (%(category)s,%(type)s) ==> %(entity)s [%(profile)s]') % {
602 'category':category, 'type':type, 'entity':entity, 'profile':profile}) 598 'category': category, 'type': type, 'entity': entity, 'profile': profile})
603 self.memory.addServerIdentity(category, type, entity, profile) 599 self.memory.addServerIdentity(category, type, entity, profile)
604 600
605 def _errback(result, entity, profile): 601 def _errback(result, entity, profile):
606 warning(_("Can't get information on identity [%(entity)s] for profile [%(profile)s]") % {'entity':entity, 'profile': profile}) 602 warning(_("Can't get information on identity [%(entity)s] for profile [%(profile)s]") % {'entity': entity, 'profile': profile})
607 603
608 defer_list = [] 604 defer_list = []
609 for item in disco_result._items: 605 for item in disco_result._items:
610 if item.entity.full().count('.') == 1: #XXX: workaround for a bug on jabberfr, tmp 606 if item.entity.full().count('.') == 1: # XXX: workaround for a bug on jabberfr, tmp
611 warning(_('Using jabberfr workaround, be sure your domain has at least two levels (e.g. "example.tld", not "example" alone)')) 607 warning(_('Using jabberfr workaround, be sure your domain has at least two levels (e.g. "example.tld", not "example" alone)'))
612 continue 608 continue
613 args = [item.entity, profile] 609 args = [item.entity, profile]
614 defer_list.append(disco_client.requestInfo(item.entity).addCallbacks(_check_entity_cb, _errback, args, None, args)) 610 defer_list.append(disco_client.requestInfo(item.entity).addCallbacks(_check_entity_cb, _errback, args, None, args))
615 defer.DeferredList(defer_list).chainDeferred(initialized) 611 defer.DeferredList(defer_list).chainDeferred(initialized)
616
617
618 ## Generic HMI ## 612 ## Generic HMI ##
619 613
620 def actionResult(self, action_id, action_type, data, profile): 614 def actionResult(self, action_id, action_type, data, profile):
621 """Send the result of an action 615 """Send the result of an action
622 @param action_id: same action_id used with action 616 @param action_id: same action_id used with action
634 if action_type != "DICT_DICT": 628 if action_type != "DICT_DICT":
635 error(_("action_type for actionResultExt must be DICT_DICT, fixing it")) 629 error(_("action_type for actionResultExt must be DICT_DICT, fixing it"))
636 action_type = "DICT_DICT" 630 action_type = "DICT_DICT"
637 self.bridge.actionResultExt(action_type, action_id, data, profile) 631 self.bridge.actionResultExt(action_type, action_id, data, profile)
638 632
639
640
641 def askConfirmation(self, conf_id, conf_type, data, cb, profile): 633 def askConfirmation(self, conf_id, conf_type, data, cb, profile):
642 """Add a confirmation callback 634 """Add a confirmation callback
643 @param conf_id: conf_id used to get answer 635 @param conf_id: conf_id used to get answer
644 @param conf_type: confirmation conf_type ("YES/NO", "FILE_TRANSFER") 636 @param conf_type: confirmation conf_type ("YES/NO", "FILE_TRANSFER")
645 @param data: data (depend of confirmation conf_type) 637 @param data: data (depend of confirmation conf_type)
646 @param cb: callback called with the answer 638 @param cb: callback called with the answer
647 """ 639 """
648 client = self.getClient(profile) 640 client = self.getClient(profile)
649 if not client: 641 if not client:
650 raise ProfileUnknownError(_("Asking confirmation a non-existant profile")) 642 raise ProfileUnknownError(_("Asking confirmation a non-existant profile"))
651 if client._waiting_conf.has_key(conf_id): 643 if conf_id in client._waiting_conf:
652 error (_("Attempt to register two callbacks for the same confirmation")) 644 error(_("Attempt to register two callbacks for the same confirmation"))
653 else: 645 else:
654 client._waiting_conf[conf_id] = (conf_type, data, cb) 646 client._waiting_conf[conf_id] = (conf_type, data, cb)
655 self.bridge.askConfirmation(conf_id, conf_type, data, profile) 647 self.bridge.askConfirmation(conf_id, conf_type, data, profile)
656
657 648
658 def confirmationAnswer(self, conf_id, accepted, data, profile): 649 def confirmationAnswer(self, conf_id, accepted, data, profile):
659 """Called by frontends to answer confirmation requests""" 650 """Called by frontends to answer confirmation requests"""
660 client = self.getClient(profile) 651 client = self.getClient(profile)
661 if not client: 652 if not client:
662 raise ProfileUnknownError(_("Confirmation answer from a non-existant profile")) 653 raise ProfileUnknownError(_("Confirmation answer from a non-existant profile"))
663 debug (_("Received confirmation answer for conf_id [%(conf_id)s]: %(success)s") % {'conf_id': conf_id, 'success':_("accepted") if accepted else _("refused")}) 654 debug(_("Received confirmation answer for conf_id [%(conf_id)s]: %(success)s") % {'conf_id': conf_id, 'success': _("accepted") if accepted else _("refused")})
664 if not client._waiting_conf.has_key(conf_id): 655 if conf_id not in client._waiting_conf:
665 error (_("Received an unknown confirmation (%(id)s for %(profile)s)") % {'id': conf_id, 'profile': profile}) 656 error(_("Received an unknown confirmation (%(id)s for %(profile)s)") % {'id': conf_id, 'profile': profile})
666 else: 657 else:
667 cb = client._waiting_conf[conf_id][-1] 658 cb = client._waiting_conf[conf_id][-1]
668 del client._waiting_conf[conf_id] 659 del client._waiting_conf[conf_id]
669 cb(conf_id, accepted, data, profile) 660 cb(conf_id, accepted, data, profile)
670 661
678 def removeProgressCB(self, progress_id, profile): 669 def removeProgressCB(self, progress_id, profile):
679 """Remove a progress callback""" 670 """Remove a progress callback"""
680 client = self.getClient(profile) 671 client = self.getClient(profile)
681 if not client: 672 if not client:
682 raise ProfileUnknownError 673 raise ProfileUnknownError
683 if not client._progress_cb_map.has_key(progress_id): 674 if progress_id not in client._progress_cb_map:
684 error (_("Trying to remove an unknow progress callback")) 675 error(_("Trying to remove an unknow progress callback"))
685 else: 676 else:
686 del client._progress_cb_map[progress_id] 677 del client._progress_cb_map[progress_id]
687 678
688 def getProgress(self, progress_id, profile): 679 def getProgress(self, progress_id, profile):
689 """Return a dict with progress information 680 """Return a dict with progress information
705 """Register a callback called for general reason""" 696 """Register a callback called for general reason"""
706 self.__general_cb_map[name] = CB 697 self.__general_cb_map[name] = CB
707 698
708 def removeGeneralCB(self, name): 699 def removeGeneralCB(self, name):
709 """Remove a general callback""" 700 """Remove a general callback"""
710 if not self.__general_cb_map.has_key(name): 701 if name not in self.__general_cb_map:
711 error (_("Trying to remove an unknow general callback")) 702 error(_("Trying to remove an unknow general callback"))
712 else: 703 else:
713 del self.__general_cb_map[name] 704 del self.__general_cb_map[name]
714 705
715 def callGeneralCB(self, name, *args, **kwargs): 706 def callGeneralCB(self, name, *args, **kwargs):
716 """Call general function back""" 707 """Call general function back"""
720 error(_("Trying to call unknown function (%s)") % name) 711 error(_("Trying to call unknown function (%s)") % name)
721 return None 712 return None
722 713
723 #Menus management 714 #Menus management
724 715
725 def importMenu(self, category, name, callback, help_string = "", type = "NORMAL"): 716 def importMenu(self, category, name, callback, help_string="", type="NORMAL"):
726 """register a new menu for frontends 717 """register a new menu for frontends
727 @param category: category of the menu 718 @param category: category of the menu
728 @param name: menu item entry 719 @param name: menu item entry
729 @param callback: method to be called when menuitem is selected""" 720 @param callback: method to be called when menuitem is selected"""
730 if self.menus.has_key((category,name)): 721 if (category, name) in self.menus:
731 error ("Want to register a menu which already existe") 722 error("Want to register a menu which already existe")
732 return 723 return
733 self.menus[(category,name,type)] = {'callback':callback, 'help_string':help_string, 'type':type} 724 self.menus[(category, name, type)] = {'callback': callback, 'help_string': help_string, 'type': type}
734 725
735 def getMenus(self): 726 def getMenus(self):
736 """Return all menus registered""" 727 """Return all menus registered"""
737 return self.menus.keys() 728 return self.menus.keys()
738 729
739 def getMenuHelp(self, category, name, type="NORMAL"): 730 def getMenuHelp(self, category, name, type="NORMAL"):
740 """return the help string of the menu""" 731 """return the help string of the menu"""
741 try: 732 try:
742 return self.menus[(category,name,type)]['help_string'] 733 return self.menus[(category, name, type)]['help_string']
743 except KeyError: 734 except KeyError:
744 error (_("Trying to access an unknown menu")) 735 error(_("Trying to access an unknown menu"))
745 return "" 736 return ""
746 737
747 def callMenu(self, category, name, type="NORMAL", profile_key='@DEFAULT@'): 738 def callMenu(self, category, name, type="NORMAL", profile_key='@DEFAULT@'):
748 """return the id of the action""" 739 """return the id of the action"""
749 profile = self.memory.getProfileName(profile_key) 740 profile = self.memory.getProfileName(profile_key)
750 if not profile_key: 741 if not profile_key:
751 error (_('Non-exsitant profile')) 742 error(_('Non-exsitant profile'))
752 return "" 743 return ""
753 if self.menus.has_key((category,name,type)): 744 if (category, name, type) in self.menus:
754 id = self.get_next_id() 745 id = self.get_next_id()
755 self.menus[(category,name,type)]['callback'](id, profile) 746 self.menus[(category, name, type)]['callback'](id, profile)
756 return id 747 return id
757 else: 748 else:
758 error (_("Trying to access an unknown menu (%(category)s/%(name)s/%(type)s)")%{'category':category, 'name':name,'type':type}) 749 error(_("Trying to access an unknown menu (%(category)s/%(name)s/%(type)s)") % {'category': category, 'name': name, 'type': type})
759 return "" 750 return ""