commandsbot.py :  » Development » xmpp.py » xmpppy-0.5.0rc1 » doc » examples » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Development » xmpp.py 
xmpp.py » xmpppy 0.5.0rc1 » doc » examples » commandsbot.py
#!/usr/bin/python
""" The example of using xmpppy's Ad-Hoc Commands (JEP-0050) implementation.
"""
import xmpp
from xmpp.protocol import *

options = {
  'JID': 'circles@example.com',
  'Password': '********',
}

class TestCommand(xmpp.commands.Command_Handler_Prototype):
  """ Example class. You should read source if you wish to understate how it works. This one
      actually does some calculations."""
  name = 'testcommand'
  description = 'Circle calculations'
  def __init__(self, jid=''):
    """ Initialize some internals. Set the first request handler to self.calcTypeForm.
    """
    xmpp.commands.Command_Handler_Prototype.__init__(self,jid)
    self.initial = {
      'execute': self.initialForm
    }

  def initialForm(self, conn, request):
    """ Assign a session id and send the first form. """
    sessionid = self.getSessionID()
    self.sessions[sessionid] = {
      'jid':request.getFrom(),
      'data':{'type':None}
    }

    # simulate that the client sent sessionid, so calcTypeForm will be able
    # to continue
    request.getTag(name="command").setAttr('sessionid', sessionid)

    return self.calcTypeForm(conn, request)
      
  def calcTypeForm(self, conn, request):
    """ Send first form to the requesting user. """
    # get the session data
    sessionid = request.getTagAttr('command','sessionid')
    session = self.sessions[sessionid]

    # What to do when a user sends us a response? Note, that we should always
    # include 'execute', as it is a default action when requester does not send
    # exact action to do (should be set to the same as 'next' or 'complete' fields)
    session['actions'] = {
      'cancel': self.cancel,
      'next': self.calcTypeFormAccept,
      'execute': self.calcTypeFormAccept,
    }

    # The form to send
    calctypefield = xmpp.DataField(
      name='calctype',
      desc='Calculation Type',
      value=session['data']['type'],
      options=[
        ['Calculate the diameter of a circle','circlediameter'],
        ['Calculate the area of a circle','circlearea']
      ],
      typ='list-single',
      required=1)

    # We set label attribute... seems that the xmpppy.DataField cannot do that
    calctypefield.setAttr('label', 'Calculation Type')

    form = xmpp.DataForm(
      title='Select type of operation',
      data=[
        'Use the combobox to select the type of calculation you would like'\
        'to do, then click Next.',
        calctypefield])

    # Build a reply with the form
    reply = request.buildReply('result')
    replypayload = [
      xmpp.Node('actions',
        attrs={'execute':'next'},
        payload=[xmpp.Node('next')]),
      form]
    reply.addChild(
      name='command',
      namespace=NS_COMMANDS,
      attrs={
        'node':request.getTagAttr('command','node'),
        'sessionid':sessionid,
        'status':'executing'},
      payload=replypayload)
    self._owner.send(reply)  # Question: self._owner or conn?
    raise xmpp.NodeProcessed

  def calcTypeFormAccept(self, conn, request):
    """ Load the calcType form filled in by requester, then reply with
        the second form. """
    # get the session data
    sessionid = request.getTagAttr('command','sessionid')
    session = self.sessions[sessionid]

    # load the form
    node = request.getTag(name='command').getTag(name='x',namespace=NS_DATA)
    form = xmpp.DataForm(node=node)

    # retrieve the data
    session['data']['type'] = form.getField('calctype').getValue()

    # send second form
    return self.calcDataForm(conn, request)

  def calcDataForm(self, conn, request, notavalue=None):
    """ Send a form asking for diameter. """
    # get the session data
    sessionid = request.getTagAttr('command','sessionid')
    session = self.sessions[sessionid]

    # set the actions taken on requester's response
    session['actions'] = {
      'cancel': self.cancel,
      'prev': self.calcTypeForm,
      'next': self.calcDataFormAccept,
      'execute': self.calcDataFormAccept
    }

    # create a form
    radiusfield = xmpp.DataField(desc='Radius',name='radius',typ='text-single')
    radiusfield.setAttr('label', 'Radius')

    form = xmpp.DataForm(
      title = 'Enter the radius',
      data=[
        'Enter the radius of the circle (numbers only)',
        radiusfield])

    # build a reply stanza
    reply = request.buildReply('result')
    replypayload = [
      xmpp.Node('actions',
        attrs={'execute':'complete'},
        payload=[xmpp.Node('complete'),xmpp.Node('prev')]),
      form]

    if notavalue:
      replypayload.append(xmpp.Node('note',
        attrs={'type': 'warn'},
        payload=['You have to enter valid number.']))

    reply.addChild(
      name='command',
      namespace=NS_COMMANDS,
      attrs={
        'node':request.getTagAttr('command','node'),
        'sessionid':request.getTagAttr('command','sessionid'),
        'status':'executing'},
      payload=replypayload)

    self._owner.send(reply)
    raise xmpp.NodeProcessed

  def calcDataFormAccept(self, conn, request):
    """ Load the calcType form filled in by requester, then reply with the result. """
    # get the session data
    sessionid = request.getTagAttr('command','sessionid')
    session = self.sessions[sessionid]

    # load the form
    node = request.getTag(name='command').getTag(name='x',namespace=NS_DATA)
    form = xmpp.DataForm(node=node)

    # retrieve the data; if the entered value is not a number, return to second stage
    try:
      value = float(form.getField('radius').getValue())
    except:
      self.calcDataForm(conn, request, notavalue=True)

    # calculate the answer
    from math import pi
    if session['data']['type'] == 'circlearea':
      result = (value**2) * pi
    else:
      result = 2 * value * pi

    # build the result form
    form = xmpp.DataForm(
      typ='result',
      data=[xmpp.DataField(desc='result', name='result', value=result)])

    # build the reply stanza
    reply = request.buildReply('result')
    reply.addChild(
      name='command',
      namespace=NS_COMMANDS,
      attrs={
        'node':request.getTagAttr('command','node'),
        'sessionid':sessionid,
        'status':'completed'},
      payload=[form])

    self._owner.send(reply)

    # erase the data about session
    del self.sessions[sessionid]

    raise xmpp.NodeProcessed

  def cancel(self, conn, request):
    """ Requester canceled the session, send a short reply. """
    # get the session id
    sessionid = request.getTagAttr('command','sessionid')

    # send the reply
    reply = request.buildReply('result')
    reply.addChild(
      name='command',
      namespace=NS_COMMANDS,
      attrs={
        'node':request.getTagAttr('command','node'),
        'sessionid':sessionid,
        'status':'cancelled'})
    self._owner.send(reply)

    # erase the data about session
    del self.sessions[sessionid]

    raise xmpp.NodeProcessed

