Mercurial > libervia-backend
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 |