Skip to content
Kagami edited this page Feb 2, 2012 · 10 revisions

Documentation is not yet complete. Sorry for that.

shitsu uses class-based API. Each shitsu's module lays in python's module file. It could be many shitsu's modules in one module file.

Load

At the start load module seeks modules in several places and tries to load them via modprobe.
These places are:

  • /usr/lib/python2.6/dist-packages/shitsu/modules/ (this may differ on your OS)
  • $HOME/.shitsu/modules/

If you run shitsu via run_without_install.py:

  • /path/to/shitsu/shitsu/modules/

To add new module you should put it under some of this places.
shitsu can add/reload your modules on the fly: use command-line -r option or %load/%modprobe <module_file> bot commands.
You could even bootstrap load and modprobe - them implemented as common modules.

MessageModule

Base class for message modules (source). All bots commands implemented through inheritance of this class.
It's definition look like this:

class MessageModule(BaseModule):
    """Base class for message modules."""

    use_prefix = True # Is command should be prefixed.
    acl = ACL_NONE # Minimum access level required to use command.
    regexp = None # Command regexp (if not specified match by name).
    types = ("chat", "groupchat") # Process messages only with
                                   # specified types.
    allow_conf_private = True # Allow or not module use in private
                               # conference chats.
    raw_query = False # If true module will get raw query string.
    args = () # List of correct arguments number. (1, 3) means 1 or 3.
               # Empty list means any number.
    highlight = True # Highlight users in groupchats with command's result.
    additional_args = False # Send to module some additional args such as
                             # original stanza and user acl.
    thread_safe = True # Is module thread-safe and can be run multiple
                        # times in parallel or not.

    def run(self, *args, **kwargs):
        """Main module function.
        Get:
        - match.groups() if module's regexp specified
        - splitted list of arguments otherwise
        See also module's additional options.
        Return:
        - string on simple result
        - tuple of 2 strings as result body and xhtml body
        - empty string if nothing should be sent back to user
        - None on invalid syntax
        Note that if result string has non-ascii symbols it MUST
        be unicode string. Input args conform the same rule.
        """

Of course you don't need specify all this options each time.

Let's consider the simplest example, date module. It goes like this:

from shitsu import modules
import datetime


class Date(modules.MessageModule):

    args = (0,)

    def run(self):
        """
        Show current date and time.
        """
        return datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

You just specify that it should be zero arguments and return current date. This module will be loaded at startup and called each time you send %date command to bot. This is just prefix (see config) + lower-cased class name. If you want shorted or unicode command names - just use aliases.

OK, next example is man command.

class Man(modules.MessageModule):

    args = (0, 1, 2)
    additional_args = True

    def run(self, *args, **kwargs):
        """[[-v] command]
        Show command's manual page.
        If verbose flag specified show acl info.
        See also: help
        """
        if not args:
            return "What manual page do you want?"
        elif len(args) == 1:
            command = args[0]
            verbose = False
        elif args[0] == "-v":
            command = args[1]
            verbose = True
        else:
            return

        not_found = "No manual entry for " + command
        for module in self._bot.modules.values():
            if module.name == command:
                man = module.run.__doc__
                if (isinstance(module, modules.MessageModule) and man and
                    module.regexp is None):
                        man = utils.trim(command + " " + man)
                        if verbose:
                            user_acl = kwargs["add"]["user_acl"]
                            man = ("%s\n\nMinimum access level required: %s\n"
                                   "Your access level: %s" % (
                                        man, module.acl, user_acl))
                        return man
                else:
                        return not_found
        return not_found

man is famous program from UNIX world which shows you (obviously) specified manual. This module emulates it's behavior and show module's documentation string if available.
New option is additional_args - you ask to grant you some additional arguments - user access level, original stanza and so on. We will have a look at ACL in the next section.

And the last example is vcard module. It's a bit advanced - we use asynchronous callback to process data when it will come and self.send_message to send it back to user because our run function has nothing to return.

See also: urltitle (regexp usage), join (config usage), nmap (some additional options).
Also most default modules meant to be self-documented.

ACL

Access level API (source).
Current levels:

  • ACL_OWNER - owner (obtained only in private chat with bot)
  • ACL_NONE - any other user

ConnectModule, DisconnectModule

Modules which will be started just after bot's connect/before disconnect.
Examples: JoinConfs, LeaveConfs.

BaseModule

Base module class (source).
At init sets some useful module-wide properties:

  • self._bot - bot instance
  • self.cfg - module file's config section (based on the filename; for modules/confs.py it will be [conf])

Config

Sandbox