comparison src/core/sat_main.py @ 587:952322b1d490

Remove trailing whitespaces.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Fri, 18 Jan 2013 17:55:34 +0100
parents 133078b82ca8
children d1b4805124a1
comparison
equal deleted inserted replaced
586:6a718ede8be1 587:952322b1d490
63 global sat_id 63 global sat_id
64 sat_id+=1 64 sat_id+=1
65 return "sat_id_"+str(sat_id) 65 return "sat_id_"+str(sat_id)
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()
71 71
72 def get_const(self, name): 72 def get_const(self, name):
73 """Return a constant""" 73 """Return a constant"""
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 CONST.has_key(name):
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))
145 self.bridge.register("confirmationAnswer", self.confirmationAnswer) 145 self.bridge.register("confirmationAnswer", self.confirmationAnswer)
146 self.bridge.register("getProgress", self.getProgress) 146 self.bridge.register("getProgress", self.getProgress)
147 self.bridge.register("getMenus", self.getMenus) 147 self.bridge.register("getMenus", self.getMenus)
148 self.bridge.register("getMenuHelp", self.getMenuHelp) 148 self.bridge.register("getMenuHelp", self.getMenuHelp)
149 self.bridge.register("callMenu", self.callMenu) 149 self.bridge.register("callMenu", self.callMenu)
150 150
151 self.memory.initialized.addCallback(self._postMemoryInit) 151 self.memory.initialized.addCallback(self._postMemoryInit)
152 152
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 158
159 def _import_plugins(self): 159 def _import_plugins(self):
160 """Import all plugins found in plugins directory""" 160 """Import all plugins found in plugins directory"""
161 import sat.plugins 161 import sat.plugins
162 plugins_path = os.path.dirname(sat.plugins.__file__) 162 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")))] 163 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 164 __plugins_to_import = {} #plugins we still have to import
165 for plug in plug_lst: 165 for plug in plug_lst:
166 plugin_path = 'sat.plugins.'+plug 166 plugin_path = 'sat.plugins.'+plug
167 __import__(plugin_path) 167 __import__(plugin_path)
196 self.plugins[import_name].is_handler = True 196 self.plugins[import_name].is_handler = True
197 else: 197 else:
198 self.plugins[import_name].is_handler = False 198 self.plugins[import_name].is_handler = False
199 #TODO: test xmppclient presence and register handler parent 199 #TODO: test xmppclient presence and register handler parent
200 200
201 201
202 def connect(self, profile_key = '@DEFAULT@'): 202 def connect(self, profile_key = '@DEFAULT@'):
203 """Connect to jabber server""" 203 """Connect to jabber server"""
204 self.asyncConnect(profile_key) 204 self.asyncConnect(profile_key)
205 205
206 def asyncConnect(self, profile_key = '@DEFAULT@'): 206 def asyncConnect(self, profile_key = '@DEFAULT@'):
207 """Connect to jabber server with asynchronous reply 207 """Connect to jabber server with asynchronous reply
208 @param profile_key: %(doc_profile)s 208 @param profile_key: %(doc_profile)s
209 """ 209 """
210 210
211 profile = self.memory.getProfileName(profile_key) 211 profile = self.memory.getProfileName(profile_key)
212 if not profile: 212 if not profile:
213 error (_('Trying to connect a non-exsitant profile')) 213 error (_('Trying to connect a non-exsitant profile'))
214 raise ProfileUnknownError(profile_key) 214 raise ProfileUnknownError(profile_key)
215 215
216 if (self.isConnected(profile)): 216 if (self.isConnected(profile)):
217 info(_("already connected !")) 217 info(_("already connected !"))
218 return defer.succeed("None") 218 return defer.succeed("None")
219 219
220 def afterMemoryInit(ignore): 220 def afterMemoryInit(ignore):
225 error(_("Can't parse port value, using default value")) 225 error(_("Can't parse port value, using default value"))
226 port = 5222 226 port = 5222
227 current = self.profiles[profile] = xmpp.SatXMPPClient(self, profile, 227 current = self.profiles[profile] = xmpp.SatXMPPClient(self, profile,
228 jid.JID(self.memory.getParamA("JabberID", "Connection", profile_key = profile), profile), 228 jid.JID(self.memory.getParamA("JabberID", "Connection", profile_key = profile), profile),
229 self.memory.getParamA("Password", "Connection", profile_key = profile), 229 self.memory.getParamA("Password", "Connection", profile_key = profile),
230 self.memory.getParamA("Server", "Connection", profile_key = profile), 230 self.memory.getParamA("Server", "Connection", profile_key = profile),
231 port) 231 port)
232 232
233 current.messageProt = xmpp.SatMessageProtocol(self) 233 current.messageProt = xmpp.SatMessageProtocol(self)
234 current.messageProt.setHandlerParent(current) 234 current.messageProt.setHandlerParent(current)
235 235
236 current.roster = xmpp.SatRosterProtocol(self) 236 current.roster = xmpp.SatRosterProtocol(self)
237 current.roster.setHandlerParent(current) 237 current.roster.setHandlerParent(current)
238 238
239 current.presence = xmpp.SatPresenceProtocol(self) 239 current.presence = xmpp.SatPresenceProtocol(self)
240 current.presence.setHandlerParent(current) 240 current.presence.setHandlerParent(current)
245 current.versionHandler = xmpp.SatVersionHandler(self.get_const('client_name'), 245 current.versionHandler = xmpp.SatVersionHandler(self.get_const('client_name'),
246 self.get_const('client_version')) 246 self.get_const('client_version'))
247 current.versionHandler.setHandlerParent(current) 247 current.versionHandler.setHandlerParent(current)
248 248
249 debug (_("setting plugins parents")) 249 debug (_("setting plugins parents"))
250 250
251 for plugin in self.plugins.iteritems(): 251 for plugin in self.plugins.iteritems():
252 if plugin[1].is_handler: 252 if plugin[1].is_handler:
253 plugin[1].getHandler(profile).setHandlerParent(current) 253 plugin[1].getHandler(profile).setHandlerParent(current)
254 connected_cb = getattr(plugin[1], "profileConnected", None) 254 connected_cb = getattr(plugin[1], "profileConnected", None)
255 if connected_cb: 255 if connected_cb:
305 305
306 def startService(self): 306 def startService(self):
307 info("Salut à toi ô mon frère !") 307 info("Salut à toi ô mon frère !")
308 #TODO: manage autoconnect 308 #TODO: manage autoconnect
309 #self.connect() 309 #self.connect()
310 310
311 def stopService(self): 311 def stopService(self):
312 self.memory.save() 312 self.memory.save()
313 info("Salut aussi à Rantanplan") 313 info("Salut aussi à Rantanplan")
314 314
315 def run(self): 315 def run(self):
316 debug(_("running app")) 316 debug(_("running app"))
317 reactor.run() 317 reactor.run()
318 318
319 def stop(self): 319 def stop(self):
320 debug(_("stopping app")) 320 debug(_("stopping app"))
321 reactor.stop() 321 reactor.stop()
322 322
323 ## Misc methods ## 323 ## Misc methods ##
324 324
325 def getJidNStream(self, profile_key): 325 def getJidNStream(self, profile_key):
326 """Convenient method to get jid and stream from profile key 326 """Convenient method to get jid and stream from profile key
327 @return: tuple (jid, xmlstream) from profile, can be None""" 327 @return: tuple (jid, xmlstream) from profile, can be None"""
328 profile = self.memory.getProfileName(profile_key) 328 profile = self.memory.getProfileName(profile_key)
329 if not profile or not self.profiles[profile].isConnected(): 329 if not profile or not self.profiles[profile].isConnected():
345 345
346 next_id = id or sat_next_id() #the id is used to send server's answer 346 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)) 347 serverRegistrer = xmlstream.XmlStreamFactory(xmpp.RegisteringAuthenticator(self, server, login, password, email, next_id, profile))
348 connector = reactor.connectTCP(server, port, serverRegistrer) 348 connector = reactor.connectTCP(server, port, serverRegistrer)
349 serverRegistrer.clientConnectionLost = lambda conn, reason: connector.disconnect() 349 serverRegistrer.clientConnectionLost = lambda conn, reason: connector.disconnect()
350 350
351 return next_id 351 return next_id
352 352
353 def registerNewAccountCB(self, id, data, profile): 353 def registerNewAccountCB(self, id, data, profile):
354 user = jid.parse(self.memory.getParamA("JabberID", "Connection", profile_key=profile))[0] 354 user = jid.parse(self.memory.getParamA("JabberID", "Connection", profile_key=profile))[0]
355 password = self.memory.getParamA("Password", "Connection", profile_key=profile) 355 password = self.memory.getParamA("Password", "Connection", profile_key=profile)
356 server = self.memory.getParamA("Server", "Connection", profile_key=profile) 356 server = self.memory.getParamA("Server", "Connection", profile_key=profile)
361 self.actionResult(id, "ERROR", {'message':_("No user, password or server given, can't register new account.")}, profile) 361 self.actionResult(id, "ERROR", {'message':_("No user, password or server given, can't register new account.")}, profile)
362 return 362 return
363 363
364 confirm_id = sat_next_id() 364 confirm_id = sat_next_id()
365 self.__private_data[confirm_id]=(id,profile) 365 self.__private_data[confirm_id]=(id,profile)
366 366
367 self.askConfirmation(confirm_id, "YES/NO", 367 self.askConfirmation(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}}, 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
391 """ 391 """
392 392
393 profile = self.memory.getProfileName(profile_key) 393 profile = self.memory.getProfileName(profile_key)
394 assert(profile) 394 assert(profile)
395 to_jid = jid.JID(target) 395 to_jid = jid.JID(target)
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':
454 error (_("Unknown action type")) 454 error (_("Unknown action type"))
455 return "" 455 return ""
456 456
457 457
458 ## jabber methods ## 458 ## jabber methods ##
459 459
460 def getWaitingConf(self, profile_key=None): 460 def getWaitingConf(self, profile_key=None):
461 assert(profile_key) 461 assert(profile_key)
462 client = self.getClient(profile_key) 462 client = self.getClient(profile_key)
463 if not client: 463 if not client:
464 raise ProfileNotInCacheError 464 raise ProfileNotInCacheError
465 ret = [] 465 ret = []
466 for conf_id in client._waiting_conf: 466 for conf_id in client._waiting_conf:
467 conf_type, data = client._waiting_conf[conf_id][:2] 467 conf_type, data = client._waiting_conf[conf_id][:2]
468 ret.append((conf_id, conf_type, data)) 468 ret.append((conf_id, conf_type, data))
469 return ret 469 return ret
470 470
471 def sendMessage(self, to, msg, subject=None, mess_type='auto', profile_key='@DEFAULT@'): 471 def sendMessage(self, to, msg, subject=None, mess_type='auto', profile_key='@DEFAULT@'):
472 #FIXME: check validity of recipient 472 #FIXME: check validity of recipient
473 profile = self.memory.getProfileName(profile_key) 473 profile = self.memory.getProfileName(profile_key)
474 assert(profile) 474 assert(profile)
475 client = self.profiles[profile] 475 client = self.profiles[profile]
476 current_jid = client.jid 476 current_jid = client.jid
477 mess_data = { #we put data in a dict, so trigger methods can change them 477 mess_data = { #we put data in a dict, so trigger methods can change them
478 "to": jid.JID(to), 478 "to": jid.JID(to),
479 "message": msg, 479 "message": msg,
480 "subject": subject, 480 "subject": subject,
481 "type": mess_type 481 "type": mess_type
482 } 482 }
483 483
484 if mess_data["type"] == "auto": 484 if mess_data["type"] == "auto":
485 # we try to guess the type 485 # we try to guess the type
486 if mess_data["subject"]: 486 if mess_data["subject"]:
487 mess_data["type"] = 'normal' 487 mess_data["type"] = 'normal'
488 elif not mess_data["to"].resource: #if to JID has a resource, the type is not 'groupchat' 488 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 489 #we may have a groupchat message, we check if the we know this jid
490 try: 490 try:
491 entity_type = self.memory.getEntityData(mess_data["to"], ['type'], profile)["type"] 491 entity_type = self.memory.getEntityData(mess_data["to"], ['type'], profile)["type"]
492 #FIXME: should entity_type manage ressources ? 492 #FIXME: should entity_type manage ressources ?
493 except (UnknownEntityError, KeyError): 493 except (UnknownEntityError, KeyError):
494 entity_type = "contact" 494 entity_type = "contact"
495 495
496 if entity_type == "chatroom": 496 if entity_type == "chatroom":
497 mess_data["type"] = 'groupchat' 497 mess_data["type"] = 'groupchat'
498 else: 498 else:
499 mess_data["type"] = 'chat' 499 mess_data["type"] = 'chat'
500 else: 500 else:
501 mess_data["type"] == 'chat' 501 mess_data["type"] == 'chat'
502 mess_data["type"] == "chat" if mess_data["subject"] else "normal" 502 mess_data["type"] == "chat" if mess_data["subject"] else "normal"
503 503
504 if not self.trigger.point("sendMessage", mess_data, profile): 504 if not self.trigger.point("sendMessage", mess_data, profile):
505 return 505 return
506 506
507 debug(_("Sending jabber message of type [%(type)s] to %(to)s...") % {"type": mess_data["type"], "to": to}) 507 debug(_("Sending jabber message of type [%(type)s] to %(to)s...") % {"type": mess_data["type"], "to": to})
508 message = domish.Element((None,'message')) 508 message = domish.Element((None,'message'))
509 message["to"] = mess_data["to"].full() 509 message["to"] = mess_data["to"].full()
510 message["from"] = current_jid.full() 510 message["from"] = current_jid.full()
511 message["type"] = mess_data["type"] 511 message["type"] = mess_data["type"]
529 if statuses.has_key(''): 529 if statuses.has_key(''):
530 statuses['default'] = statuses[''] 530 statuses['default'] = statuses['']
531 del statuses[''] 531 del statuses['']
532 self.bridge.presenceUpdate(self.profiles[profile].jid.full(), show, 532 self.bridge.presenceUpdate(self.profiles[profile].jid.full(), show,
533 int(priority), statuses, profile) 533 int(priority), statuses, profile)
534 534
535 535
536 def subscription(self, subs_type, raw_jid, profile_key): 536 def subscription(self, subs_type, raw_jid, profile_key):
537 """Called to manage subscription 537 """Called to manage subscription
538 @param subs_type: subsciption type (cf RFC 3921) 538 @param subs_type: subsciption type (cf RFC 3921)
539 @param raw_jid: unicode entity's jid 539 @param raw_jid: unicode entity's jid
540 @param profile_key: profile""" 540 @param profile_key: profile"""
590 debug (_("Identity found: [%(category)s/%(type)s] %(identity)s") % {'category':cat, 'type':type, 'identity':disco.identities[(cat,type)]}) 590 debug (_("Identity found: [%(category)s/%(type)s] %(identity)s") % {'category':cat, 'type':type, 'identity':disco.identities[(cat,type)]})
591 591
592 def serverDiscoItems(self, disco_result, disco_client, profile, initialized): 592 def serverDiscoItems(self, disco_result, disco_client, profile, initialized):
593 """xep-0030 Discovery Protocol. 593 """xep-0030 Discovery Protocol.
594 @param disco_result: result of the disco item querry 594 @param disco_result: result of the disco item querry
595 @param disco_client: SatDiscoProtocol instance 595 @param disco_client: SatDiscoProtocol instance
596 @param profile: profile of the user 596 @param profile: profile of the user
597 @param initialized: deferred which must be chained when everything is done""" 597 @param initialized: deferred which must be chained when everything is done"""
598 598
599 def _check_entity_cb(result, entity, profile): 599 def _check_entity_cb(result, entity, profile):
600 for category, type in result.identities: 600 for category, type in result.identities:
601 debug (_('Identity added: (%(category)s,%(type)s) ==> %(entity)s [%(profile)s]') % { 601 debug (_('Identity added: (%(category)s,%(type)s) ==> %(entity)s [%(profile)s]') % {
602 'category':category, 'type':type, 'entity':entity, 'profile':profile}) 602 'category':category, 'type':type, 'entity':entity, 'profile':profile})
603 self.memory.addServerIdentity(category, type, entity, profile) 603 self.memory.addServerIdentity(category, type, entity, profile)
604 604
605 def _errback(result, entity, profile): 605 def _errback(result, entity, profile):
606 warning(_("Can't get information on identity [%(entity)s] for profile [%(profile)s]") % {'entity':entity, 'profile': profile}) 606 warning(_("Can't get information on identity [%(entity)s] for profile [%(profile)s]") % {'entity':entity, 'profile': profile})
607 607
608 defer_list = [] 608 defer_list = []
609 for item in disco_result._items: 609 for item in disco_result._items:
610 if item.entity.full().count('.') == 1: #XXX: workaround for a bug on jabberfr, tmp 610 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)')) 611 warning(_('Using jabberfr workaround, be sure your domain has at least two levels (e.g. "example.tld", not "example" alone)'))
612 continue 612 continue
613 args = [item.entity, profile] 613 args = [item.entity, profile]
614 defer_list.append(disco_client.requestInfo(item.entity).addCallbacks(_check_entity_cb, _errback, args, None, args)) 614 defer_list.append(disco_client.requestInfo(item.entity).addCallbacks(_check_entity_cb, _errback, args, None, args))
615 defer.DeferredList(defer_list).chainDeferred(initialized) 615 defer.DeferredList(defer_list).chainDeferred(initialized)
616 616
617 617
618 ## Generic HMI ## 618 ## Generic HMI ##
619 619
620 def actionResult(self, action_id, action_type, data, profile): 620 def actionResult(self, action_id, action_type, data, profile):
621 """Send the result of an action 621 """Send the result of an action
622 @param action_id: same action_id used with action 622 @param action_id: same action_id used with action
623 @param action_type: result action_type ("PARAM", "SUCCESS", "ERROR", "XMLUI") 623 @param action_type: result action_type ("PARAM", "SUCCESS", "ERROR", "XMLUI")
624 @param data: dictionary 624 @param data: dictionary