comparison idavoll/pubsub.py @ 38:c9ddca3cce20

Change exception classes to include stanza error. Change name of exception base class to Error. Change backend error map to have a tuple as value: stanza-error, pubsub-error. Remove empty componentConnected() definition in Service. Move registering of notification from __init__ to componentConnected in ComponentServiceFromNotificationService. Add observers for subscribe, options and configure.
author Ralph Meijer <ralphm@ik.nu>
date Sun, 31 Oct 2004 16:03:50 +0000
parents fa866793075d
children 31eb00734cc5
comparison
equal deleted inserted replaced
37:9aa20efac203 38:c9ddca3cce20
17 PUBSUB_GET = IQ_GET + PUBSUB_ELEMENT 17 PUBSUB_GET = IQ_GET + PUBSUB_ELEMENT
18 PUBSUB_SET = IQ_SET + PUBSUB_ELEMENT 18 PUBSUB_SET = IQ_SET + PUBSUB_ELEMENT
19 PUBSUB_CREATE = PUBSUB_SET + '/create' 19 PUBSUB_CREATE = PUBSUB_SET + '/create'
20 PUBSUB_PUBLISH = PUBSUB_SET + '/publish' 20 PUBSUB_PUBLISH = PUBSUB_SET + '/publish'
21 PUBSUB_SUBSCRIBE = PUBSUB_SET + '/subscribe' 21 PUBSUB_SUBSCRIBE = PUBSUB_SET + '/subscribe'
22 PUBSUB_UNSUBSCRIBE = PUBSUB_SET + '/unsubscribe'
22 PUBSUB_OPTIONS_GET = PUBSUB_GET + '/options' 23 PUBSUB_OPTIONS_GET = PUBSUB_GET + '/options'
23 PUBSUB_OPTIONS_SET = PUBSUB_SET + '/options' 24 PUBSUB_OPTIONS_SET = PUBSUB_SET + '/options'
24 PUBSUB_CONFIGURE_GET = PUBSUB_GET + '/configure' 25 PUBSUB_CONFIGURE_GET = PUBSUB_GET + '/configure'
25 PUBSUB_CONFIGURE_SET = PUBSUB_SET + '/configure' 26 PUBSUB_CONFIGURE_SET = PUBSUB_SET + '/configure'
26 27
27 class PubSubError(Exception): 28 class Error(Exception):
28 pubsub_error = None 29 pubsub_error = None
30 stanza_error = None
29 msg = '' 31 msg = ''
30 32
31 class NotImplemented(PubSubError): 33 class NotImplemented(Error):
32 pass 34 stanza_error = 'feature-not-implemented'
33 35
34 class OptionsUnavailable(PubSubError): 36 class OptionsUnavailable(Error):
37 stanza_error = 'feature-not-implemented'
35 pubsub_error = 'subscription-options-unavailable' 38 pubsub_error = 'subscription-options-unavailable'
36 39
37 class SubscriptionOptionsUnavailable(PubSubError): 40 class SubscriptionOptionsUnavailable(Error):
41 stanza_error = 'not-acceptable'
38 pubsub_error = 'subscription-options-unavailable' 42 pubsub_error = 'subscription-options-unavailable'
39 43
40 class NodeNotConfigurable(PubSubError): 44 class NodeNotConfigurable(Error):
45 stanza_error = 'feature-not-implemented'
41 pubsub_error = 'node-not-configurable' 46 pubsub_error = 'node-not-configurable'
42 47
43 class CreateNodeNotConfigurable(PubSubError): 48 class CreateNodeNotConfigurable(Error):
49 stanza_error = 'not-acceptable'
44 pubsub_error = 'node-not-configurable' 50 pubsub_error = 'node-not-configurable'
45 51
46 error_map = { 52 error_map = {
47 backend.NotAuthorized: 'not-authorized', 53 backend.NotAuthorized: ('not-authorized', None),
48 backend.NodeNotFound: 'item-not-found', 54 backend.NodeNotFound: ('item-not-found', None),
49 backend.NoPayloadAllowed: 'bad-request', 55 backend.NoPayloadAllowed: ('bad-request', None),
50 backend.PayloadExpected: 'bad-request', 56 backend.PayloadExpected: ('bad-request', None),
51 backend.NoInstantNodes: 'not-acceptable', 57 backend.NoInstantNodes: ('not-acceptable', None),
52 backend.NodeExists: 'conflict', 58 backend.NodeExists: ('conflict', None),
53 backend.NotImplemented: 'feature-not-implemented', 59 backend.NotImplemented: ('feature-not-implemented', None),
54 NotImplemented: 'feature-not-implemented', 60 backend.NotSubscribed: ('not-authorized', 'requestor-not-subscribed'),
55 OptionsUnavailable: 'feature-not-implemented',
56 SubscriptionOptionsUnavailable: 'not-acceptable',
57 NodeNotConfigurable: 'feature-not-implemented',
58 CreateNodeNotConfigurable: 'not-acceptable',
59 } 61 }
60 62
61 class Service(component.Service): 63 class Service(component.Service):
62 64
63 __implements__ = component.IService 65 __implements__ = component.IService
64 66
65 def __init__(self, backend): 67 def __init__(self, backend):
66 self.backend = backend 68 self.backend = backend
67 69
68 def componentConnected(self, xmlstream):
69 pass
70
71 def error(self, failure, iq): 70 def error(self, failure, iq):
72 try: 71 try:
73 r = failure.trap(*error_map.keys()) 72 e = failure.trap(Error, *error_map.keys())
74 xmpp_error.error_from_iq(iq, error_map[r], failure.value.msg) 73
75 if isinstance(failure.value, PubSubError) and \ 74 if e == Error:
76 failure.value.pubsub_error is not None: 75 stanza_error = failure.value.stanza_error
77 iq.error.addElement((NS_PUBSUB_ERRORS, 76 pubsub_error = failure.value.pubsub_error
78 failure.value.pubsub_error), 77 msg = ''
79 NS_PUBSUB_ERRORS) 78 else:
79 stanza_error, pubsub_error = error_map[e]
80 msg = failure.value.msg
81
82 xmpp_error.error_from_iq(iq, stanza_error, msg)
83 if pubsub_error:
84 iq.error.addElement((NS_PUBSUB_ERRORS, pubsub_error))
80 return iq 85 return iq
81 except: 86 except:
82 xmpp_error.error_from_iq(iq, 'internal-server-error') 87 xmpp_error.error_from_iq(iq, 'internal-server-error')
83 self.send(iq) 88 self.send(iq)
84 raise 89 raise
128 133
129 components.registerAdapter(ComponentServiceFromService, backend.IBackendService, component.IService) 134 components.registerAdapter(ComponentServiceFromService, backend.IBackendService, component.IService)
130 135
131 class ComponentServiceFromNotificationService(Service): 136 class ComponentServiceFromNotificationService(Service):
132 137
133 def __init__(self, backend): 138 def componentConnected(self, xmlstream):
134 Service.__init__(self, backend)
135 self.backend.register_notifier(self.notify) 139 self.backend.register_notifier(self.notify)
136 140
137 def notify(self, object): 141 def notify(self, object):
138 node_id = object["node_id"] 142 node_id = object["node_id"]
139 items = object["items"] 143 items = object["items"]
140 d = self.backend.get_notification_list(node_id, items) 144 d = self.backend.get_notification_list(node_id, items)
141 d.addCallback(self._notify, node_id) 145 d.addCallback(self._notify, node_id)
142 146
143 def _notify(self, list, node_id): 147 def _notify(self, list, node_id):
148 print list
144 for recipient, items in list.items(): 149 for recipient, items in list.items():
145 self._notify_recipient(recipient, node_id, items) 150 self._notify_recipient(recipient, node_id, items)
146 151
147 def _notify_recipient(self, recipient, node_id, itemlist): 152 def _notify_recipient(self, recipient, node_id, itemlist):
148 message = domish.Element((NS_COMPONENT, "message")) 153 message = domish.Element((NS_COMPONENT, "message"))
149 message["from"] = self.parent.jabberId 154 message["from"] = self.parent.jabberId
150 message["to"] = recipient 155 message["to"] = recipient
151 event = message.addElement((NS_PUBSUB_EVENT, "event"), NS_PUBSUB_EVENT) 156 event = message.addElement((NS_PUBSUB_EVENT, "event"))
152 items = event.addElement("items") 157 items = event.addElement("items")
153 items["node"] = node_id 158 items["node"] = node_id
154 items.children.extend(itemlist) 159 items.children.extend(itemlist)
155 self.send(message) 160 self.send(message)
156 161
181 186
182 class ComponentServiceFromSubscriptionService(Service): 187 class ComponentServiceFromSubscriptionService(Service):
183 188
184 def componentConnected(self, xmlstream): 189 def componentConnected(self, xmlstream):
185 xmlstream.addObserver(PUBSUB_SUBSCRIBE, self.onSubscribe) 190 xmlstream.addObserver(PUBSUB_SUBSCRIBE, self.onSubscribe)
191 xmlstream.addObserver(PUBSUB_UNSUBSCRIBE, self.onUnsubscribe)
192 xmlstream.addObserver(PUBSUB_OPTIONS_GET, self.onOptionsGet)
193 xmlstream.addObserver(PUBSUB_OPTIONS_SET, self.onOptionsSet)
186 194
187 def onSubscribe(self, iq): 195 def onSubscribe(self, iq):
188 self.handler_wrapper(self._onSubscribe, iq) 196 self.handler_wrapper(self._onSubscribe, iq)
189 197
190 def _onSubscribe(self, iq): 198 def _onSubscribe(self, iq):
192 raise SubscribeOptionsUnavailable 200 raise SubscribeOptionsUnavailable
193 201
194 node_id = iq.pubsub.subscribe["node"] 202 node_id = iq.pubsub.subscribe["node"]
195 subscriber = jid.JID(iq.pubsub.subscribe["jid"]) 203 subscriber = jid.JID(iq.pubsub.subscribe["jid"])
196 requestor = jid.JID(iq["from"]).userhostJID() 204 requestor = jid.JID(iq["from"]).userhostJID()
197 d = self.backend.do_subscribe(node_id, subscriber, requestor) 205 d = self.backend.subscribe(node_id, subscriber, requestor)
198 d.addCallback(self.return_subscription) 206 d.addCallback(self.return_subscription)
199 d.addCallback(self.succeed, iq) 207 return d
200 d.addErrback(self.error, iq)
201 d.addCallback(self.send)
202
203 def _onConfigureGet(self, iq):
204 raise NodeNotConfigurable
205
206 def _onConfigureSet(self, iq):
207 raise NodeNotConfigurable
208 208
209 def return_subscription(self, result): 209 def return_subscription(self, result):
210 reply = domish.Element("pubsub", NS_PUBSUB) 210 reply = domish.Element((NS_PUBSUB, "pubsub"), NS_PUBSUB)
211 entity = reply.addElement("entity") 211 entity = reply.addElement("entity")
212 entity["node"] = result["node"] 212 entity["node"] = result["node"]
213 entity["jid"] = result["jid"].full() 213 entity["jid"] = result["jid"].full()
214 entity["affiliation"] = result["affiliation"] 214 entity["affiliation"] = result["affiliation"]
215 entity["subscription"] = result["subscription"] 215 entity["subscription"] = result["subscription"]
216 return reply 216 return [reply]
217
218 def onUnsubscribe(self, iq):
219 self.handler_wrapper(self._onUnsubscribe, iq)
220
221 def _onUnsubscribe(self, iq):
222 node_id = iq.pubsub.unsubscribe["node"]
223 subscriber = jid.JID(iq.pubsub.unsubscribe["jid"])
224 requestor = jid.JID(iq["from"]).userhostJID()
225 return self.backend.unsubscribe(node_id, subscriber, requestor)
226
227 def onOptionsGet(self, iq):
228 self.handler_wrapper(self._onOptionsGet, iq)
229
230 def _onOptionsGet(self, iq):
231 raise OptionsUnavailable
232
233 def onOptionsSet(self, iq):
234 self.handler_wrapper(self._onOptionsSet, iq)
235
236 def _onOptionsSet(self, iq):
237 raise OptionsUnavailable
217 238
218 components.registerAdapter(ComponentServiceFromSubscriptionService, backend.ISubscriptionService, component.IService) 239 components.registerAdapter(ComponentServiceFromSubscriptionService, backend.ISubscriptionService, component.IService)
219 240
220 class ComponentServiceFromNodeCreationService(Service): 241 class ComponentServiceFromNodeCreationService(Service):
221 242
222 def componentConnected(self, xmlstream): 243 def componentConnected(self, xmlstream):
223 xmlstream.addObserver(PUBSUB_CREATE, self.onCreate) 244 xmlstream.addObserver(PUBSUB_CREATE, self.onCreate)
245 xmlstream.addObserver(PUBSUB_CONFIGURE_GET, self.onConfigureGet)
246 xmlstream.addObserver(PUBSUB_CONFIGURE_SET, self.onConfigureSet)
224 247
225 def onCreate(self, iq): 248 def onCreate(self, iq):
226 self.handler_wrapper(self._onCreate, iq) 249 self.handler_wrapper(self._onCreate, iq)
227 250
228 def _onCreate(self, iq): 251 def _onCreate(self, iq):
233 owner = jid.JID(iq["from"]).userhostJID() 256 owner = jid.JID(iq["from"]).userhostJID()
234 257
235 d = self.backend.create_node(node, owner) 258 d = self.backend.create_node(node, owner)
236 d.addCallback(self.return_create_response, iq) 259 d.addCallback(self.return_create_response, iq)
237 return d 260 return d
238
239 def _onOptionsGet(self, iq):
240 raise OptionsUnavailable
241
242 def _onOptionsSet(self, iq):
243 raise OptionsUnavailable
244 261
245 def return_create_response(self, result, iq): 262 def return_create_response(self, result, iq):
246 if iq.pubsub.create["node"] is None: 263 if iq.pubsub.create["node"] is None:
247 reply = domish.Element('pubsub', NS_PUBSUB) 264 reply = domish.Element('pubsub', NS_PUBSUB)
248 entity = reply.addElement('create') 265 entity = reply.addElement('create')
249 entity['node'] = result['node_id'] 266 entity['node'] = result['node_id']
250 return reply 267 return reply
251 268
269 def onConfigureGet(self, iq):
270 self.handler_wrapper(self._onConfigureGet, iq)
271
272 def _onConfigureGet(self, iq):
273 raise NodeNotConfigurable
274
275 def onConfigureSet(self, iq):
276 self.handler_wrapper(self._onConfigureSet, iq)
277
278 def _onConfigureSet(self, iq):
279 raise NodeNotConfigurable
280
252 components.registerAdapter(ComponentServiceFromNodeCreationService, backend.INodeCreationService, component.IService) 281 components.registerAdapter(ComponentServiceFromNodeCreationService, backend.INodeCreationService, component.IService)