Changeset 2:47f1cb624f14 for wokkel/pubsub.py
- Timestamp:
- Aug 22, 2007, 3:43:43 PM (15 years ago)
- Branch:
- default
- Convert:
- svn:b33ecbfc-034c-dc11-8662-000475d9059e/trunk@3
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
wokkel/pubsub.py
r1 r2 14 14 15 15 from twisted.internet import defer 16 from twisted.words.protocols.jabber import jid, error 16 from twisted.words.protocols.jabber import jid, error, xmlstream 17 17 from twisted.words.xish import domish 18 18 19 19 from wokkel import disco, data_form 20 20 from wokkel.subprotocols import IQHandlerMixin, XMPPHandler 21 from wokkel.iwokkel import IPubSub Service21 from wokkel.iwokkel import IPubSubClient, IPubSubService 22 22 23 23 # Iq get and set XPath queries … … 71 71 72 72 class BadRequest(error.StanzaError): 73 """ 74 Bad request stanza error. 75 """ 73 76 def __init__(self): 74 77 error.StanzaError.__init__(self, 'bad-request') 75 78 79 80 81 class SubscriptionPending(Exception): 82 """ 83 Raised when the requested subscription is pending acceptance. 84 """ 85 86 87 class SubscriptionUnconfigured(Exception): 88 """ 89 Raised when the requested subscription needs to be configured before 90 becoming active. 91 """ 92 93 76 94 class PubSubError(error.StanzaError): 95 """ 96 Exception with publish-subscribe specific condition. 97 """ 77 98 def __init__(self, condition, pubsubCondition, feature=None, text=None): 78 99 appCondition = domish.Element((NS_PUBSUB_ERRORS, pubsubCondition)) … … 83 104 appCondition=appCondition) 84 105 106 85 107 class Unsupported(PubSubError): 86 108 def __init__(self, feature, text=None): … … 90 112 text) 91 113 114 92 115 class OptionsUnavailable(Unsupported): 93 116 def __init__(self): 94 117 Unsupported.__init__(self, 'subscription-options-unavailable') 118 119 120 class Item(domish.Element): 121 """ 122 Publish subscribe item. 123 124 This behaves like an object providing L{domish.IElement}. 125 126 Item payload can be added using C{addChild} or C{addRawXml}, or using the 127 C{payload} keyword argument to C{__init__}. 128 """ 129 130 def __init__(self, id=None, payload=None): 131 """ 132 @param id: optional item identifier 133 @type id: L{unicode} 134 @param payload: optional item payload. Either as a domish element, or 135 as serialized XML. 136 @type payload: object providing L{domish.IElement} or L{unicode}. 137 """ 138 139 domish.Element.__init__(self, (None, 'item')) 140 if id is not None: 141 self['id'] = id 142 if payload is not None: 143 if isinstance(payload, basestring): 144 self.addRawXml(payload) 145 else: 146 self.addChild(payload) 147 148 class PubSubRequest(xmlstream.IQ): 149 """ 150 Base class for publish subscribe user requests. 151 152 @cvar namespace: request namespace 153 @cvar verb: request verb 154 @cvar method: type attribute of the IQ request. Either C{'set'} or C{'get'} 155 @ivar command: command element of the request. This is the direct child of 156 the C{pubsub} element in the C{namespace} with the name 157 C{verb}. 158 """ 159 160 namespace = NS_PUBSUB 161 method = 'set' 162 163 def __init__(self, xs): 164 xmlstream.IQ.__init__(self, xs, self.method) 165 self.addElement((self.namespace, 'pubsub')) 166 167 self.command = self.pubsub.addElement(self.verb) 168 169 def send(self, to): 170 destination = unicode(to) 171 return xmlstream.IQ.send(self, destination) 172 173 class CreateNode(PubSubRequest): 174 verb = 'create' 175 176 def __init__(self, xs, node=None): 177 PubSubRequest.__init__(self, xs) 178 if node: 179 self.command["node"] = node 180 181 class DeleteNode(PubSubRequest): 182 verb = 'delete' 183 def __init__(self, xs, node): 184 PubSubRequest.__init__(self, xs) 185 self.command["node"] = node 186 187 class Subscribe(PubSubRequest): 188 verb = 'subscribe' 189 190 def __init__(self, xs, node, subscriber): 191 PubSubRequest.__init__(self, xs) 192 self.command["node"] = node 193 self.command["jid"] = subscriber.full() 194 195 class Publish(PubSubRequest): 196 verb = 'publish' 197 198 def __init__(self, xs, node): 199 PubSubRequest.__init__(self, xs) 200 self.command["node"] = node 201 202 def addItem(self, id=None, payload=None): 203 item = self.command.addElement("item") 204 item.addChild(payload) 205 206 if id is not None: 207 item["id"] = id 208 209 return item 210 211 class PubSubClient(XMPPHandler): 212 """ 213 Publish subscribe client protocol. 214 """ 215 216 implements(IPubSubClient) 217 218 def connectionInitialized(self): 219 self.xmlstream.addObserver('/message/event[@xmlns="%s"]/items' % 220 NS_PUBSUB_EVENT, self._onItems) 221 222 def _onItems(self, message): 223 try: 224 notifier = jid.JID(message["from"]) 225 node = message.event.items["node"] 226 except KeyError: 227 return 228 229 items = [element for element in message.event.items.elements() 230 if element.name == 'item'] 231 232 self.itemsReceived(notifier, node, items) 233 234 def itemsReceived(self, notifier, node, items): 235 pass 236 237 def createNode(self, service, node=None): 238 request = CreateNode(self.xmlstream, node) 239 240 def cb(iq): 241 try: 242 new_node = iq.pubsub.create["node"] 243 except AttributeError: 244 # the suggested node identifier was accepted 245 new_node = node 246 return new_node 247 248 return request.send(service).addCallback(cb) 249 250 def deleteNode(self, service, node): 251 return DeleteNode(self.xmlstream, node).send(service) 252 253 def subscribe(self, service, node, subscriber): 254 request = Subscribe(self.xmlstream, node, subscriber) 255 256 def cb(iq): 257 subscription = iq.pubsub.subscription["subscription"] 258 259 if subscription == 'pending': 260 raise SubscriptionPending 261 elif subscription == 'unconfigured': 262 raise SubscriptionUnconfigured 263 else: 264 # we assume subscription == 'subscribed' 265 # any other value would be invalid, but that should have 266 # yielded a stanza error. 267 return None 268 269 return request.send(service).addCallback(cb) 270 271 def publish(self, service, node, items=[]): 272 request = Publish(self.xmlstream, node) 273 for item in items: 274 request.command.addChild(item) 275 276 return request.send(service) 95 277 96 278 class PubSubService(XMPPHandler, IQHandlerMixin): … … 215 397 216 398 items = [] 217 for child in iq.pubsub.publish.children:218 if child.__class__ == domish.Element and child.name == 'item':219 items.append( child)399 for element in iq.pubsub.publish.elements(): 400 if element.uri == NS_PUBSUB and element.name == 'item': 401 items.append(element) 220 402 221 403 return self.publish(requestor, nodeIdentifier, items)
Note: See TracChangeset
for help on using the changeset viewer.