3764f657d82919db1b269fdc9b740ce53bf74bc0
[nepi.git] / src / neco / resources / omf / omf_client.py
1 import logging
2 import sleekxmpp
3 from sleekxmpp.exceptions import IqError, IqTimeout
4 import traceback
5 import xml.etree.ElementTree as ET
6
7 import neco
8
9 class OMFClient(sleekxmpp.ClientXMPP):
10     """
11     .. class:: Class Args :
12       
13         :param jid: Jabber Id (= Xmpp Slice + Date)
14         :type jid: Str
15         :param password: Jabber Password (= Xmpp Password)
16         :type password: Str
17
18     .. note::
19
20        This class is an XMPP Client with customized method
21
22     """
23
24     def __init__(self, jid, password):
25         sleekxmpp.ClientXMPP.__init__(self, jid, password)
26         self._ready = False
27         self._registered = False
28         self._server = None
29
30         self.register_plugin('xep_0077') # In-band registration
31         self.register_plugin('xep_0030')
32         self.register_plugin('xep_0059')
33         self.register_plugin('xep_0060') # PubSub 
34
35         self.add_event_handler("session_start", self.start)
36         self.add_event_handler("register", self.register)
37         self.add_event_handler("pubsub_publish", self.handle_omf_message)
38         
39         self._logger = logging.getLogger("neco.omf.xmppClient")
40         self._logger.setLevel(neco.LOGLEVEL)
41
42     @property
43     def ready(self):
44         return self._ready
45
46     def start(self, event):
47         self.send_presence()
48         self._ready = True
49         self._server = "pubsub.%s" % self.boundjid.domain
50
51     def register(self, iq):
52         if self._registered:
53             self._logger.info("%s already registered!" % self.boundjid)
54             return 
55
56         resp = self.Iq()
57         resp['type'] = 'set'
58         resp['register']['username'] = self.boundjid.user
59         resp['register']['password'] = self.password
60
61         try:
62             resp.send(now=True)
63             self._logger.info("Account created for %s!" % self.boundjid)
64             self._registered = True
65         except IqError as e:
66             self._logger.error("Could not register account: %s" %
67                     e.iq['error']['text'])
68         except IqTimeout:
69             self._logger.error("No response from server.")
70
71     def unregister(self):
72         try:
73             self.plugin['xep_0077'].cancel_registration(
74                 ifrom=self.boundjid.full)
75             self._logger.info("Account unregistered for %s!" % self.boundjid)
76         except IqError as e:
77             self._logger.error("Could not unregister account: %s" %
78                     e.iq['error']['text'])
79         except IqTimeout:
80             self._logger.error("No response from server.")
81
82     def nodes(self):
83         try:
84             result = self['xep_0060'].get_nodes(self._server)
85             for item in result['disco_items']['items']:
86                 self._logger.info(' - %s' % str(item))
87             return result
88         except:
89             error = traceback.format_exc()
90             self._logger.error('Could not retrieve node list.\ntraceback:\n%s', error)
91
92     def subscriptions(self):
93         try:
94             result = self['xep_0060'].get_subscriptions(self._server)
95                 #self.boundjid.full)
96             for node in result['node']:
97                 self._logger.info(' - %s' % str(node))
98             return result
99         except:
100             error = traceback.format_exc()
101             self._logger.error('Could not retrieve subscriptions.\ntraceback:\n%s', error)
102
103     def create(self, node):
104         self._logger.debug(" Create Topic : " + node)
105    
106         config = self['xep_0004'].makeForm('submit')
107         config.add_field(var='pubsub#node_type', value='leaf')
108         config.add_field(var='pubsub#notify_retract', value='0')
109         config.add_field(var='pubsub#publish_model', value='open')
110         config.add_field(var='pubsub#persist_items', value='1')
111         config.add_field(var='pubsub#max_items', value='1')
112         config.add_field(var='pubsub#title', value=node)
113
114         try:
115             self['xep_0060'].create_node(self._server, node, config = config)
116         except:
117             error = traceback.format_exc()
118             self._logger.error('Could not create topic: %s\ntraceback:\n%s' % (node, error))
119
120     def delete(self, node):
121         try:
122             self['xep_0060'].delete_node(self._server, node)
123             self._logger.info('Deleted node: %s' % node)
124         except:
125             error = traceback.format_exc()
126             self._logger.error('Could not delete topic: %s\ntraceback:\n%s' % (node, error))
127     
128     def publish(self, data, node):
129         self._logger.debug(" Publish to Topic :" + node)
130         try:
131             result = self['xep_0060'].publish(self._server,node,payload=data)
132             # id = result['pubsub']['publish']['item']['id']
133             # print('Published at item id: %s' % id)
134         except:
135             error = traceback.format_exc()
136             self._logger.error('Could not publish to: %s\ntraceback:\n%s' \
137                     % (node, error))
138
139     def get(self, data):
140         try:
141             result = self['xep_0060'].get_item(self._server, self.boundjid,
142                 data)
143             for item in result['pubsub']['items']['substanzas']:
144                 self._logger.info('Retrieved item %s: %s' % (item['id'], 
145                     tostring(item['payload'])))
146         except:
147             error = traceback.format_exc()
148             self._logger.error('Could not retrieve item %s from topic %s\ntraceback:\n%s' \
149                     % (data, self.boundjid, error))
150
151     def retract(self, data):
152         try:
153             result = self['xep_0060'].retract(self._server, self.boundjid, data)
154             self._logger.info('Retracted item %s from topic %s' % (data, self.boundjid))
155         except:
156             error = traceback.format_exc()
157             self._logger.error('Could not retract item %s from topic %s\ntraceback:\n%s' \
158                     % (data, self.boundjid, error))
159
160     def purge(self):
161         try:
162             result = self['xep_0060'].purge(self._server, self.boundjid)
163             self._logger.info('Purged all items from topic %s' % self.boundjid)
164         except:
165             error = traceback.format_exc()
166             self._logger.error('Could not purge items from topic %s\ntraceback:\n%s' \
167                     % (self.boundjid, error))
168
169     def subscribe(self, node):
170         try:
171             result = self['xep_0060'].subscribe(self._server, node)
172             #self._logger.debug('Subscribed %s to node %s' \
173                     #% (self.boundjid.bare, node))
174             self._logger.info(' Subscribed %s to topic %s' \
175                     % (self.boundjid.user, node))
176         except:
177             error = traceback.format_exc()
178             self._logger.error(' Could not subscribe %s to topic %s\ntraceback:\n%s' \
179                     % (self.boundjid.bare, node, error))
180
181     def unsubscribe(self, node):
182         try:
183             result = self['xep_0060'].unsubscribe(self._server, node)
184             self._logger.info(' Unsubscribed %s from topic %s' % (self.boundjid.bare, node))
185         except:
186             error = traceback.format_exc()
187             self._logger.error(' Could not unsubscribe %s from topic %s\ntraceback:\n%s' \
188                     % (self.boundjid.bare, node, error))
189
190     def _check_for_tag(self, treeroot, namespaces, tag):
191         for element in treeroot.iter(namespaces+tag):
192             if element.text:
193                 return element
194             else : 
195                 return None    
196
197     def _check_output(self, treeroot, namespaces):
198         output_param = ["TARGET", "REASON", "PATH", "APPID", "VALUE"]
199         response = ""
200         for elt in output_param:
201             msg = self._check_for_tag(treeroot, namespaces, elt)
202             if msg is not None:
203                 response = response + " " + msg.text + " :"
204         deb = self._check_for_tag(treeroot, namespaces, "MESSAGE")
205         if deb is not None:
206             self._logger.debug(response + " " + deb.text)
207         else :
208             self._logger.info(response)
209
210     def handle_omf_message(self, iq):
211         namespaces = "{http://jabber.org/protocol/pubsub}"
212         for i in iq['pubsub_event']['items']:
213             root = ET.fromstring(str(i))
214             self._check_output(root, namespaces)
215
216