text: #!/usr/bin/env python
  #
  # Copyright 2007 Google Inc.
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #     http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  #
  
  """XMPP webapp handler classes.
  
  This module provides handler classes for XMPP bots, including both basic
  messaging functionality and a command handler for commands such as "/foo bar"
  """
  
  
  
  import logging
  from google.appengine.api import xmpp
  from google.appengine.ext import webapp
  
  
  class BaseHandler(webapp.RequestHandler):
    """A webapp baseclass for XMPP handlers.
  
    Implements a straightforward message delivery pattern. When a message is
    received, message_received is called with a Message object that encapsulates
    the relevant details. Users can reply using the standard XMPP API, or the
    convenient .reply() method on the Message object.
    """
  
    def message_received(self, message):
      """Called when a message is sent to the XMPP bot.
  
      Args:
        message: Message: The message that was sent by the user.
      """
      raise NotImplementedError()
  
    def handle_exception(self, exception, debug_mode):
      """Called if this handler throws an exception during execution.
  
      Args:
        exception: the exception that was thrown
        debug_mode: True if the web application is running in debug mode
      """
      super(BaseHandler, self).handle_exception(exception, debug_mode)
      if self.xmpp_message:
        self.xmpp_message.reply('Oops. Something went wrong.')
  
    def post(self):
      try:
        self.xmpp_message = xmpp.Message(self.request.POST)
      except xmpp.InvalidMessageError, e:
        logging.error("Invalid XMPP request: Missing required field %s", e[0])
        return
      self.message_received(self.xmpp_message)
  
  
  class CommandHandlerMixin(object):
    """A command handler for XMPP bots.
  
    Implements a command handler pattern. XMPP messages are processed by calling
    message_received. Message objects handled by this class are annotated with
    'command' and 'arg' fields. On receipt of a message starting with a forward
    or backward slash, the handler calls a method named after the command - eg,
    if the user sends "/foo bar", the handler will call foo_command(message).
    If no handler method matches, unhandled_command is called. The default behaviour
    of unhandled_command is to send the message "Unknown command" back to
    the sender.
  
    If the user sends a message not prefixed with a slash,
    text_message(message) is called.
    """
  
    def unhandled_command(self, message):
      """Called when an unknown command is sent to the XMPP bot.
  
      Args:
        message: Message: The message that was sent by the user.
      """
      message.reply('Unknown command')
  
    def text_message(self, message):
      """Called when a message not prefixed by a /command is sent to the XMPP bot.
  
      Args:
        message: Message: The message that was sent by the user.
      """
      pass
  
    def message_received(self, message):
      """Called when a message is sent to the XMPP bot.
  
      Args:
        message: Message: The message that was sent by the user.
      """
      if message.command:
        handler_name = '%s_command' % (message.command,)
        handler = getattr(self, handler_name, None)
        if handler:
          handler(message)
        else:
          self.unhandled_command(message)
      else:
        self.text_message(message)
  
  
  class CommandHandler(CommandHandlerMixin, BaseHandler):
    """A webapp implementation of CommandHandlerMixin."""
    pass
  