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