Mercurial > libervia-backend
comparison src/core/sat_main.py @ 1367:f71a0fc26886
merged branch frontends_multi_profiles
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 18 Mar 2015 10:52:28 +0100 |
parents | ba87b940f07a |
children | 0befb14ecf62 |
comparison
equal
deleted
inserted
replaced
1295:1e3b1f9ad6e2 | 1367:f71a0fc26886 |
---|---|
81 sys.exit(1) | 81 sys.exit(1) |
82 self.bridge.register("getReady", lambda: self._initialised) | 82 self.bridge.register("getReady", lambda: self._initialised) |
83 self.bridge.register("getVersion", lambda: C.APP_VERSION) | 83 self.bridge.register("getVersion", lambda: C.APP_VERSION) |
84 self.bridge.register("getProfileName", self.memory.getProfileName) | 84 self.bridge.register("getProfileName", self.memory.getProfileName) |
85 self.bridge.register("getProfilesList", self.memory.getProfilesList) | 85 self.bridge.register("getProfilesList", self.memory.getProfilesList) |
86 self.bridge.register("getEntityData", lambda _jid, keys, profile: self.memory.getEntityData(jid.JID(_jid), keys, profile)) | 86 self.bridge.register("getEntityData", lambda jid_, keys, profile: self.memory.getEntityData(jid.JID(jid_), keys, profile)) |
87 self.bridge.register("getEntitiesData", self.memory._getEntitiesData) | |
87 self.bridge.register("asyncCreateProfile", self.memory.asyncCreateProfile) | 88 self.bridge.register("asyncCreateProfile", self.memory.asyncCreateProfile) |
88 self.bridge.register("asyncDeleteProfile", self.memory.asyncDeleteProfile) | 89 self.bridge.register("asyncDeleteProfile", self.memory.asyncDeleteProfile) |
89 self.bridge.register("asyncConnect", self.asyncConnect) | 90 self.bridge.register("asyncConnect", self.asyncConnect) |
90 self.bridge.register("disconnect", self.disconnect) | 91 self.bridge.register("disconnect", self.disconnect) |
91 self.bridge.register("getContacts", self.getContacts) | 92 self.bridge.register("getContacts", self.getContacts) |
92 self.bridge.register("getContactsFromGroup", self.getContactsFromGroup) | 93 self.bridge.register("getContactsFromGroup", self.getContactsFromGroup) |
93 self.bridge.register("getLastResource", self.memory._getLastResource) | 94 self.bridge.register("getMainResource", self.memory._getMainResource) |
94 self.bridge.register("getPresenceStatuses", self.memory._getPresenceStatuses) | 95 self.bridge.register("getPresenceStatuses", self.memory._getPresenceStatuses) |
95 self.bridge.register("getWaitingSub", self.memory.getWaitingSub) | 96 self.bridge.register("getWaitingSub", self.memory.getWaitingSub) |
96 self.bridge.register("getWaitingConf", self.getWaitingConf) | 97 self.bridge.register("getWaitingConf", self.getWaitingConf) |
97 self.bridge.register("sendMessage", self._sendMessage) | 98 self.bridge.register("sendMessage", self._sendMessage) |
98 self.bridge.register("getConfig", self._getConfig) | 99 self.bridge.register("getConfig", self._getConfig) |
262 | 263 |
263 plugin_conn_cb = [] | 264 plugin_conn_cb = [] |
264 for plugin in self.plugins.iteritems(): | 265 for plugin in self.plugins.iteritems(): |
265 if plugin[1].is_handler: | 266 if plugin[1].is_handler: |
266 plugin[1].getHandler(profile).setHandlerParent(current) | 267 plugin[1].getHandler(profile).setHandlerParent(current) |
267 connected_cb = getattr(plugin[1], "profileConnected", None) | 268 connected_cb = getattr(plugin[1], "profileConnected", None) # profile connected is called after client is ready and roster is got |
268 if connected_cb: | 269 if connected_cb: |
269 plugin_conn_cb.append((plugin[0], connected_cb)) | 270 plugin_conn_cb.append((plugin[0], connected_cb)) |
271 try: | |
272 yield plugin[1].profileConnecting(profile) # profile connecting is called before actually starting client | |
273 except AttributeError: | |
274 pass | |
270 | 275 |
271 current.startService() | 276 current.startService() |
272 | 277 |
273 yield current.getConnectionDeferred() | 278 yield current.getConnectionDeferred() |
274 yield current.roster.got_roster # we want to be sure that we got the roster | 279 yield current.roster.got_roster # we want to be sure that we got the roster |
287 if not success: | 292 if not success: |
288 log.error("error (plugin %(name)s): %(failure)s" % | 293 log.error("error (plugin %(name)s): %(failure)s" % |
289 {'name': plugin_conn_cb[idx][0], 'failure': result}) | 294 {'name': plugin_conn_cb[idx][0], 'failure': result}) |
290 | 295 |
291 yield list_d.addCallback(logPluginResults) # FIXME: we should have a timeout here, and a way to know if a plugin freeze | 296 yield list_d.addCallback(logPluginResults) # FIXME: we should have a timeout here, and a way to know if a plugin freeze |
292 # TODO: mesure time to launch of each plugin | 297 # TODO: mesure launch time of each plugin |
293 | 298 |
294 def _authenticateProfile(self, password, profile): | 299 def _authenticateProfile(self, password, profile): |
295 """Authenticate the profile. | 300 """Authenticate the profile. |
296 | 301 |
297 @param password (string): the SàT profile password | 302 @param password (string): the SàT profile password |
329 if disconnected_cb: | 334 if disconnected_cb: |
330 disconnected_cb(profile) | 335 disconnected_cb(profile) |
331 | 336 |
332 def getContacts(self, profile_key): | 337 def getContacts(self, profile_key): |
333 client = self.getClient(profile_key) | 338 client = self.getClient(profile_key) |
334 ret = [] | 339 def got_roster(dummy): |
335 for item in client.roster.getItems(): # we get all items for client's roster | 340 ret = [] |
336 # and convert them to expected format | 341 for item in client.roster.getItems(): # we get all items for client's roster |
337 attr = client.roster.getAttributes(item) | 342 # and convert them to expected format |
338 ret.append([item.jid.userhost(), attr, item.groups]) | 343 attr = client.roster.getAttributes(item) |
339 return ret | 344 ret.append([item.jid.userhost(), attr, item.groups]) |
345 return ret | |
346 | |
347 return client.roster.got_roster.addCallback(got_roster) | |
340 | 348 |
341 def getContactsFromGroup(self, group, profile_key): | 349 def getContactsFromGroup(self, group, profile_key): |
342 client = self.getClient(profile_key) | 350 client = self.getClient(profile_key) |
343 return [jid_.full() for jid_ in client.roster.getJidsFromGroup(group)] | 351 return [jid_.full() for jid_ in client.roster.getJidsFromGroup(group)] |
344 | 352 |
454 return self.sendMessage(to_jid, msg, subject, mess_type, {unicode(key): unicode(value) for key, value in extra.items()}, profile_key=profile_key) | 462 return self.sendMessage(to_jid, msg, subject, mess_type, {unicode(key): unicode(value) for key, value in extra.items()}, profile_key=profile_key) |
455 | 463 |
456 def sendMessage(self, to_jid, msg, subject=None, mess_type='auto', extra={}, no_trigger=False, profile_key=C.PROF_KEY_NONE): | 464 def sendMessage(self, to_jid, msg, subject=None, mess_type='auto', extra={}, no_trigger=False, profile_key=C.PROF_KEY_NONE): |
457 #FIXME: check validity of recipient | 465 #FIXME: check validity of recipient |
458 profile = self.memory.getProfileName(profile_key) | 466 profile = self.memory.getProfileName(profile_key) |
459 assert(profile) | 467 assert profile |
460 client = self.profiles[profile] | 468 client = self.profiles[profile] |
461 if extra is None: | 469 if extra is None: |
462 extra = {} | 470 extra = {} |
463 mess_data = { # we put data in a dict, so trigger methods can change them | 471 mess_data = { # we put data in a dict, so trigger methods can change them |
464 "to": to_jid, | 472 "to": to_jid, |
477 mess_data["type"] = 'normal' | 485 mess_data["type"] = 'normal' |
478 elif not mess_data["to"].resource: # if to JID has a resource, the type is not 'groupchat' | 486 elif not mess_data["to"].resource: # if to JID has a resource, the type is not 'groupchat' |
479 # we may have a groupchat message, we check if the we know this jid | 487 # we may have a groupchat message, we check if the we know this jid |
480 try: | 488 try: |
481 entity_type = self.memory.getEntityData(mess_data["to"], ['type'], profile)["type"] | 489 entity_type = self.memory.getEntityData(mess_data["to"], ['type'], profile)["type"] |
482 #FIXME: should entity_type manage ressources ? | 490 #FIXME: should entity_type manage resources ? |
483 except (exceptions.UnknownEntityError, KeyError): | 491 except (exceptions.UnknownEntityError, KeyError): |
484 entity_type = "contact" | 492 entity_type = "contact" |
485 | 493 |
486 if entity_type == "chatroom": | 494 if entity_type == "chatroom": |
487 mess_data["type"] = 'groupchat' | 495 mess_data["type"] = 'groupchat' |
495 | 503 |
496 if not no_trigger and not send_only: | 504 if not no_trigger and not send_only: |
497 if not self.trigger.point("sendMessage", mess_data, pre_xml_treatments, post_xml_treatments, profile): | 505 if not self.trigger.point("sendMessage", mess_data, pre_xml_treatments, post_xml_treatments, profile): |
498 return defer.succeed(None) | 506 return defer.succeed(None) |
499 | 507 |
500 log.debug(_("Sending jabber message of type [%(type)s] to %(to)s...") % {"type": mess_data["type"], "to": to_jid.full()}) | 508 log.debug(_(u"Sending message (type {type}, to {to})").format(type=mess_data["type"], to=to_jid.full())) |
501 | 509 |
502 def cancelErrorTrap(failure): | 510 def cancelErrorTrap(failure): |
503 """A message sending can be cancelled by a plugin treatment""" | 511 """A message sending can be cancelled by a plugin treatment""" |
504 failure.trap(exceptions.CancelError) | 512 failure.trap(exceptions.CancelError) |
505 | 513 |
570 def setPresence(self, to_jid=None, show="", statuses=None, profile_key=C.PROF_KEY_NONE): | 578 def setPresence(self, to_jid=None, show="", statuses=None, profile_key=C.PROF_KEY_NONE): |
571 """Send our presence information""" | 579 """Send our presence information""" |
572 if statuses is None: | 580 if statuses is None: |
573 statuses = {} | 581 statuses = {} |
574 profile = self.memory.getProfileName(profile_key) | 582 profile = self.memory.getProfileName(profile_key) |
575 assert(profile) | 583 assert profile |
576 priority = int(self.memory.getParamA("Priority", "Connection", profile_key=profile)) | 584 priority = int(self.memory.getParamA("Priority", "Connection", profile_key=profile)) |
577 self.profiles[profile].presence.available(to_jid, show, statuses, priority) | 585 self.profiles[profile].presence.available(to_jid, show, statuses, priority) |
578 #XXX: FIXME: temporary fix to work around openfire 3.7.0 bug (presence is not broadcasted to generating resource) | 586 #XXX: FIXME: temporary fix to work around openfire 3.7.0 bug (presence is not broadcasted to generating resource) |
579 if '' in statuses: | 587 if '' in statuses: |
580 statuses['default'] = statuses[''] | 588 statuses['default'] = statuses[''] |
586 """Called to manage subscription | 594 """Called to manage subscription |
587 @param subs_type: subsciption type (cf RFC 3921) | 595 @param subs_type: subsciption type (cf RFC 3921) |
588 @param raw_jid: unicode entity's jid | 596 @param raw_jid: unicode entity's jid |
589 @param profile_key: profile""" | 597 @param profile_key: profile""" |
590 profile = self.memory.getProfileName(profile_key) | 598 profile = self.memory.getProfileName(profile_key) |
591 assert(profile) | 599 assert profile |
592 to_jid = jid.JID(raw_jid) | 600 to_jid = jid.JID(raw_jid) |
593 log.debug(_('subsciption request [%(subs_type)s] for %(jid)s') % {'subs_type': subs_type, 'jid': to_jid.full()}) | 601 log.debug(_('subsciption request [%(subs_type)s] for %(jid)s') % {'subs_type': subs_type, 'jid': to_jid.full()}) |
594 if subs_type == "subscribe": | 602 if subs_type == "subscribe": |
595 self.profiles[profile].presence.subscribe(to_jid) | 603 self.profiles[profile].presence.subscribe(to_jid) |
596 elif subs_type == "subscribed": | 604 elif subs_type == "subscribed": |
604 return self.addContact(jid.JID(to_jid_s), profile_key) | 612 return self.addContact(jid.JID(to_jid_s), profile_key) |
605 | 613 |
606 def addContact(self, to_jid, profile_key): | 614 def addContact(self, to_jid, profile_key): |
607 """Add a contact in roster list""" | 615 """Add a contact in roster list""" |
608 profile = self.memory.getProfileName(profile_key) | 616 profile = self.memory.getProfileName(profile_key) |
609 assert(profile) | 617 assert profile |
610 #self.profiles[profile].roster.addItem(to_jid) #XXX: disabled (cf http://wokkel.ik.nu/ticket/56)) | 618 # presence is sufficient, as a roster push will be sent according to RFC 6121 §3.1.2 |
611 self.profiles[profile].presence.subscribe(to_jid) | 619 self.profiles[profile].presence.subscribe(to_jid) |
612 | 620 |
613 def _updateContact(self, to_jid_s, name, groups, profile_key): | 621 def _updateContact(self, to_jid_s, name, groups, profile_key): |
614 return self.updateContact(jid.JID(to_jid_s), name, groups, profile_key) | 622 return self.updateContact(jid.JID(to_jid_s), name, groups, profile_key) |
615 | 623 |
616 def updateContact(self, to_jid, name, groups, profile_key): | 624 def updateContact(self, to_jid, name, groups, profile_key): |
617 """update a contact in roster list""" | 625 """update a contact in roster list""" |
618 profile = self.memory.getProfileName(profile_key) | 626 profile = self.memory.getProfileName(profile_key) |
619 assert(profile) | 627 assert profile |
620 groups = set(groups) | 628 groups = set(groups) |
621 roster_item = RosterItem(to_jid) | 629 roster_item = RosterItem(to_jid) |
622 roster_item.name = name or None | 630 roster_item.name = name or None |
623 roster_item.groups = set(groups) | 631 roster_item.groups = set(groups) |
624 self.profiles[profile].roster.updateItem(roster_item) | 632 return self.profiles[profile].roster.setItem(roster_item) |
625 | 633 |
626 def _delContact(self, to_jid_s, profile_key): | 634 def _delContact(self, to_jid_s, profile_key): |
627 return self.delContact(jid.JID(to_jid_s), profile_key) | 635 return self.delContact(jid.JID(to_jid_s), profile_key) |
628 | 636 |
629 def delContact(self, to_jid, profile_key): | 637 def delContact(self, to_jid, profile_key): |
630 """Remove contact from roster list""" | 638 """Remove contact from roster list""" |
631 profile = self.memory.getProfileName(profile_key) | 639 profile = self.memory.getProfileName(profile_key) |
632 assert(profile) | 640 assert profile |
633 self.profiles[profile].roster.removeItem(to_jid) | 641 self.profiles[profile].presence.unsubscribe(to_jid) # is not asynchronous |
634 self.profiles[profile].presence.unsubscribe(to_jid) | 642 return self.profiles[profile].roster.removeItem(to_jid) |
635 | |
636 | 643 |
637 ## Discovery ## | 644 ## Discovery ## |
638 # discovery methods are shortcuts to self.memory.disco | 645 # discovery methods are shortcuts to self.memory.disco |
639 # the main difference with client.disco is that self.memory.disco manage cache | 646 # the main difference with client.disco is that self.memory.disco manage cache |
640 | 647 |
768 @param callback_id: id of the action (callback) to launch | 775 @param callback_id: id of the action (callback) to launch |
769 @param data: optional data | 776 @param data: optional data |
770 @profile_key: %(doc_profile_key)s | 777 @profile_key: %(doc_profile_key)s |
771 @return: a deferred which fire a dict where key can be: | 778 @return: a deferred which fire a dict where key can be: |
772 - xmlui: a XMLUI need to be displayed | 779 - xmlui: a XMLUI need to be displayed |
780 - validated: if present, can be used to launch a callback, it can have the values | |
781 - C.BOOL_TRUE | |
782 - C.BOOL_FALSE | |
773 """ | 783 """ |
774 profile = self.memory.getProfileName(profile_key) | 784 profile = self.memory.getProfileName(profile_key) |
775 if not profile: | 785 if not profile: |
776 raise exceptions.ProfileUnknownError(_('trying to launch action with a non-existant profile')) | 786 raise exceptions.ProfileUnknownError(_('trying to launch action with a non-existant profile')) |
777 | 787 |
846 | 856 |
847 return callback_id | 857 return callback_id |
848 | 858 |
849 def getMenus(self, language='', security_limit=C.NO_SECURITY_LIMIT): | 859 def getMenus(self, language='', security_limit=C.NO_SECURITY_LIMIT): |
850 """Return all menus registered | 860 """Return all menus registered |
861 | |
851 @param language: language used for translation, or empty string for default | 862 @param language: language used for translation, or empty string for default |
852 @param security_limit: %(doc_security_limit)s | 863 @param security_limit: %(doc_security_limit)s |
853 @return: array of tuple with: | 864 @return: array of tuple with: |
854 - menu id (same as callback_id) | 865 - menu id (same as callback_id) |
855 - menu type | 866 - menu type |
856 - raw menu path (array of strings) | 867 - raw menu path (array of strings) |
857 - translated menu path | 868 - translated menu path |
858 | 869 - extra (dict(unicode, unicode)): extra data where key can be: |
870 - icon: name of the icon to use (TODO) | |
871 - help_url: link to a page with more complete documentation (TODO) | |
859 """ | 872 """ |
860 ret = [] | 873 ret = [] |
861 for menu_id, menu_data in self._menus.iteritems(): | 874 for menu_id, menu_data in self._menus.iteritems(): |
862 type_ = menu_data['type'] | 875 type_ = menu_data['type'] |
863 path = menu_data['path'] | 876 path = menu_data['path'] |
865 if security_limit!=C.NO_SECURITY_LIMIT and (menu_security_limit==C.NO_SECURITY_LIMIT or menu_security_limit>security_limit): | 878 if security_limit!=C.NO_SECURITY_LIMIT and (menu_security_limit==C.NO_SECURITY_LIMIT or menu_security_limit>security_limit): |
866 continue | 879 continue |
867 languageSwitch(language) | 880 languageSwitch(language) |
868 path_i18n = [_(elt) for elt in path] | 881 path_i18n = [_(elt) for elt in path] |
869 languageSwitch() | 882 languageSwitch() |
870 ret.append((menu_id, type_, path, path_i18n)) | 883 extra = {} # TODO: manage extra data like icon |
884 ret.append((menu_id, type_, path, path_i18n, extra)) | |
871 | 885 |
872 return ret | 886 return ret |
873 | 887 |
874 def getMenuHelp(self, menu_id, language=''): | 888 def getMenuHelp(self, menu_id, language=''): |
875 """ | 889 """ |