Changeset 68:2c6d1f895583 for wokkel/xmppim.py
- Timestamp:
- Jul 17, 2009, 3:19:40 PM (13 years ago)
- Branch:
- default
- Convert:
- svn:b33ecbfc-034c-dc11-8662-000475d9059e/trunk@186
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
wokkel/xmppim.py
r63 r68 1 1 # -*- test-case-name: wokkel.test.test_xmppim -*- 2 2 # 3 # Copyright (c) 2003-200 8Ralph Meijer3 # Copyright (c) 2003-2009 Ralph Meijer 4 4 # See LICENSE for details. 5 5 … … 17 17 18 18 from wokkel.compat import IQ 19 from wokkel.generic import ErrorStanza, Stanza 19 20 from wokkel.subprotocols import XMPPHandler 20 21 … … 114 115 def _onPresenceUnsubscribe(self, presence): 115 116 self.unsubscribeReceived(JID(presence["from"])) 117 116 118 117 119 def availableReceived(self, entity, show=None, statuses=None, priority=0): … … 246 248 """ 247 249 self.send(Presence(to=entity, type='unsubscribed')) 250 251 252 253 class BasePresence(Stanza): 254 """ 255 Stanza of kind presence. 256 """ 257 stanzaKind = 'presence' 258 259 260 261 class AvailabilityPresence(BasePresence): 262 """ 263 Presence. 264 265 This represents availability presence (as opposed to 266 L{SubscriptionPresence}). 267 268 @ivar available: The availability being communicated. 269 @type available: C{bool} 270 @ivar show: More specific availability. Can be one of C{'chat'}, C{'away'}, 271 C{'xa'}, C{'dnd'} or C{None}. 272 @type show: C{str} or C{NoneType} 273 @ivar statuses: Natural language texts to detail the (un)availability. 274 These are represented as a mapping from language code 275 (C{str} or C{None}) to the corresponding text (C{unicode}). 276 If the key is C{None}, the associated text is in the 277 default language. 278 @type statuses: C{dict} 279 @ivar priority: Priority level for this resource. Must be between -128 and 280 127. Defaults to 0. 281 @type priority: C{int} 282 """ 283 284 childParsers = {(None, 'show'): '_childParser_show', 285 (None, 'status'): '_childParser_status', 286 (None, 'priority'): '_childParser_priority'} 287 288 def __init__(self, recipient=None, sender=None, available=True, 289 show=None, status=None, statuses=None, priority=0): 290 BasePresence.__init__(self, recipient=recipient, sender=sender) 291 self.available = available 292 self.show = show 293 self.statuses = statuses or {} 294 if status: 295 self.statuses[None] = status 296 self.priority = priority 297 298 299 def _childParser_show(self, element): 300 show = unicode(element) 301 if show in ('chat', 'away', 'xa', 'dnd'): 302 self.show = show 303 304 305 def _childParser_status(self, element): 306 lang = element.getAttribute((NS_XML, 'lang'), None) 307 text = unicode(element) 308 self.statuses[lang] = text 309 310 311 def _childParser_priority(self, element): 312 try: 313 self.priority = int(unicode(element)) 314 except ValueError: 315 pass 316 317 318 def parseElement(self, element): 319 BasePresence.parseElement(self, element) 320 321 if self.stanzaType == 'unavailable': 322 self.available = False 323 324 325 def toElement(self): 326 if not self.available: 327 self.stanzaType = 'unavailable' 328 329 presence = BasePresence.toElement(self) 330 331 if self.available: 332 if self.show in ('chat', 'away', 'xa', 'dnd'): 333 presence.addElement('show', content=self.show) 334 if self.priority != 0: 335 presence.addElement('priority', content=unicode(self.priority)) 336 337 for lang, text in self.statuses.iteritems(): 338 status = presence.addElement('status', content=text) 339 if lang: 340 status[(NS_XML, 'lang')] = lang 341 342 return presence 343 344 345 346 class SubscriptionPresence(BasePresence): 347 """ 348 Presence subscription request or response. 349 350 This kind of presence is used to represent requests for presence 351 subscription and their replies. 352 353 Based on L{BasePresence} and {Stanza}, it just uses the L{stanzaType} 354 attribute to represent the type of subscription presence. This can be 355 one of C{'subscribe'}, C{'unsubscribe'}, C{'subscribed'} and 356 C{'unsubscribed'}. 357 """ 358 359 360 361 class ProbePresence(BasePresence): 362 """ 363 Presence probe request. 364 """ 365 366 stanzaType = 'probe' 367 368 369 370 class PresenceProtocol(XMPPHandler): 371 """ 372 XMPP Presence protocol. 373 374 @cvar presenceTypeParserMap: Maps presence stanza types to their respective 375 stanza parser classes (derived from L{Stanza}). 376 @type presenceTypeParserMap: C{dict} 377 """ 378 379 presenceTypeParserMap = { 380 'error': ErrorStanza, 381 'available': AvailabilityPresence, 382 'unavailable': AvailabilityPresence, 383 'subscribe': SubscriptionPresence, 384 'unsubscribe': SubscriptionPresence, 385 'subscribed': SubscriptionPresence, 386 'unsubscribed': SubscriptionPresence, 387 'probe': ProbePresence, 388 } 389 390 def connectionInitialized(self): 391 self.xmlstream.addObserver("/presence", self._onPresence) 392 393 394 def _onPresence(self, element): 395 stanza = Stanza.fromElement(element) 396 397 presenceType = stanza.stanzaType or 'available' 398 399 try: 400 parser = self.presenceTypeParserMap[presenceType] 401 except KeyError: 402 return 403 404 presence = parser.fromElement(element) 405 406 try: 407 handler = getattr(self, '%sReceived' % presenceType) 408 except AttributeError: 409 return 410 else: 411 handler(presence) 412 413 414 def errorReceived(self, presence): 415 """ 416 Error presence was received. 417 """ 418 pass 419 420 421 def availableReceived(self, presence): 422 """ 423 Available presence was received. 424 """ 425 pass 426 427 428 def unavailableReceived(self, presence): 429 """ 430 Unavailable presence was received. 431 """ 432 pass 433 434 435 def subscribedReceived(self, presence): 436 """ 437 Subscription approval confirmation was received. 438 """ 439 pass 440 441 442 def unsubscribedReceived(self, presence): 443 """ 444 Unsubscription confirmation was received. 445 """ 446 pass 447 448 449 def subscribeReceived(self, presence): 450 """ 451 Subscription request was received. 452 """ 453 pass 454 455 456 def unsubscribeReceived(self, presence): 457 """ 458 Unsubscription request was received. 459 """ 460 pass 461 462 463 def probeReceived(self, presence): 464 """ 465 Probe presence was received. 466 """ 467 pass 468 469 470 def available(self, recipient=None, show=None, statuses=None, priority=0, 471 status=None, sender=None): 472 """ 473 Send available presence. 474 475 @param recipient: Optional Recipient to which the presence should be 476 sent. 477 @type recipient: {JID} 478 479 @param show: Optional detailed presence information. One of C{'away'}, 480 C{'xa'}, C{'chat'}, C{'dnd'}. 481 @type show: C{str} 482 483 @param statuses: Mapping of natural language descriptions of the 484 availability status, keyed by the language descriptor. A status 485 without a language specified, is keyed with C{None}. 486 @type statuses: C{dict} 487 488 @param priority: priority level of the resource. 489 @type priority: C{int} 490 """ 491 presence = AvailabilityPresence(recipient=recipient, sender=sender, 492 show=show, statuses=statuses, 493 status=status, priority=priority) 494 self.send(presence.toElement()) 495 496 497 def unavailable(self, recipient=None, statuses=None, sender=None): 498 """ 499 Send unavailable presence. 500 501 @param recipient: Optional entity to which the presence should be sent. 502 @type recipient: {JID} 503 504 @param statuses: dictionary of natural language descriptions of the 505 availability status, keyed by the language descriptor. A status 506 without a language specified, is keyed with C{None}. 507 @type statuses: C{dict} 508 """ 509 presence = AvailabilityPresence(recipient=recipient, sender=sender, 510 available=False, statuses=statuses) 511 self.send(presence.toElement()) 512 513 514 def subscribe(self, recipient, sender=None): 515 """ 516 Send subscription request 517 518 @param recipient: Entity to subscribe to. 519 @type recipient: {JID} 520 """ 521 presence = SubscriptionPresence(recipient=recipient, sender=sender) 522 presence.stanzaType = 'subscribe' 523 self.send(presence.toElement()) 524 525 526 def unsubscribe(self, recipient, sender=None): 527 """ 528 Send unsubscription request 529 530 @param recipient: Entity to unsubscribe from. 531 @type recipient: {JID} 532 """ 533 presence = SubscriptionPresence(recipient=recipient, sender=sender) 534 presence.stanzaType = 'unsubscribe' 535 self.send(presence.toElement()) 536 537 538 def subscribed(self, recipient, sender=None): 539 """ 540 Send subscription confirmation. 541 542 @param recipient: Entity that subscribed. 543 @type recipient: {JID} 544 """ 545 presence = SubscriptionPresence(recipient=recipient, sender=sender) 546 presence.stanzaType = 'subscribed' 547 self.send(presence.toElement()) 548 549 550 def unsubscribed(self, recipient, sender=None): 551 """ 552 Send unsubscription confirmation. 553 554 @param recipient: Entity that unsubscribed. 555 @type recipient: {JID} 556 """ 557 presence = SubscriptionPresence(recipient=recipient, sender=sender) 558 presence.stanzaType = 'unsubscribed' 559 self.send(presence.toElement()) 560 561 562 def probe(self, recipient, sender=None): 563 """ 564 Send presence probe. 565 566 @param recipient: Entity to be probed. 567 @type recipient: {JID} 568 """ 569 presence = ProbePresence(recipient=recipient, sender=sender) 570 self.send(presence.toElement()) 571 248 572 249 573
Note: See TracChangeset
for help on using the changeset viewer.