Mercurial > libervia-pubsub
comparison src/iidavoll.py @ 369:dabee42494ac
config file + cleaning:
- SàT Pubsub can now be configured using the same config file as SàT itself (i.e. sat.conf or .sat.conf), in the same locations (/etc, local dir, xdg dir).
Its options must be in the "pubsub" section
- options on command line override config options
- removed tap and http files which are not used anymore
- changed directory structure to put source in src, to be coherent with SàT and Libervia
- changed options name, db* become db_*, secret become xmpp_pwd
- an exception is raised if jid or xmpp_pwd is are not configured
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 02 Mar 2018 12:59:38 +0100 |
parents | sat_pubsub/iidavoll.py@618a92080812 |
children | aa3a464df605 |
comparison
equal
deleted
inserted
replaced
368:618a92080812 | 369:dabee42494ac |
---|---|
1 #!/usr/bin/python | |
2 #-*- coding: utf-8 -*- | |
3 | |
4 # Copyright (c) 2003-2011 Ralph Meijer | |
5 # Copyright (c) 2012-2018 Jérôme Poisson | |
6 | |
7 | |
8 # This program is free software: you can redistribute it and/or modify | |
9 # it under the terms of the GNU Affero 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 Affero General Public License for more details. | |
17 | |
18 # You should have received a copy of the GNU Affero General Public License | |
19 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
20 # -- | |
21 | |
22 # This program is based on Idavoll (http://idavoll.ik.nu/), | |
23 # originaly written by Ralph Meijer (http://ralphm.net/blog/) | |
24 # It is sublicensed under AGPL v3 (or any later version) as allowed by the original | |
25 # license. | |
26 | |
27 # -- | |
28 | |
29 # Here is a copy of the original license: | |
30 | |
31 # Copyright (c) 2003-2011 Ralph Meijer | |
32 | |
33 # Permission is hereby granted, free of charge, to any person obtaining | |
34 # a copy of this software and associated documentation files (the | |
35 # "Software"), to deal in the Software without restriction, including | |
36 # without limitation the rights to use, copy, modify, merge, publish, | |
37 # distribute, sublicense, and/or sell copies of the Software, and to | |
38 # permit persons to whom the Software is furnished to do so, subject to | |
39 # the following conditions: | |
40 | |
41 # The above copyright notice and this permission notice shall be | |
42 # included in all copies or substantial portions of the Software. | |
43 | |
44 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
45 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
46 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
47 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |
48 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |
49 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
50 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
51 | |
52 | |
53 """ | |
54 Interfaces for idavoll. | |
55 """ | |
56 | |
57 from zope.interface import Attribute, Interface | |
58 | |
59 class IBackendService(Interface): | |
60 """ Interface to a backend service of a pubsub service. """ | |
61 | |
62 | |
63 def __init__(storage): | |
64 """ | |
65 @param storage: Object providing L{IStorage}. | |
66 """ | |
67 | |
68 | |
69 def supportsPublisherAffiliation(): | |
70 """ Reports if the backend supports the publisher affiliation. | |
71 | |
72 @rtype: C{bool} | |
73 """ | |
74 | |
75 | |
76 def supportsOutcastAffiliation(): | |
77 """ Reports if the backend supports the publisher affiliation. | |
78 | |
79 @rtype: C{bool} | |
80 """ | |
81 | |
82 | |
83 def supportsPersistentItems(): | |
84 """ Reports if the backend supports persistent items. | |
85 | |
86 @rtype: C{bool} | |
87 """ | |
88 | |
89 | |
90 def getNodeType(nodeIdentifier): | |
91 """ Return type of a node. | |
92 | |
93 @return: a deferred that returns either 'leaf' or 'collection' | |
94 """ | |
95 | |
96 | |
97 def getNodes(): | |
98 """ Returns list of all nodes. | |
99 | |
100 @return: a deferred that returns a C{list} of node ids. | |
101 """ | |
102 | |
103 | |
104 def getNodeMetaData(nodeIdentifier): | |
105 """ Return meta data for a node. | |
106 | |
107 @return: a deferred that returns a C{list} of C{dict}s with the | |
108 metadata. | |
109 """ | |
110 | |
111 | |
112 def createNode(nodeIdentifier, requestor): | |
113 """ Create a node. | |
114 | |
115 @return: a deferred that fires when the node has been created. | |
116 """ | |
117 | |
118 | |
119 def registerPreDelete(preDeleteFn): | |
120 """ Register a callback that is called just before a node deletion. | |
121 | |
122 The function C{preDeletedFn} is added to a list of functions to be | |
123 called just before deletion of a node. The callback C{preDeleteFn} is | |
124 called with the C{nodeIdentifier} that is about to be deleted and | |
125 should return a deferred that returns a list of deferreds that are to | |
126 be fired after deletion. The backend collects the lists from all these | |
127 callbacks before actually deleting the node in question. After | |
128 deletion all collected deferreds are fired to do post-processing. | |
129 | |
130 The idea is that you want to be able to collect data from the node | |
131 before deleting it, for example to get a list of subscribers that have | |
132 to be notified after the node has been deleted. To do this, | |
133 C{preDeleteFn} fetches the subscriber list and passes this list to a | |
134 callback attached to a deferred that it sets up. This deferred is | |
135 returned in the list of deferreds. | |
136 """ | |
137 | |
138 | |
139 def deleteNode(nodeIdentifier, requestor): | |
140 """ Delete a node. | |
141 | |
142 @return: a deferred that fires when the node has been deleted. | |
143 """ | |
144 | |
145 | |
146 def purgeNode(nodeIdentifier, requestor): | |
147 """ Removes all items in node from persistent storage """ | |
148 | |
149 | |
150 def subscribe(nodeIdentifier, subscriber, requestor): | |
151 """ Request the subscription of an entity to a pubsub node. | |
152 | |
153 Depending on the node's configuration and possible business rules, the | |
154 C{subscriber} is added to the list of subscriptions of the node with id | |
155 C{nodeIdentifier}. The C{subscriber} might be different from the | |
156 C{requestor}, and if the C{requestor} is not allowed to subscribe this | |
157 entity an exception should be raised. | |
158 | |
159 @return: a deferred that returns the subscription state | |
160 """ | |
161 | |
162 | |
163 def unsubscribe(nodeIdentifier, subscriber, requestor): | |
164 """ Cancel the subscription of an entity to a pubsub node. | |
165 | |
166 The subscription of C{subscriber} is removed from the list of | |
167 subscriptions of the node with id C{nodeIdentifier}. If the | |
168 C{requestor} is not allowed to unsubscribe C{subscriber}, an an | |
169 exception should be raised. | |
170 | |
171 @return: a deferred that fires when unsubscription is complete. | |
172 """ | |
173 | |
174 | |
175 def getSubscribers(nodeIdentifier): | |
176 """ Get node subscriber list. | |
177 | |
178 @return: a deferred that fires with the list of subscribers. | |
179 """ | |
180 | |
181 | |
182 def getSubscriptions(entity): | |
183 """ Report the list of current subscriptions with this pubsub service. | |
184 | |
185 Report the list of the current subscriptions with all nodes within this | |
186 pubsub service, for the C{entity}. | |
187 | |
188 @return: a deferred that returns the list of all current subscriptions | |
189 as tuples C{(nodeIdentifier, subscriber, subscription)}. | |
190 """ | |
191 | |
192 | |
193 def getAffiliations(entity): | |
194 """ Report the list of current affiliations with this pubsub service. | |
195 | |
196 Report the list of the current affiliations with all nodes within this | |
197 pubsub service, for the C{entity}. | |
198 | |
199 @return: a deferred that returns the list of all current affiliations | |
200 as tuples C{(nodeIdentifier, affiliation)}. | |
201 """ | |
202 | |
203 | |
204 def publish(nodeIdentifier, items, requestor): | |
205 """ Publish items to a pubsub node. | |
206 | |
207 @return: a deferred that fires when the items have been published. | |
208 @rtype: L{Deferred<twisted.internet.defer.Deferred>} | |
209 """ | |
210 | |
211 | |
212 def registerNotifier(observerfn, *args, **kwargs): | |
213 """ Register callback which is called for notification. """ | |
214 | |
215 | |
216 def getNotifications(nodeIdentifier, items): | |
217 """ | |
218 Get notification list. | |
219 | |
220 This method is called to discover which entities should receive | |
221 notifications for the given items that have just been published to the | |
222 given node. | |
223 | |
224 The notification list contains tuples (subscriber, subscriptions, | |
225 items) to result in one notification per tuple: the given subscriptions | |
226 yielded the given items to be notified to this subscriber. This | |
227 structure is needed allow for letting the subscriber know which | |
228 subscriptions yielded which notifications, while catering for | |
229 collection nodes and content-based subscriptions. | |
230 | |
231 To minimize the amount of notifications per entity, implementers | |
232 should take care that if all items in C{items} were yielded | |
233 by the same set of subscriptions, exactly one tuple is for this | |
234 subscriber is returned, so that the subscriber would get exactly one | |
235 notification. Alternatively, one tuple per subscription combination. | |
236 | |
237 @param nodeIdentifier: The identifier of the node the items were | |
238 published to. | |
239 @type nodeIdentifier: C{unicode}. | |
240 @param items: The list of published items as | |
241 L{Element<twisted.words.xish.domish.Element>}s. | |
242 @type items: C{list} | |
243 @return: The notification list as tuples of | |
244 (L{JID<twisted.words.protocols.jabber.jid.JID>}, | |
245 C{list} of L{Subscription<wokkel.pubsub.Subscription>}, | |
246 C{list} of L{Element<twisted.words.xish.domish.Element>}. | |
247 @rtype: C{list} | |
248 """ | |
249 | |
250 | |
251 def getItems(nodeIdentifier, requestor, maxItems=None, itemIdentifiers=[]): | |
252 """ Retrieve items from persistent storage | |
253 | |
254 If C{maxItems} is given, return the C{maxItems} last published | |
255 items, else if C{itemIdentifiers} is not empty, return the items | |
256 requested. If neither is given, return all items. | |
257 | |
258 @return: a deferred that returns the requested items | |
259 """ | |
260 | |
261 | |
262 def retractItem(nodeIdentifier, itemIdentifier, requestor): | |
263 """ Removes item in node from persistent storage """ | |
264 | |
265 | |
266 | |
267 class IStorage(Interface): | |
268 """ | |
269 Storage interface. | |
270 """ | |
271 | |
272 | |
273 def getNode(nodeIdentifier): | |
274 """ | |
275 Get Node. | |
276 | |
277 @param nodeIdentifier: NodeID of the desired node. | |
278 @type nodeIdentifier: C{str} | |
279 @return: deferred that returns a L{INode} providing object. | |
280 """ | |
281 | |
282 | |
283 def getNodeIds(): | |
284 """ | |
285 Return all NodeIDs. | |
286 | |
287 @return: deferred that returns a list of NodeIDs (C{unicode}). | |
288 """ | |
289 | |
290 | |
291 def createNode(nodeIdentifier, owner, config): | |
292 """ | |
293 Create new node. | |
294 | |
295 The implementation should make sure, the passed owner JID is stripped | |
296 of the resource (e.g. using C{owner.userhostJID()}). The passed config | |
297 is expected to have values for the fields returned by | |
298 L{getDefaultConfiguration}, as well as a value for | |
299 C{'pubsub#node_type'}. | |
300 | |
301 @param nodeIdentifier: NodeID of the new node. | |
302 @type nodeIdentifier: C{unicode} | |
303 @param owner: JID of the new nodes's owner. | |
304 @type owner: L{JID<twisted.words.protocols.jabber.jid.JID>} | |
305 @param config: Node configuration. | |
306 @type config: C{dict} | |
307 @return: deferred that fires on creation. | |
308 """ | |
309 | |
310 | |
311 def deleteNode(nodeIdentifier): | |
312 """ | |
313 Delete a node. | |
314 | |
315 @param nodeIdentifier: NodeID of the new node. | |
316 @type nodeIdentifier: C{unicode} | |
317 @return: deferred that fires on deletion. | |
318 """ | |
319 | |
320 | |
321 def getAffiliations(entity): | |
322 """ | |
323 Get all affiliations for entity. | |
324 | |
325 The implementation should make sure, the passed owner JID is stripped | |
326 of the resource (e.g. using C{owner.userhostJID()}). | |
327 | |
328 @param entity: JID of the entity. | |
329 @type entity: L{JID<twisted.words.protocols.jabber.jid.JID>} | |
330 @return: deferred that returns a C{list} of tuples of the form | |
331 C{(nodeIdentifier, affiliation)}, where C{nodeIdentifier} is | |
332 of the type L{unicode} and C{affiliation} is one of | |
333 C{'owner'}, C{'publisher'} and C{'outcast'}. | |
334 """ | |
335 | |
336 | |
337 def getSubscriptions(entity): | |
338 """ | |
339 Get all subscriptions for an entity. | |
340 | |
341 The implementation should make sure, the passed owner JID is stripped | |
342 of the resource (e.g. using C{owner.userhostJID()}). | |
343 | |
344 @param entity: JID of the entity. | |
345 @type entity: L{JID<twisted.words.protocols.jabber.jid.JID>} | |
346 @return: deferred that returns a C{list} of tuples of the form | |
347 C{(nodeIdentifier, subscriber, state)}, where | |
348 C{nodeIdentifier} is of the type C{unicode}, C{subscriber} of | |
349 the type J{JID<twisted.words.protocols.jabber.jid.JID>}, and | |
350 C{state} is C{'subscribed'}, C{'pending'} or | |
351 C{'unconfigured'}. | |
352 """ | |
353 | |
354 | |
355 def getDefaultConfiguration(nodeType): | |
356 """ | |
357 Get the default configuration for the given node type. | |
358 | |
359 @param nodeType: Either C{'leaf'} or C{'collection'}. | |
360 @type nodeType: C{str} | |
361 @return: The default configuration. | |
362 @rtype: C{dict}. | |
363 @raises: L{idavoll.error.NoCollections} if collections are not | |
364 supported. | |
365 """ | |
366 | |
367 | |
368 | |
369 class INode(Interface): | |
370 """ | |
371 Interface to the class of objects that represent nodes. | |
372 """ | |
373 | |
374 nodeType = Attribute("""The type of this node. One of {'leaf'}, | |
375 {'collection'}.""") | |
376 nodeIdentifier = Attribute("""The node identifer of this node""") | |
377 | |
378 | |
379 def getType(): | |
380 """ | |
381 Get node's type. | |
382 | |
383 @return: C{'leaf'} or C{'collection'}. | |
384 """ | |
385 | |
386 | |
387 def getConfiguration(): | |
388 """ | |
389 Get node's configuration. | |
390 | |
391 The configuration must at least have two options: | |
392 C{pubsub#persist_items}, and C{pubsub#deliver_payloads}. | |
393 | |
394 @return: C{dict} of configuration options. | |
395 """ | |
396 | |
397 | |
398 def getMetaData(): | |
399 """ | |
400 Get node's meta data. | |
401 | |
402 The meta data must be a superset of the configuration options, and | |
403 also at least should have a C{pubsub#node_type} entry. | |
404 | |
405 @return: C{dict} of meta data. | |
406 """ | |
407 | |
408 | |
409 def setConfiguration(options): | |
410 """ | |
411 Set node's configuration. | |
412 | |
413 The elements of {options} will set the new values for those | |
414 configuration items. This means that only changing items have to | |
415 be given. | |
416 | |
417 @param options: a dictionary of configuration options. | |
418 @returns: a deferred that fires upon success. | |
419 """ | |
420 | |
421 | |
422 def getAffiliation(entity): | |
423 """ | |
424 Get affiliation of entity with this node. | |
425 | |
426 @param entity: JID of entity. | |
427 @type entity: L{JID<twisted.words.protocols.jabber.jid.JID>} | |
428 @return: deferred that returns C{'owner'}, C{'publisher'}, C{'outcast'} | |
429 or C{None}. | |
430 """ | |
431 | |
432 | |
433 def getSubscription(subscriber): | |
434 """ | |
435 Get subscription to this node of subscriber. | |
436 | |
437 @param subscriber: JID of the new subscriptions' entity. | |
438 @type subscriber: L{JID<twisted.words.protocols.jabber.jid.JID>} | |
439 @return: deferred that returns the subscription state (C{'subscribed'}, | |
440 C{'pending'} or C{None}). | |
441 """ | |
442 | |
443 | |
444 def getSubscriptions(state=None): | |
445 """ | |
446 Get list of subscriptions to this node. | |
447 | |
448 The optional C{state} argument filters the subscriptions to their | |
449 state. | |
450 | |
451 @param state: Subscription state filter. One of C{'subscribed'}, | |
452 C{'pending'}, C{'unconfigured'}. | |
453 @type state: C{str} | |
454 @return: a deferred that returns a C{list} of | |
455 L{wokkel.pubsub.Subscription}s. | |
456 """ | |
457 | |
458 | |
459 def addSubscription(subscriber, state, config): | |
460 """ | |
461 Add new subscription to this node with given state. | |
462 | |
463 @param subscriber: JID of the new subscriptions' entity. | |
464 @type subscriber: L{JID<twisted.words.protocols.jabber.jid.JID>} | |
465 @param state: C{'subscribed'} or C{'pending'} | |
466 @type state: C{str} | |
467 @param config: Subscription configuration. | |
468 @param config: C{dict} | |
469 @return: deferred that fires on subscription. | |
470 """ | |
471 | |
472 | |
473 def removeSubscription(subscriber): | |
474 """ | |
475 Remove subscription to this node. | |
476 | |
477 @param subscriber: JID of the subscriptions' entity. | |
478 @type subscriber: L{JID<twisted.words.protocols.jabber.jid.JID>} | |
479 @return: deferred that fires on removal. | |
480 """ | |
481 | |
482 | |
483 def isSubscribed(entity): | |
484 """ | |
485 Returns whether entity has any subscription to this node. | |
486 | |
487 Only returns C{True} when the subscription state (if present) is | |
488 C{'subscribed'} for any subscription that matches the bare JID. | |
489 | |
490 @param subscriber: bare JID of the subscriptions' entity. | |
491 @type subscriber: L{JID<twisted.words.protocols.jabber.jid.JID>} | |
492 @return: deferred that returns a C{bool}. | |
493 """ | |
494 | |
495 | |
496 def getAffiliations(): | |
497 """ | |
498 Get affiliations of entities with this node. | |
499 | |
500 @return: deferred that returns a C{list} of tuples (jid, affiliation), | |
501 where jid is a L(JID<twisted.words.protocols.jabber.jid.JID>) | |
502 and affiliation is one of C{'owner'}, | |
503 C{'publisher'}, C{'outcast'}. | |
504 """ | |
505 | |
506 | |
507 | |
508 class ILeafNode(Interface): | |
509 """ | |
510 Interface to the class of objects that represent leaf nodes. | |
511 """ | |
512 | |
513 def storeItems(items, publisher): | |
514 """ | |
515 Store items in persistent storage for later retrieval. | |
516 | |
517 @param items: The list of items to be stored. Each item is the | |
518 L{domish} representation of the XML fragment as defined | |
519 for C{<item/>} in the | |
520 C{http://jabber.org/protocol/pubsub} namespace. | |
521 @type items: C{list} of {domish.Element} | |
522 @param publisher: JID of the publishing entity. | |
523 @type publisher: L{JID<twisted.words.protocols.jabber.jid.JID>} | |
524 @return: deferred that fires upon success. | |
525 """ | |
526 | |
527 | |
528 def removeItems(itemIdentifiers): | |
529 """ | |
530 Remove items by id. | |
531 | |
532 @param itemIdentifiers: C{list} of item ids. | |
533 @return: deferred that fires with a C{list} of ids of the items that | |
534 were deleted | |
535 """ | |
536 | |
537 | |
538 def getItems(authorized_groups, unrestricted, maxItems=None): | |
539 """ Get all authorised items | |
540 If C{maxItems} is not given, all authorised items in the node are returned, | |
541 just like C{getItemsById}. Otherwise, C{maxItems} limits | |
542 the returned items to a maximum of that number of most recently | |
543 published and authorised items. | |
544 | |
545 @param authorized_groups: we want to get items that these groups can access | |
546 @param unrestricted: if true, don't check permissions (i.e.: get all items) | |
547 @param maxItems: if given, a natural number (>0) that limits the | |
548 returned number of items. | |
549 @return: deferred that fires a C{list} of (item, access_model, id) | |
550 if unrestricted is True, else a C{list} of items. | |
551 """ | |
552 | |
553 | |
554 def countItems(authorized_groups, unrestricted): | |
555 """ Count the accessible items. | |
556 | |
557 @param authorized_groups: we want to get items that these groups can access. | |
558 @param unrestricted: if true, don't check permissions (i.e.: get all items). | |
559 @return: deferred that fires a C{int}. | |
560 """ | |
561 | |
562 | |
563 def getIndex(authorized_groups, unrestricted, item): | |
564 """ Retrieve the index of the given item within the accessible window. | |
565 | |
566 @param authorized_groups: we want to get items that these groups can access. | |
567 @param unrestricted: if true, don't check permissions (i.e.: get all items). | |
568 @param item: item identifier. | |
569 @return: deferred that fires a C{int}. | |
570 """ | |
571 | |
572 def getItemsById(authorized_groups, unrestricted, itemIdentifiers): | |
573 """ | |
574 Get items by item id. | |
575 | |
576 Each item in the returned list is a unicode string that | |
577 represent the XML of the item as it was published, including the | |
578 item wrapper with item id. | |
579 | |
580 @param authorized_groups: we want to get items that these groups can access | |
581 @param unrestricted: if true, don't check permissions | |
582 @param itemIdentifiers: C{list} of item ids. | |
583 @return: deferred that fires a C{list} of (item, access_model, id) | |
584 if unrestricted is True, else a C{list} of items. | |
585 """ | |
586 | |
587 | |
588 def purge(): | |
589 """ | |
590 Purge node of all items in persistent storage. | |
591 | |
592 @return: deferred that fires when the node has been purged. | |
593 """ | |
594 | |
595 | |
596 def filterItemsWithPublisher(itemIdentifiers, requestor): | |
597 """ | |
598 Filter the given items by checking the items publisher against the requestor. | |
599 | |
600 @param itemIdentifiers: C{list} of item ids. | |
601 @param requestor: JID of the requestor. | |
602 @type requestor: L{JID<twisted.words.protocols.jabber.jid.JID>} | |
603 @return: deferred that fires with a C{list} of item identifiers. | |
604 """ | |
605 | |
606 class IGatewayStorage(Interface): | |
607 | |
608 def addCallback(service, nodeIdentifier, callback): | |
609 """ | |
610 Register a callback URI. | |
611 | |
612 The registered HTTP callback URI will have an Atom Entry documented | |
613 POSTed to it upon receiving a notification for the given pubsub node. | |
614 | |
615 @param service: The XMPP entity that holds the node. | |
616 @type service: L{JID<twisted.words.protocols.jabber.jid.JID>} | |
617 @param nodeIdentifier: The identifier of the publish-subscribe node. | |
618 @type nodeIdentifier: C{unicode}. | |
619 @param callback: The callback URI to be registered. | |
620 @type callback: C{str}. | |
621 @rtype: L{Deferred<twisted.internet.defer.Deferred>} | |
622 """ | |
623 | |
624 def removeCallback(service, nodeIdentifier, callback): | |
625 """ | |
626 Remove a registered callback URI. | |
627 | |
628 The returned deferred will fire with a boolean that signals wether or | |
629 not this was the last callback unregistered for this node. | |
630 | |
631 @param service: The XMPP entity that holds the node. | |
632 @type service: L{JID<twisted.words.protocols.jabber.jid.JID>} | |
633 @param nodeIdentifier: The identifier of the publish-subscribe node. | |
634 @type nodeIdentifier: C{unicode}. | |
635 @param callback: The callback URI to be unregistered. | |
636 @type callback: C{str}. | |
637 @rtype: L{Deferred<twisted.internet.defer.Deferred>} | |
638 """ | |
639 | |
640 def getCallbacks(service, nodeIdentifier): | |
641 """ | |
642 Get the callbacks registered for this node. | |
643 | |
644 Returns a deferred that fires with the set of HTTP callback URIs | |
645 registered for this node. | |
646 | |
647 @param service: The XMPP entity that holds the node. | |
648 @type service: L{JID<twisted.words.protocols.jabber.jid.JID>} | |
649 @param nodeIdentifier: The identifier of the publish-subscribe node. | |
650 @type nodeIdentifier: C{unicode}. | |
651 @rtype: L{Deferred<twisted.internet.defer.Deferred>} | |
652 """ | |
653 | |
654 | |
655 def hasCallbacks(service, nodeIdentifier): | |
656 """ | |
657 Return wether there are callbacks registered for a node. | |
658 | |
659 @param service: The XMPP entity that holds the node. | |
660 @type service: L{JID<twisted.words.protocols.jabber.jid.JID>} | |
661 @param nodeIdentifier: The identifier of the publish-subscribe node. | |
662 @type nodeIdentifier: C{unicode}. | |
663 @returns: Deferred that fires with a boolean. | |
664 @rtype: L{Deferred<twisted.internet.defer.Deferred>} | |
665 """ |