3 from sleekxmpp.exceptions import IqError, IqTimeout
5 import xml.etree.ElementTree as ET
9 # inherit from BaseXmpp and XMLStream classes
10 class OMFClient(sleekxmpp.ClientXMPP):
12 .. class:: Class Args :
14 :param jid: Jabber Id (= Xmpp Slice + Date)
16 :param password: Jabber Password (= Xmpp Password)
21 This class is an XMPP Client with customized method
25 def __init__(self, jid, password):
28 :param jid: Jabber Id (= Xmpp Slice + Date)
30 :param password: Jabber Password (= Xmpp Password)
35 sleekxmpp.ClientXMPP.__init__(self, jid, password)
37 self._registered = False
40 self.register_plugin('xep_0077') # In-band registration
41 self.register_plugin('xep_0030')
42 self.register_plugin('xep_0059')
43 self.register_plugin('xep_0060') # PubSub
45 self.add_event_handler("session_start", self.start)
46 self.add_event_handler("register", self.register)
47 self.add_event_handler("pubsub_publish", self.handle_omf_message)
49 self._logger = logging.getLogger("nepi.omf.xmppClient")
50 self._logger.setLevel(nepi.LOGLEVEL)
54 """ Check if the client is ready
59 def start(self, event):
60 """ Send presence to the Xmppp Server. This function is called directly by the sleekXmpp library
65 self._server = "pubsub.%s" % self.boundjid.domain
67 def register(self, iq):
68 """ Register to the Xmppp Server. This function is called directly by the sleekXmpp library
72 self._logger.info(" %s already registered!" % self.boundjid)
77 resp['register']['username'] = self.boundjid.user
78 resp['register']['password'] = self.password
82 self._logger.info(" Account created for %s!" % self.boundjid)
83 self._registered = True
85 self._logger.error(" Could not register account: %s" %
86 e.iq['error']['text'])
88 self._logger.error(" No response from server.")
91 """ Unregister from the Xmppp Server.
95 self.plugin['xep_0077'].cancel_registration(
96 ifrom=self.boundjid.full)
97 self._logger.info(" Account unregistered for %s!" % self.boundjid)
99 self._logger.error(" Could not unregister account: %s" %
100 e.iq['error']['text'])
102 self._logger.error(" No response from server.")
105 """ Get all the nodes of the Xmppp Server.
109 result = self['xep_0060'].get_nodes(self._server)
110 for item in result['disco_items']['items']:
111 self._logger.info(' - %s' % str(item))
114 error = traceback.format_exc()
115 self._logger.error(' Could not retrieve node list.\ntraceback:\n%s', error)
117 def subscriptions(self):
118 """ Get all the subscriptions of the Xmppp Server.
122 result = self['xep_0060'].get_subscriptions(self._server)
124 for node in result['node']:
125 self._logger.info(' - %s' % str(node))
128 error = traceback.format_exc()
129 self._logger.error(' Could not retrieve subscriptions.\ntraceback:\n%s', error)
131 def create(self, node):
132 """ Create the topic corresponding to the node
134 :param node: Name of the topic, corresponding to the node (ex : omf.plexus.wlab17)
138 self._logger.debug(" Create Topic : " + node)
140 config = self['xep_0004'].makeForm('submit')
141 config.add_field(var='pubsub#node_type', value='leaf')
142 config.add_field(var='pubsub#notify_retract', value='0')
143 config.add_field(var='pubsub#publish_model', value='open')
144 config.add_field(var='pubsub#persist_items', value='1')
145 config.add_field(var='pubsub#max_items', value='1')
146 config.add_field(var='pubsub#title', value=node)
149 self['xep_0060'].create_node(self._server, node, config = config)
151 error = traceback.format_exc()
152 self._logger.error(' Could not create topic: %s\ntraceback:\n%s' % (node, error))
154 def delete(self, node):
155 """ Delete the topic corresponding to the node
157 :param node: Name of the topic, corresponding to the node (ex : omf.plexus.wlab17)
161 # To check if the queue are well empty at the end
162 #print " length of the queue : " + str(self.send_queue.qsize())
163 #print " length of the queue : " + str(self.event_queue.qsize())
165 self['xep_0060'].delete_node(self._server, node)
166 self._logger.info(' Deleted node: %s' % node)
168 error = traceback.format_exc()
169 self._logger.error(' Could not delete topic: %s\ntraceback:\n%s' % (node, error))
171 def publish(self, data, node):
172 """ Publish the data to the corresponding topic
174 :param data: Data that will be published
176 :param node: Name of the topic
181 self._logger.debug(" Publish to Topic : " + node)
183 result = self['xep_0060'].publish(self._server,node,payload=data)
184 # id = result['pubsub']['publish']['item']['id']
185 # print('Published at item id: %s' % id)
187 error = traceback.format_exc()
188 self._logger.error(' Could not publish to: %s\ntraceback:\n%s' \
194 :param data: data from which the items will be get back
200 result = self['xep_0060'].get_item(self._server, self.boundjid,
202 for item in result['pubsub']['items']['substanzas']:
203 self._logger.info('Retrieved item %s: %s' % (item['id'],
204 tostring(item['payload'])))
206 error = traceback.format_exc()
207 self._logger.error(' Could not retrieve item %s from topic %s\ntraceback:\n%s' \
208 % (data, self.boundjid, error))
210 def retract(self, data):
213 :param data: data from which the item will be retracted
218 result = self['xep_0060'].retract(self._server, self.boundjid, data)
219 self._logger.info(' Retracted item %s from topic %s' % (data, self.boundjid))
221 error = traceback.format_exc()
222 self._logger.error(' Could not retract item %s from topic %s\ntraceback:\n%s' \
223 % (data, self.boundjid, error))
226 """ Purge the information in the server
230 result = self['xep_0060'].purge(self._server, self.boundjid)
231 self._logger.info(' Purged all items from topic %s' % self.boundjid)
233 error = traceback.format_exc()
234 self._logger.error(' Could not purge items from topic %s\ntraceback:\n%s' \
235 % (self.boundjid, error))
237 def subscribe(self, node):
238 """ Subscribe to a topic
240 :param node: Name of the topic
245 result = self['xep_0060'].subscribe(self._server, node)
246 #self._logger.debug('Subscribed %s to node %s' \
247 #% (self.boundjid.bare, node))
248 self._logger.info(' Subscribed %s to topic %s' \
249 % (self.boundjid.user, node))
251 error = traceback.format_exc()
252 self._logger.error(' Could not subscribe %s to topic %s\ntraceback:\n%s' \
253 % (self.boundjid.bare, node, error))
255 def unsubscribe(self, node):
256 """ Unsubscribe to a topic
258 :param node: Name of the topic
263 result = self['xep_0060'].unsubscribe(self._server, node)
264 self._logger.info(' Unsubscribed %s from topic %s' % (self.boundjid.bare, node))
266 error = traceback.format_exc()
267 self._logger.error(' Could not unsubscribe %s from topic %s\ntraceback:\n%s' \
268 % (self.boundjid.bare, node, error))
270 def _check_for_tag(self, root, namespaces, tag):
271 """ Check if an element markup is in the ElementTree
273 :param root: Root of the tree
274 :type root: ElementTree Element
275 :param namespaces: Namespaces of the element
276 :type namespaces: str
277 :param tag: Tag that will search in the tree
281 for element in root.iter(namespaces+tag):
287 def _check_output(self, root, namespaces):
288 """ Check the significative element in the answer and display it
290 :param root: Root of the tree
291 :type root: ElementTree Element
292 :param namespaces: Namespaces of the tree
293 :type namespaces: str
296 fields = ["TARGET", "REASON", "PATH", "APPID", "VALUE"]
299 msg = self._check_for_tag(root, namespaces, elt)
301 response = response + " " + msg.text + " :"
302 deb = self._check_for_tag(root, namespaces, "MESSAGE")
304 self._logger.debug(response + " " + deb.text)
306 self._logger.info(response)
308 def handle_omf_message(self, iq):
309 """ Handle published/received message
311 :param iq: Stanzas that is currently published/received
315 namespaces = "{http://jabber.org/protocol/pubsub}"
316 for i in iq['pubsub_event']['items']:
317 root = ET.fromstring(str(i))
318 self._check_output(root, namespaces)