Fix the xep_0009 import (no more relatives)
[slixmpp.git] / sleekxmpp / plugins / xep_0009 / rpc.py
blobfc306d31c4047771dec36e25bebc11e8d58ee6d3
1 """
2 SleekXMPP: The Sleek XMPP Library
3 Copyright (C) 2011 Nathanael C. Fritz, Dann Martens (TOMOTON).
4 This file is part of SleekXMPP.
6 See the file LICENSE for copying permission.
7 """
9 from sleekxmpp.plugins import base
10 from sleekxmpp.plugins.xep_0009.stanza.RPC import RPCQuery, MethodCall, MethodResponse
11 from sleekxmpp.stanza.iq import Iq
12 from sleekxmpp.xmlstream.handler.callback import Callback
13 from sleekxmpp.xmlstream.matcher.xpath import MatchXPath
14 from sleekxmpp.xmlstream.stanzabase import register_stanza_plugin
15 from xml.etree import cElementTree as ET
16 import logging
20 log = logging.getLogger(__name__)
24 class xep_0009(base.base_plugin):
26 def plugin_init(self):
27 self.xep = '0009'
28 self.description = 'Jabber-RPC'
29 #self.stanza = sleekxmpp.plugins.xep_0009.stanza
31 register_stanza_plugin(Iq, RPCQuery)
32 register_stanza_plugin(RPCQuery, MethodCall)
33 register_stanza_plugin(RPCQuery, MethodResponse)
35 self.xmpp.registerHandler(
36 Callback('RPC Call', MatchXPath('{%s}iq/{%s}query/{%s}methodCall' % (self.xmpp.default_ns, RPCQuery.namespace, RPCQuery.namespace)),
37 self._handle_method_call)
39 self.xmpp.registerHandler(
40 Callback('RPC Call', MatchXPath('{%s}iq/{%s}query/{%s}methodResponse' % (self.xmpp.default_ns, RPCQuery.namespace, RPCQuery.namespace)),
41 self._handle_method_response)
43 self.xmpp.registerHandler(
44 Callback('RPC Call', MatchXPath('{%s}iq/{%s}error' % (self.xmpp.default_ns, self.xmpp.default_ns)),
45 self._handle_error)
47 self.xmpp.add_event_handler('jabber_rpc_method_call', self._on_jabber_rpc_method_call)
48 self.xmpp.add_event_handler('jabber_rpc_method_response', self._on_jabber_rpc_method_response)
49 self.xmpp.add_event_handler('jabber_rpc_method_fault', self._on_jabber_rpc_method_fault)
50 self.xmpp.add_event_handler('jabber_rpc_error', self._on_jabber_rpc_error)
51 self.xmpp.add_event_handler('error', self._handle_error)
52 #self.activeCalls = []
54 def post_init(self):
55 base.base_plugin.post_init(self)
56 self.xmpp.plugin['xep_0030'].add_feature('jabber:iq:rpc')
57 self.xmpp.plugin['xep_0030'].add_identity('automation','rpc')
59 def make_iq_method_call(self, pto, pmethod, params):
60 iq = self.xmpp.makeIqSet()
61 iq.attrib['to'] = pto
62 iq.attrib['from'] = self.xmpp.boundjid.full
63 iq.enable('rpc_query')
64 iq['rpc_query']['method_call']['method_name'] = pmethod
65 iq['rpc_query']['method_call']['params'] = params
66 return iq;
68 def make_iq_method_response(self, pid, pto, params):
69 iq = self.xmpp.makeIqResult(pid)
70 iq.attrib['to'] = pto
71 iq.attrib['from'] = self.xmpp.boundjid.full
72 iq.enable('rpc_query')
73 iq['rpc_query']['method_response']['params'] = params
74 return iq
76 def make_iq_method_response_fault(self, pid, pto, params):
77 iq = self.xmpp.makeIqResult(pid)
78 iq.attrib['to'] = pto
79 iq.attrib['from'] = self.xmpp.boundjid.full
80 iq.enable('rpc_query')
81 iq['rpc_query']['method_response']['params'] = None
82 iq['rpc_query']['method_response']['fault'] = params
83 return iq
85 # def make_iq_method_error(self, pto, pid, pmethod, params, code, type, condition):
86 # iq = self.xmpp.makeIqError(pid)
87 # iq.attrib['to'] = pto
88 # iq.attrib['from'] = self.xmpp.boundjid.full
89 # iq['error']['code'] = code
90 # iq['error']['type'] = type
91 # iq['error']['condition'] = condition
92 # iq['rpc_query']['method_call']['method_name'] = pmethod
93 # iq['rpc_query']['method_call']['params'] = params
94 # return iq
96 def _item_not_found(self, iq):
97 payload = iq.get_payload()
98 iq.reply().error().set_payload(payload);
99 iq['error']['code'] = '404'
100 iq['error']['type'] = 'cancel'
101 iq['error']['condition'] = 'item-not-found'
102 return iq
104 def _undefined_condition(self, iq):
105 payload = iq.get_payload()
106 iq.reply().error().set_payload(payload)
107 iq['error']['code'] = '500'
108 iq['error']['type'] = 'cancel'
109 iq['error']['condition'] = 'undefined-condition'
110 return iq
112 def _forbidden(self, iq):
113 payload = iq.get_payload()
114 iq.reply().error().set_payload(payload)
115 iq['error']['code'] = '403'
116 iq['error']['type'] = 'auth'
117 iq['error']['condition'] = 'forbidden'
118 return iq
120 def _recipient_unvailable(self, iq):
121 payload = iq.get_payload()
122 iq.reply().error().set_payload(payload)
123 iq['error']['code'] = '404'
124 iq['error']['type'] = 'wait'
125 iq['error']['condition'] = 'recipient-unavailable'
126 return iq
128 def _handle_method_call(self, iq):
129 type = iq['type']
130 if type == 'set':
131 log.debug("Incoming Jabber-RPC call from %s" % iq['from'])
132 self.xmpp.event('jabber_rpc_method_call', iq)
133 else:
134 if type == 'error' and ['rpc_query'] is None:
135 self.handle_error(iq)
136 else:
137 log.debug("Incoming Jabber-RPC error from %s" % iq['from'])
138 self.xmpp.event('jabber_rpc_error', iq)
140 def _handle_method_response(self, iq):
141 if iq['rpc_query']['method_response']['fault'] is not None:
142 log.debug("Incoming Jabber-RPC fault from %s" % iq['from'])
143 #self._on_jabber_rpc_method_fault(iq)
144 self.xmpp.event('jabber_rpc_method_fault', iq)
145 else:
146 log.debug("Incoming Jabber-RPC response from %s" % iq['from'])
147 self.xmpp.event('jabber_rpc_method_response', iq)
149 def _handle_error(self, iq):
150 print("['XEP-0009']._handle_error -> ERROR! Iq is '%s'" % iq)
151 print("#######################")
152 print("### NOT IMPLEMENTED ###")
153 print("#######################")
155 def _on_jabber_rpc_method_call(self, iq, forwarded=False):
157 A default handler for Jabber-RPC method call. If another
158 handler is registered, this one will defer and not run.
160 If this handler is called by your own custom handler with
161 forwarded set to True, then it will run as normal.
163 if not forwarded and self.xmpp.event_handled('jabber_rpc_method_call') > 1:
164 return
165 # Reply with error by default
166 error = self.client.plugin['xep_0009']._item_not_found(iq)
167 error.send()
169 def _on_jabber_rpc_method_response(self, iq, forwarded=False):
171 A default handler for Jabber-RPC method response. If another
172 handler is registered, this one will defer and not run.
174 If this handler is called by your own custom handler with
175 forwarded set to True, then it will run as normal.
177 if not forwarded and self.xmpp.event_handled('jabber_rpc_method_response') > 1:
178 return
179 error = self.client.plugin['xep_0009']._recpient_unavailable(iq)
180 error.send()
182 def _on_jabber_rpc_method_fault(self, iq, forwarded=False):
184 A default handler for Jabber-RPC fault response. If another
185 handler is registered, this one will defer and not run.
187 If this handler is called by your own custom handler with
188 forwarded set to True, then it will run as normal.
190 if not forwarded and self.xmpp.event_handled('jabber_rpc_method_fault') > 1:
191 return
192 error = self.client.plugin['xep_0009']._recpient_unavailable(iq)
193 error.send()
195 def _on_jabber_rpc_error(self, iq, forwarded=False):
197 A default handler for Jabber-RPC error response. If another
198 handler is registered, this one will defer and not run.
200 If this handler is called by your own custom handler with
201 forwarded set to True, then it will run as normal.
203 if not forwarded and self.xmpp.event_handled('jabber_rpc_error') > 1:
204 return
205 error = self.client.plugin['xep_0009']._recpient_unavailable(iq, iq.get_payload())
206 error.send()
208 def _send_fault(self, iq, fault_xml): #
209 fault = self.make_iq_method_response_fault(iq['id'], iq['from'], fault_xml)
210 fault.send()
212 def _send_error(self, iq):
213 print("['XEP-0009']._send_error -> ERROR! Iq is '%s'" % iq)
214 print("#######################")
215 print("### NOT IMPLEMENTED ###")
216 print("#######################")
218 def _extract_method(self, stanza):
219 xml = ET.fromstring("%s" % stanza)
220 return xml.find("./methodCall/methodName").text