class ConnectionError: pass
class AuthorizationError: pass
class NotImplemented: pass

class Bot:
  """ The main bot class. """

  def __init__(self, JID, Password):
    """ Create a new bot. Connect to the server and log in. """

    # connect...
    jid = xmpp.JID(JID)
    self.connection = xmpp.Client(jid.getDomain(), debug=['always', 'browser', 'testcommand'])

    result = self.connection.connect()

    if result is None:
      raise ConnectionError

    # authorize
    result = self.connection.auth(jid.getNode(), Password)

    if result is None:
      raise AuthorizationError

    # plugins
    # disco - needed by commands

    # warning: case of "plugin" method names are important!
    # to attach a command to Commands class, use .plugin()
    # to attach anything to Client class, use .PlugIn()
    self.disco = xmpp.browser.Browser()
    self.disco.PlugIn(self.connection)
    self.disco.setDiscoHandler({
      'info': {
        'ids': [{
          'category': 'client',
          'type': 'pc',
          'name': 'Bot'
          }],
        'features': [NS_DISCO_INFO],
        }
      })

    self.commands = xmpp.commands.Commands(self.disco)
    self.commands.PlugIn(self.connection)

    self.command_test = TestCommand()
    self.command_test.plugin(self.commands)

    # presence
    self.connection.sendInitPresence(requestRoster=0)

  def loop(self):
    """ Do nothing except handling new xmpp stanzas. """
    try:
      while self.connection.Process(1):
        pass
    except KeyboardInterrupt:
      pass

bot = Bot(**options)
bot.loop()
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.