Mercurial > libervia-backend
comparison src/plugins/plugin_xep_0059.py @ 1219:16484ebb695b
plugin XEP-0059: first draft, pubsub and jabber search do not exploit it yet
author | souliane <souliane@mailoo.org> |
---|---|
date | Mon, 22 Sep 2014 22:25:44 +0200 |
parents | |
children | ea692d51a0ee |
comparison
equal
deleted
inserted
replaced
1218:3b1c5f723c4b | 1219:16484ebb695b |
---|---|
1 #!/usr/bin/python | |
2 # -*- coding: utf-8 -*- | |
3 | |
4 # SAT plugin for Result Set Management (XEP-0059) | |
5 # Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 Jérôme Poisson (goffi@goffi.org) | |
6 # Copyright (C) 2013, 2014 Adrien Cossa (souliane@mailoo.org) | |
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 from sat.core.i18n import _ | |
22 from sat.core.log import getLogger | |
23 log = getLogger(__name__) | |
24 | |
25 from twisted.words.xish import domish | |
26 from wokkel import disco, iwokkel | |
27 try: | |
28 from twisted.words.protocols.xmlstream import XMPPHandler | |
29 except ImportError: | |
30 from wokkel.subprotocols import XMPPHandler | |
31 from zope.interface import implements | |
32 | |
33 | |
34 NS_RSM = 'http://jabber.org/protocol/rsm' | |
35 | |
36 PLUGIN_INFO = { | |
37 "name": "Result Set Management", | |
38 "import_name": "XEP-0059", | |
39 "type": "XEP", | |
40 "protocols": ["XEP-0059"], | |
41 "main": "XEP_0059", | |
42 "handler": "no", | |
43 "description": _("""Implementation of Result Set Management""") | |
44 } | |
45 | |
46 | |
47 class XEP_0059(object): | |
48 | |
49 def __init__(self, host): | |
50 log.info(_("Result Set Management plugin initialization")) | |
51 self.host = host | |
52 | |
53 def requestPage(self, stanza, limit=10, index=None, after=None, before=None): | |
54 """Embed a RSM page request in the given stanza. | |
55 | |
56 @param stanza (domish.Element): any stanza to which RSM applies | |
57 @param limit (int): the maximum number of items in the page | |
58 @param index (int): the starting index of the requested page | |
59 @param after (str, int): the element immediately preceding the page | |
60 @param before (str, int): the element immediately following the page | |
61 """ | |
62 main_elt = None | |
63 try: | |
64 main_elt = domish.generateElementsNamed(stanza.elements(), name="query").next() | |
65 except StopIteration: | |
66 try: | |
67 main_elt = domish.generateElementsNamed(stanza.elements(), name="pubsub").next() | |
68 except StopIteration: | |
69 log.warning("Injection of a RSM element only applies to query or pubsub stanzas") | |
70 return | |
71 limit = str(int(limit)) | |
72 | |
73 # in case the service doesn't support RSM, do this at least | |
74 main_elt.items.attributes['max_items'] = limit | |
75 | |
76 set_elt = main_elt.addElement('set', NS_RSM) | |
77 set_elt.addElement('max').addContent(limit) | |
78 if index: | |
79 assert(after is None and before is None) | |
80 set_elt.addElement('index').addContent(str(int(index))) | |
81 if after: | |
82 assert(before is None) # could not specify both at the same time | |
83 set_elt.addElement('after').addContent(str(after)) | |
84 if before is not None: | |
85 if before == '': # request the last page, according to http://xmpp.org/extensions/xep-0059.html#last | |
86 set_elt.addElement('before') | |
87 else: | |
88 set_elt.addElement('before').addContent(str(before)) | |
89 | |
90 def countItems(self, stanza): | |
91 """Count the items without retrieving any of them. | |
92 | |
93 @param stanza (domish.Element): any stanza to which RSM applies | |
94 """ | |
95 self.requestPage(stanza, limit=0) | |
96 | |
97 def extractMetadata(self, stanza): | |
98 """Extract the RSM metadata from the given stanza. | |
99 | |
100 @param stanza (domish.Element, wokkel.pubsub.PubSubRequest): | |
101 any stanza to which RSM applies. When used by XEP-0060, | |
102 wokkel's PubSubRequest instance is also accepted. | |
103 @return: dict containing the page metadata | |
104 """ | |
105 try: | |
106 main_elt = domish.generateElementsNamed(stanza.elements(), name="query").next() | |
107 except StopIteration: | |
108 try: | |
109 main_elt = domish.generateElementsNamed(stanza.elements(), name="pubsub").next() | |
110 except StopIteration: | |
111 log.warning("Extracting data from a RSM element only applies to query or pubsub stanzas") | |
112 return {} | |
113 try: | |
114 set_elt = domish.generateElementsQNamed(main_elt.elements(), name="set", uri=NS_RSM).next() | |
115 except StopIteration: | |
116 log.debug("There's no RSM element in the stanza") | |
117 return {} | |
118 | |
119 data = {} | |
120 elts = set_elt.elements() | |
121 try: | |
122 elt = elts.next() | |
123 if elt.name == "first": | |
124 data["first"] = "".join(elt.children) | |
125 data["first_index"] = int(elt.getAttribute("index")) | |
126 elif elt.name == "last": | |
127 data["last"] = "".join(elt.children) | |
128 elif elt.name == "count": | |
129 data["count"] = int("".join(elt.children)) | |
130 except StopIteration: | |
131 pass | |
132 if "count" not in data: | |
133 log.warning("There's no 'count' element in the RSM element!") | |
134 return data | |
135 | |
136 | |
137 class XEP_0059_handler(XMPPHandler): | |
138 implements(iwokkel.IDisco) | |
139 | |
140 def __init__(self, plugin_parent, profile): | |
141 self.plugin_parent = plugin_parent | |
142 self.host = plugin_parent.host | |
143 self.profile = profile | |
144 | |
145 def getDiscoInfo(self, requestor, target, nodeIdentifier=''): | |
146 return [disco.DiscoFeature(NS_RSM)] | |
147 | |
148 def getDiscoItems(self, requestor, target, nodeIdentifier=''): | |
149 return [] |