Mercurial > libervia-backend
comparison src/tools/memory.py @ 224:9c6ee3f9ab29
files reorganisation
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 04 Jan 2011 19:30:27 +0100 |
parents | src/sat/tools/memory.py@86d249b6d9b7 |
children | b1794cbb88e5 |
comparison
equal
deleted
inserted
replaced
223:86d249b6d9b7 | 224:9c6ee3f9ab29 |
---|---|
1 #!/usr/bin/python | |
2 # -*- coding: utf-8 -*- | |
3 | |
4 """ | |
5 SAT: a jabber client | |
6 Copyright (C) 2009, 2010 Jérôme Poisson (goffi@goffi.org) | |
7 | |
8 This program is free software: you can redistribute it and/or modify | |
9 it under the terms of the GNU General Public License as published by | |
10 the Free Software Foundation, either version 3 of the License, or | |
11 (at your option) any later version. | |
12 | |
13 This program is distributed in the hope that it will be useful, | |
14 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 GNU General Public License for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
19 along with this program. If not, see <http://www.gnu.org/licenses/>. | |
20 """ | |
21 | |
22 from __future__ import with_statement | |
23 | |
24 import os.path | |
25 import time | |
26 import cPickle as pickle | |
27 from xml.dom import minidom | |
28 from logging import debug, info, error | |
29 import pdb | |
30 from twisted.internet import defer | |
31 from twisted.words.protocols.jabber import jid | |
32 from sat.tools.xml_tools import paramsXml2xmlUI | |
33 | |
34 SAVEFILE_PARAM_XML="/param" #xml parameters template | |
35 SAVEFILE_PARAM_DATA="/param" #individual & general parameters; _ind and _gen suffixes will be added | |
36 SAVEFILE_HISTORY="/history" | |
37 SAVEFILE_PRIVATE="/private" #file used to store misc values (mainly for plugins) | |
38 | |
39 class Param(): | |
40 """This class manage parameters with xml""" | |
41 ### TODO: add desciption in params | |
42 | |
43 #TODO: move Watched in a plugin | |
44 default_xml = u""" | |
45 <params> | |
46 <general> | |
47 </general> | |
48 <individual> | |
49 <category name="Connection" label="%(category_connection)s"> | |
50 <param name="JabberID" value="goffi@necton2.int/TestScript" type="string" /> | |
51 <param name="Password" value="toto" type="password" /> | |
52 <param name="Server" value="necton2.int" type="string" /> | |
53 <param name="NewAccount" value="%(label_NewAccount)s" type="button" callback_id="registerNewAccount"/> | |
54 <param name="autoconnect" label="%(label_autoconnect)s" value="true" type="bool" /> | |
55 <param name="autodisconnect" label="%(label_autodisconnect)s" value="false" type="bool" /> | |
56 </category> | |
57 <category name="Misc" label="%(category_misc)s"> | |
58 <param name="Watched" value="test@Jabber.goffi.int" type="string" /> | |
59 </category> | |
60 </individual> | |
61 </params> | |
62 """ % {'category_connection': _("Connection"), | |
63 'label_NewAccount': _("Register new account"), | |
64 'label_autoconnect': _('Connect on frontend startup'), | |
65 'label_autodisconnect': _('Disconnect on frontend closure'), | |
66 'category_misc': _("Misc") | |
67 } | |
68 | |
69 def load_default_params(self): | |
70 self.dom = minidom.parseString(Param.default_xml.encode('utf-8')) | |
71 | |
72 def load_xml(self, file): | |
73 """Load parameters template from file""" | |
74 self.dom = minidom.parse(file) | |
75 | |
76 def load_data(self, file): | |
77 """Load parameters data from file""" | |
78 file_ind = file + '_ind' | |
79 file_gen = file + '_gen' | |
80 | |
81 if os.path.exists(file_gen): | |
82 try: | |
83 with open(file_gen, 'r') as file_gen_pickle: | |
84 self.params_gen=pickle.load(file_gen_pickle) | |
85 debug(_("general params data loaded")) | |
86 except: | |
87 error (_("Can't load general params data !")) | |
88 | |
89 if os.path.exists(file_ind): | |
90 try: | |
91 with open(file_ind, 'r') as file_ind_pickle: | |
92 self.params=pickle.load(file_ind_pickle) | |
93 debug(_("individual params data loaded")) | |
94 except: | |
95 error (_("Can't load individual params data !")) | |
96 | |
97 def save_xml(self, file): | |
98 """Save parameters template to xml file""" | |
99 with open(file, 'wb') as xml_file: | |
100 xml_file.write(self.dom.toxml('utf-8')) | |
101 | |
102 def save_data(self, file): | |
103 """Save parameters data to file""" | |
104 #TODO: save properly in a separate file/database, | |
105 # use different behaviour depending of the data type (e.g. password encrypted) | |
106 | |
107 #general params | |
108 with open(file+'_gen', 'w') as param_gen_pickle: | |
109 pickle.dump(self.params_gen, param_gen_pickle) | |
110 | |
111 #then individual params | |
112 with open(file+'_ind', 'w') as param_ind_pickle: | |
113 pickle.dump(self.params, param_ind_pickle) | |
114 | |
115 def __init__(self, host): | |
116 debug("Parameters init") | |
117 self.host = host | |
118 self.default_profile = None | |
119 self.params = {} | |
120 self.params_gen = {} | |
121 host.set_const('savefile_param_xml', SAVEFILE_PARAM_XML) | |
122 host.set_const('savefile_param_data', SAVEFILE_PARAM_DATA) | |
123 host.registerGeneralCB("registerNewAccount", host.registerNewAccountCB) | |
124 | |
125 def getProfilesList(self): | |
126 return self.params.keys() | |
127 | |
128 def createProfile(self, name): | |
129 """Create a new profile | |
130 @param name: Name of the profile""" | |
131 if self.params.has_key(name): | |
132 info (_('The profile name already exists')) | |
133 return 1 | |
134 self.params[name]={} | |
135 return 0 | |
136 | |
137 def deleteProfile(self, name): | |
138 """Delete an existing profile | |
139 @param name: Name of the profile""" | |
140 if not self.params.has_key(name): | |
141 error (_('Trying to delete an unknown profile')) | |
142 return 1 | |
143 del self.params[name] | |
144 return 0 | |
145 | |
146 def getProfileName(self, profile_key): | |
147 """return profile according to profile_key | |
148 @param profile_key: profile name or key which can be | |
149 @ALL@ for all profiles | |
150 @DEFAULT@ for default profile | |
151 @return: requested profile name or None if it doesn't exist""" | |
152 if profile_key=='@DEFAULT@': | |
153 if not self.params: | |
154 return "" | |
155 default = self.host.memory.getPrivate('Profile_default') | |
156 if not default or not default in self.params: | |
157 info(_('No default profile, returning first one')) #TODO: manage real default profile | |
158 default = self.params.keys()[0] | |
159 self.host.memory.setPrivate('Profile_default', default) | |
160 return default #FIXME: temporary, must use real default value, and fallback to first one if it doesn't exists | |
161 if not self.params.has_key(profile_key): | |
162 info (_('Trying to access an unknown profile')) | |
163 return "" | |
164 return profile_key | |
165 | |
166 def __get_unique_node(self, parent, tag, name): | |
167 """return node with given tag | |
168 @param parent: parent of nodes to check (e.g. documentElement) | |
169 @param tag: tag to check (e.g. "category") | |
170 @param name: name to check (e.g. "JID") | |
171 @return: node if it exist or None | |
172 """ | |
173 for node in parent.childNodes: | |
174 if node.nodeName == tag and node.getAttribute("name") == name: | |
175 #the node already exists | |
176 return node | |
177 #the node is new | |
178 return None | |
179 | |
180 def importParams(self, xml): | |
181 """import xml in parameters, do nothing if the param already exist | |
182 @param xml: parameters in xml form""" | |
183 src_dom = minidom.parseString(xml.encode('utf-8')) | |
184 | |
185 def import_node(tgt_parent, src_parent): | |
186 for child in src_parent.childNodes: | |
187 if child.nodeName == '#text': | |
188 continue | |
189 node = self.__get_unique_node(tgt_parent, child.nodeName, child.getAttribute("name")) | |
190 if not node: #The node is new | |
191 tgt_parent.appendChild(child) | |
192 else: | |
193 import_node(node, child) | |
194 | |
195 import_node(self.dom.documentElement, src_dom.documentElement) | |
196 | |
197 def __default_ok(self, value, name, category): | |
198 #FIXME: gof: will not work with individual parameters | |
199 self.setParam(name, value, category) #FIXME: better to set param xml value ??? | |
200 | |
201 def __default_ko(self, failure, name, category): | |
202 error (_("Can't determine default value for [%(category)s/%(name)s]: %(reason)s") % {'category':category, 'name':name, 'reason':str(failure.value)}) | |
203 | |
204 def setDefault(self, name, category, callback, errback=None): | |
205 """Set default value of parameter | |
206 'default_cb' attibute of parameter must be set to 'yes' | |
207 @param name: name of the parameter | |
208 @param category: category of the parameter | |
209 @param callback: must return a string with the value (use deferred if needed) | |
210 @param errback: must manage the error with args failure, name, category | |
211 """ | |
212 #TODO: send signal param update if value changed | |
213 node = self.__getParamNode(name, category, '@ALL@') | |
214 if not node: | |
215 error(_("Requested param [%(name)s] in category [%(category)s] doesn't exist !") % {'name':name, 'category':category}) | |
216 return | |
217 if node[1].getAttribute('default_cb') == 'yes': | |
218 del node[1].attributes['default_cb'] | |
219 d = defer.maybeDeferred(callback) | |
220 d.addCallback(self.__default_ok, name, category) | |
221 d.addErrback(errback or self.__default_ko, name, category) | |
222 | |
223 def getParamA(self, name, category, attr="value", profile_key="@DEFAULT@"): | |
224 """Helper method to get a specific attribute | |
225 @param name: name of the parameter | |
226 @param category: category of the parameter | |
227 @param attr: name of the attribute (default: "value") | |
228 @param profile: owner of the param (@ALL@ for everyone) | |
229 | |
230 @return: attribute""" | |
231 node = self.__getParamNode(name, category) | |
232 if not node: | |
233 error(_("Requested param [%(name)s] in category [%(category)s] doesn't exist !") % {'name':name, 'category':category}) | |
234 return None | |
235 | |
236 if node[0] == 'general': | |
237 value = self.__getParam(None, category, name, 'general') | |
238 return value or node[1].getAttribute(attr) | |
239 | |
240 assert(node[0] == 'individual') | |
241 | |
242 profile = self.getProfileName(profile_key) | |
243 if not profile: | |
244 error(_('Requesting a param for an non-existant profile')) | |
245 return None | |
246 | |
247 if attr == "value": | |
248 return self.__getParam(profile, category, name) or node[1].getAttribute(attr) | |
249 else: | |
250 return node[1].getAttribute(attr) | |
251 | |
252 | |
253 def __getParam(self, profile, category, name, type='individual'): | |
254 """Return the param, or None if it doesn't exist | |
255 @param profile: the profile name (not profile key, i.e. name and not something like @DEFAULT@) | |
256 @param category: param category | |
257 @param name: param name | |
258 """ | |
259 if type == 'general': | |
260 if self.params_gen.has_key((category, name)): | |
261 return self.params_gen[(category, name)] | |
262 return None #This general param has the default value | |
263 assert (type == 'individual') | |
264 if not self.params.has_key(profile) or not self.params[profile].has_key((category, name)): | |
265 return None | |
266 return self.params[profile][(category, name)] | |
267 | |
268 def __constructProfileXml(self, profile): | |
269 """Construct xml for asked profile, filling values when needed | |
270 /!\ as noticed in doc, don't forget to unlink the minidom.Document | |
271 @param profile: profile name (not key !) | |
272 @return: minidom.Document of the profile xml (cf warning above) | |
273 """ | |
274 prof_xml = minidom.parseString('<params/>') | |
275 | |
276 for type_node in self.dom.documentElement.childNodes: | |
277 if type_node.nodeName == 'general' or type_node.nodeName == 'individual': #we use all params, general and individual | |
278 for cat_node in type_node.childNodes: | |
279 if cat_node.nodeName == 'category': | |
280 category = cat_node.getAttribute('name') | |
281 cat_copy = cat_node.cloneNode(True) #we make a copy for the new xml | |
282 params = cat_copy.getElementsByTagName("param") | |
283 for param_node in params: | |
284 name = param_node.getAttribute('name') | |
285 profile_value = self.__getParam(profile, category, name, type_node.nodeName) | |
286 if profile_value: #there is a value for this profile, we must change the default | |
287 param_node.setAttribute('value', profile_value) | |
288 prof_xml.documentElement.appendChild(cat_copy) | |
289 return prof_xml | |
290 | |
291 | |
292 def getParamsUI(self, profile_key='@DEFAULT@'): | |
293 """Return a SàT XMLUI for parameters, with given profile""" | |
294 profile = self.getProfileName(profile_key) | |
295 if not profile: | |
296 error(_("Asking params for inexistant profile")) | |
297 return "" | |
298 param_xml = self.getParams(profile) | |
299 return paramsXml2xmlUI(param_xml) | |
300 | |
301 def getParams(self, profile_key='@DEFAULT@'): | |
302 """Construct xml for asked profile | |
303 Take params xml as skeleton""" | |
304 profile = self.getProfileName(profile_key) | |
305 if not profile: | |
306 error(_("Asking params for inexistant profile")) | |
307 return "" | |
308 prof_xml = self.__constructProfileXml(profile) | |
309 return_xml = prof_xml.toxml() | |
310 prof_xml.unlink() | |
311 | |
312 return return_xml | |
313 | |
314 def getParamsForCategory(self, category, profile_key='@DEFAULT@'): | |
315 """Return node's xml for selected category""" | |
316 #TODO: manage category of general type (without existant profile) | |
317 profile = self.getProfileName(profile_key) | |
318 if not profile: | |
319 error(_("Asking params for inexistant profile")) | |
320 return "" | |
321 prof_xml = self.__constructProfileXml(profile) | |
322 | |
323 for node in prof_xml.getElementsByTagName("category"): | |
324 if node.nodeName == "category" and node.getAttribute("name") == category: | |
325 result = node.toxml() | |
326 prof_xml.unlink() | |
327 return result | |
328 | |
329 prof_xml.unlink() | |
330 return "<category />" | |
331 | |
332 def __getParamNode(self, name, category, type="@ALL@"): #FIXME: is type useful ? | |
333 """Return a node from the param_xml | |
334 @param name: name of the node | |
335 @param category: category of the node | |
336 @type: keyword for search: | |
337 @ALL@ search everywhere | |
338 @GENERAL@ only search in general type | |
339 @INDIVIDUAL@ only search in individual type | |
340 @return: a tuple with the node type and the the node, or None if not found""" | |
341 | |
342 for type_node in self.dom.documentElement.childNodes: | |
343 if ( ((type == "@ALL@" or type == "@GENERAL@") and type_node.nodeName == 'general') | |
344 or ( (type == "@ALL@" or type == "@INDIVIDUAL@") and type_node.nodeName == 'individual') ): | |
345 for node in type_node.getElementsByTagName('category'): | |
346 if node.getAttribute("name") == category: | |
347 params = node.getElementsByTagName("param") | |
348 for param in params: | |
349 if param.getAttribute("name") == name: | |
350 return (type_node.nodeName, param) | |
351 return None | |
352 | |
353 def getParamsCategories(self): | |
354 """return the categories availables""" | |
355 categories=[] | |
356 for cat in self.dom.getElementsByTagName("category"): | |
357 categories.append(cat.getAttribute("name")) | |
358 return categories | |
359 | |
360 def setParam(self, name, value, category, profile_key='@DEFAULT@'): | |
361 """Set a parameter, return None if the parameter is not in param xml""" | |
362 profile = self.getProfileName(profile_key) | |
363 if not profile: | |
364 error(_('Trying to set parameter for an unknown profile')) | |
365 return #TODO: throw an error | |
366 | |
367 node = self.__getParamNode(name, category, '@ALL@') | |
368 if not node: | |
369 error(_('Requesting an unknown parameter (%(category)s/%(name)s)') % {'category':category, 'name':name}) | |
370 return | |
371 | |
372 if node[0] == 'general': | |
373 self.params_gen[(category, name)] = value | |
374 self.host.bridge.paramUpdate(name, value, category, profile) #TODO: add profile in signal | |
375 return | |
376 | |
377 assert (node[0] == 'individual') | |
378 | |
379 type = node[1].getAttribute("type") | |
380 if type=="button": | |
381 print "clique",node.toxml() | |
382 else: | |
383 self.params[profile][(category, name)] = value | |
384 self.host.bridge.paramUpdate(name, value, category, profile) #TODO: add profile in signal | |
385 | |
386 class Memory: | |
387 """This class manage all persistent informations""" | |
388 | |
389 def __init__(self, host): | |
390 info (_("Memory manager init")) | |
391 self.host = host | |
392 self.contacts={} | |
393 self.presenceStatus={} | |
394 self.subscriptions={} | |
395 self.params=Param(host) | |
396 self.history={} #used to store chat history (key: short jid) | |
397 self.private={} #used to store private value | |
398 host.set_const('savefile_history', SAVEFILE_HISTORY) | |
399 host.set_const('savefile_private', SAVEFILE_PRIVATE) | |
400 self.load() | |
401 | |
402 def load(self): | |
403 """Load parameters and all memory things from file/db""" | |
404 param_file_xml = os.path.expanduser(self.host.get_const('local_dir')+ | |
405 self.host.get_const('savefile_param_xml')) | |
406 param_file_data = os.path.expanduser(self.host.get_const('local_dir')+ | |
407 self.host.get_const('savefile_param_data')) | |
408 history_file = os.path.expanduser(self.host.get_const('local_dir')+ | |
409 self.host.get_const('savefile_history')) | |
410 private_file = os.path.expanduser(self.host.get_const('local_dir')+ | |
411 self.host.get_const('savefile_private')) | |
412 | |
413 #parameters | |
414 if os.path.exists(param_file_xml): | |
415 try: | |
416 self.params.load_xml(param_file_xml) | |
417 debug(_("params template loaded")) | |
418 except: | |
419 error (_("Can't load params template !")) | |
420 self.params.load_default_params() | |
421 else: | |
422 info (_("No params template, using default template")) | |
423 self.params.load_default_params() | |
424 | |
425 try: | |
426 self.params.load_data(param_file_data) | |
427 debug(_("params loaded")) | |
428 except: | |
429 error (_("Can't load params !")) | |
430 | |
431 #history | |
432 if os.path.exists(history_file): | |
433 try: | |
434 with open(history_file, 'r') as history_pickle: | |
435 self.history=pickle.load(history_pickle) | |
436 debug(_("history loaded")) | |
437 except: | |
438 error (_("Can't load history !")) | |
439 | |
440 #private | |
441 if os.path.exists(private_file): | |
442 try: | |
443 with open(private_file, 'r') as private_pickle: | |
444 self.private=pickle.load(private_pickle) | |
445 debug(_("private values loaded")) | |
446 except: | |
447 error (_("Can't load private values !")) | |
448 | |
449 def save(self): | |
450 """Save parameters and all memory things to file/db""" | |
451 #TODO: need to encrypt files (at least passwords !) and set permissions | |
452 param_file_xml = os.path.expanduser(self.host.get_const('local_dir')+ | |
453 self.host.get_const('savefile_param_xml')) | |
454 param_file_data = os.path.expanduser(self.host.get_const('local_dir')+ | |
455 self.host.get_const('savefile_param_data')) | |
456 history_file = os.path.expanduser(self.host.get_const('local_dir')+ | |
457 self.host.get_const('savefile_history')) | |
458 private_file = os.path.expanduser(self.host.get_const('local_dir')+ | |
459 self.host.get_const('savefile_private')) | |
460 | |
461 self.params.save_xml(param_file_xml) | |
462 self.params.save_data(param_file_data) | |
463 debug(_("params saved")) | |
464 with open(history_file, 'w') as history_pickle: | |
465 pickle.dump(self.history, history_pickle) | |
466 debug(_("history saved")) | |
467 with open(private_file, 'w') as private_pickle: | |
468 pickle.dump(self.private, private_pickle) | |
469 debug(_("private values saved")) | |
470 | |
471 def getProfilesList(self): | |
472 return self.params.getProfilesList() | |
473 | |
474 | |
475 def getProfileName(self, profile_key): | |
476 """Return name of profile from keyword | |
477 @param profile_key: can be the profile name or a keywork (like @DEFAULT@) | |
478 @return: profile name or None if it doesn't exist""" | |
479 return self.params.getProfileName(profile_key) | |
480 | |
481 def createProfile(self, name): | |
482 """Create a new profile | |
483 @param name: Profile name | |
484 """ | |
485 return self.params.createProfile(name) | |
486 | |
487 def deleteProfile(self, name): | |
488 """Delete an existing profile | |
489 @param name: Name of the profile""" | |
490 return self.params.deleteProfile(name) | |
491 | |
492 def addToHistory(self, me_jid, from_jid, to_jid, type, message): | |
493 me_short=me_jid.userhost() | |
494 from_short=from_jid.userhost() | |
495 to_short=to_jid.userhost() | |
496 | |
497 if from_jid==me_jid: | |
498 key=to_short | |
499 else: | |
500 key=from_short | |
501 | |
502 if not self.history.has_key(me_short): | |
503 self.history[me_short]={} | |
504 if not self.history[me_short].has_key(key): | |
505 self.history[me_short][key]={} | |
506 | |
507 self.history[me_short][key][int(time.time())] = (from_jid.full(), message) | |
508 | |
509 def getHistory(self, from_jid, to_jid, size): | |
510 ret={} | |
511 if not self.history.has_key(from_jid): | |
512 error(_("source JID not found !")) | |
513 #TODO: throw an error here | |
514 return {} | |
515 if not self.history[from_jid].has_key(to_jid): | |
516 error(_("dest JID not found !")) | |
517 #TODO: throw an error here | |
518 return {} | |
519 stamps=self.history[from_jid][to_jid].keys() | |
520 stamps.sort() | |
521 for stamp in stamps[-size:]: | |
522 ret[stamp]=self.history[from_jid][to_jid][stamp] | |
523 | |
524 return ret | |
525 | |
526 def setPrivate(self, key, value): | |
527 """Save a misc private value (mainly useful for plugins)""" | |
528 self.private[key] = value | |
529 | |
530 def getPrivate(self, key): | |
531 """return a private value | |
532 @param key: name of wanted value | |
533 @return: value or None if value don't exist""" | |
534 if self.private.has_key(key): | |
535 return self.private[key] | |
536 return None | |
537 | |
538 | |
539 def addContact(self, contact_jid, attributes, groups, profile_key='@DEFAULT@'): | |
540 debug("Memory addContact: %s",contact_jid.userhost()) | |
541 profile = self.getProfileName(profile_key) | |
542 if not profile: | |
543 error (_('Trying to add a contact to a non-existant profile')) | |
544 return | |
545 assert(isinstance(attributes,dict)) | |
546 assert(isinstance(groups,set)) | |
547 if not self.contacts.has_key(profile): | |
548 self.contacts[profile] = {} | |
549 self.contacts[profile][contact_jid.userhost()]=[attributes, groups] | |
550 | |
551 def delContact(self, contact_jid, profile_key='@DEFAULT@'): | |
552 debug("Memory delContact: %s",contact_jid.userhost()) | |
553 profile = self.getProfileName(profile_key) | |
554 if not profile: | |
555 error (_('Trying to delete a contact for a non-existant profile')) | |
556 return | |
557 if self.contacts.has_key(profile) and self.contacts[profile].has_key(contact_jid.userhost()): | |
558 del self.contacts[profile][contact_jid.userhost()] | |
559 | |
560 def getContact(self, contact_jid, profile_key='@DEFAULT@'): | |
561 profile = self.getProfileName(profile_key) | |
562 if not profile: | |
563 error(_('Asking a contact for a non-existant profile')) | |
564 return None | |
565 if self.contacts.has_key(profile) and self.contacts[profile].has_key(contact_jid.userhost()): | |
566 self.contacts[profile][contact_jid.userhost()] | |
567 else: | |
568 return None | |
569 | |
570 def getContacts(self, profile_key='@DEFAULT@'): | |
571 """Return list of contacts for given profile | |
572 @param profile_key: profile key | |
573 @return list of [contact, attr, groups]""" | |
574 debug ("Memory getContact OK (%s)", self.contacts) | |
575 profile = self.getProfileName(profile_key) | |
576 if not profile: | |
577 error(_('Asking contacts for a non-existant profile')) | |
578 return [] | |
579 ret=[] | |
580 for contact in self.contacts[profile]: | |
581 attr, groups = self.contacts[profile][contact] | |
582 ret.append([contact, attr, groups ]) | |
583 return ret | |
584 | |
585 def addPresenceStatus(self, contact_jid, show, priority, statuses, profile_key='@DEFAULT@'): | |
586 profile = self.getProfileName(profile_key) | |
587 if not profile: | |
588 error(_('Trying to add presence status to a non-existant profile')) | |
589 return | |
590 if not self.presenceStatus.has_key(profile): | |
591 self.presenceStatus[profile] = {} | |
592 if not self.presenceStatus[profile].has_key(contact_jid.userhost()): | |
593 self.presenceStatus[profile][contact_jid.userhost()] = {} | |
594 resource = jid.parse(contact_jid.full())[2] or '' | |
595 self.presenceStatus[profile][contact_jid.userhost()][resource] = (show, priority, statuses) | |
596 | |
597 def addWaitingSub(self, type, contact_jid, profile_key): | |
598 """Called when a subcription request is received""" | |
599 profile = self.getProfileName(profile_key) | |
600 assert(profile) | |
601 if not self.subscriptions.has_key(profile): | |
602 self.subscriptions[profile] = {} | |
603 self.subscriptions[profile][contact_jid] = type | |
604 | |
605 def delWaitingSub(self, contact_jid, profile_key): | |
606 """Called when a subcription request is finished""" | |
607 profile = self.getProfileName(profile_key) | |
608 assert(profile) | |
609 if self.subscriptions.has_key(profile) and self.subscriptions[profile].has_key(contact_jid): | |
610 del self.subscriptions[profile][contact_jid] | |
611 | |
612 def getWaitingSub(self, profile_key='@DEFAULT@'): | |
613 """Called to get a list of currently waiting subscription requests""" | |
614 profile = self.getProfileName(profile_key) | |
615 if not profile: | |
616 error(_('Asking waiting subscriptions for a non-existant profile')) | |
617 return {} | |
618 if not self.subscriptions.has_key(profile): | |
619 return {} | |
620 | |
621 return self.subscriptions[profile] | |
622 | |
623 def getPresenceStatus(self, profile_key='@DEFAULT@'): | |
624 profile = self.getProfileName(profile_key) | |
625 if not profile: | |
626 error(_('Asking contacts for a non-existant profile')) | |
627 return {} | |
628 if not self.presenceStatus.has_key(profile): | |
629 self.presenceStatus[profile] = {} | |
630 debug ("Memory getPresenceStatus (%s)", self.presenceStatus[profile]) | |
631 return self.presenceStatus[profile] | |
632 | |
633 def getParamA(self, name, category, attr="value", profile_key="@DEFAULT@"): | |
634 return self.params.getParamA(name, category, attr, profile_key) | |
635 | |
636 def getParamsUI(self, profile_key='@DEFAULT@'): | |
637 return self.params.getParamsUI(profile_key) | |
638 | |
639 def getParams(self, profile_key='@DEFAULT@'): | |
640 return self.params.getParams(profile_key) | |
641 | |
642 def getParamsForCategory(self, category, profile_key='@DEFAULT@'): | |
643 return self.params.getParamsForCategory(category, profile_key) | |
644 | |
645 def getParamsCategories(self): | |
646 return self.params.getParamsCategories() | |
647 | |
648 def setParam(self, name, value, category, profile_key='@DEFAULT@'): | |
649 return self.params.setParam(name, value, category, profile_key) | |
650 | |
651 def importParams(self, xml): | |
652 return self.params.importParams(xml) | |
653 | |
654 def setDefault(self, name, category, callback, errback=None): | |
655 return self.params.setDefault(name, category, callback, errback) |