Mercurial > libervia-backend
comparison src/plugins/plugin_xep_0055.py @ 631:694f118d0cd5
plugin XEP-0055: implementation of Jabber Search
author | Goffi <goffi@goffi.org> |
---|---|
date | Sun, 08 Sep 2013 18:05:19 +0200 |
parents | |
children | 7c806491c76a |
comparison
equal
deleted
inserted
replaced
630:0b914394e74f | 631:694f118d0cd5 |
---|---|
1 #!/usr/bin/python | |
2 # -*- coding: utf-8 -*- | |
3 | |
4 # SAT plugin for Jabber Search (xep-0055) | |
5 # Copyright (C) 2009, 2010, 2011, 2012, 2013 Jérôme Poisson (goffi@goffi.org) | |
6 | |
7 # This program is free software: you can redistribute it and/or modify | |
8 # it under the terms of the GNU Affero General Public License as published by | |
9 # the Free Software Foundation, either version 3 of the License, or | |
10 # (at your option) any later version. | |
11 | |
12 # This program is distributed in the hope that it will be useful, | |
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 # GNU Affero General Public License for more details. | |
16 | |
17 # You should have received a copy of the GNU Affero General Public License | |
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | |
20 from logging import debug, info, warning, error | |
21 from twisted.words.protocols.jabber.xmlstream import IQ | |
22 from twisted.words.protocols.jabber import jid | |
23 from wokkel import data_form | |
24 from sat.core.exceptions import DataError | |
25 from sat.tools.xml_tools import dataForm2XML, dataFormResult2XML | |
26 | |
27 NS_SEARCH = 'jabber:iq:search' | |
28 | |
29 PLUGIN_INFO = { | |
30 "name": "Jabber Search", | |
31 "import_name": "XEP-0055", | |
32 "type": "XEP", | |
33 "protocols": ["XEP-0055"], | |
34 "main": "XEP_0055", | |
35 "handler": "no", | |
36 "description": _("""Implementation of Jabber Search""") | |
37 } | |
38 | |
39 | |
40 class XEP_0055(object): | |
41 | |
42 def __init__(self, host): | |
43 info(_("Jabber search plugin initialization")) | |
44 self.host = host | |
45 host.bridge.addMethod("getSearchUI", ".plugin", in_sign='ss', out_sign='s', | |
46 method=self._getSearchUI, | |
47 async=True) | |
48 host.bridge.addMethod("searchRequest", ".plugin", in_sign='sa{ss}s', out_sign='s', | |
49 method=self._searchRequest, | |
50 async=True) | |
51 | |
52 def _getSearchUI(self, to_jid_s, profile_key): | |
53 return self.getSearchUI(jid.JID(to_jid_s), profile_key) | |
54 | |
55 def getSearchUI(self, to_jid, profile_key): | |
56 """ Ask for a search interface | |
57 @param to_jid: XEP-0055 compliant search entity | |
58 @param profile_key: %(doc_profile_key)s | |
59 @return: XMLUI search interface """ | |
60 client = self.host.getClient(profile_key) | |
61 fields_request = IQ(client.xmlstream, 'get') | |
62 fields_request["from"] = client.jid.full() | |
63 fields_request["to"] = to_jid.full() | |
64 fields_request.addElement('query', NS_SEARCH) | |
65 d = fields_request.send(to_jid.full()) | |
66 d.addCallbacks(self._fieldsOk, self._fieldsErr, callbackArgs=[client.profile], errbackArgs=[client.profile]) | |
67 return d | |
68 | |
69 def _fieldsOk(self, answer, profile): | |
70 """got fields available""" | |
71 try: | |
72 query_elts = answer.elements('jabber:iq:search', 'query').next() | |
73 except StopIteration: | |
74 info(_("No query element found")) | |
75 raise DataError # FIXME: StanzaError is probably more appropriate, check the RFC | |
76 try: | |
77 form_elt = query_elts.elements(data_form.NS_X_DATA, 'x').next() | |
78 except StopIteration: | |
79 info(_("No data form found")) | |
80 raise NotImplementedError("Only search through data form is implemented so far") | |
81 parsed_form = data_form.Form.fromElement(form_elt) | |
82 return dataForm2XML(parsed_form) | |
83 | |
84 def _fieldsErr(self, failure, profile): | |
85 """ Called when something is wrong with fields request """ | |
86 info(_("Fields request failure: %s") % str(failure.value)) | |
87 return failure | |
88 | |
89 def _searchRequest(self, to_jid_s, search_dict, profile_key): | |
90 return self.searchRequest(jid.JID(to_jid_s), search_dict, profile_key) | |
91 | |
92 def searchRequest(self, to_jid, search_dict, profile_key): | |
93 """ Actually do a search, according to filled data | |
94 @param to_jid: XEP-0055 compliant search entity | |
95 @param search_dict: filled data, corresponding to the form obtained in getSearchUI | |
96 @param profile_key: %(doc_profile_key)s | |
97 @return: XMLUI search result """ | |
98 client = self.host.getClient(profile_key) | |
99 search_request = IQ(client.xmlstream, 'set') | |
100 search_request["from"] = client.jid.full() | |
101 search_request["to"] = to_jid.full() | |
102 query_elt = search_request.addElement('query', NS_SEARCH) | |
103 x_form = data_form.Form('submit') | |
104 x_form.makeFields(search_dict) | |
105 query_elt.addChild(x_form.toElement()) | |
106 d = search_request.send(to_jid.full()) | |
107 d.addCallbacks(self._searchOk, self._searchErr, callbackArgs=[client.profile], errbackArgs=[client.profile]) | |
108 return d | |
109 | |
110 def _searchOk(self, answer, profile): | |
111 """got search available""" | |
112 try: | |
113 query_elts = answer.elements('jabber:iq:search', 'query').next() | |
114 except StopIteration: | |
115 info(_("No query element found")) | |
116 raise DataError # FIXME: StanzaError is probably more appropriate, check the RFC | |
117 try: | |
118 form_elt = query_elts.elements(data_form.NS_X_DATA, 'x').next() | |
119 except StopIteration: | |
120 info(_("No data form found")) | |
121 raise NotImplementedError("Only search through data form is implemented so far") | |
122 xmlui = dataFormResult2XML(form_elt) | |
123 print "=== XMLUI ===\n%s\n\n" % xmlui | |
124 return xmlui | |
125 | |
126 | |
127 def _searchErr(self, failure, profile): | |
128 """ Called when something is wrong with search request """ | |
129 info(_("Search request failure: %s") % str(failure.value)) | |
130 return failure |