Writing plugins

Omnipresence supports two different types of plugins:

  • Handler plugins listen for and respond to general events.
  • Command plugins are more specialized variants of handler plugins that only respond when a specific keyword is sent to the bot in a message. In IRC channels, a command prefix is also expected. Both of these are specified in the bot configuration.

Plugins are expected to be module-level variables in submodules of the package omnipresence.plugins. Twisted’s plugin documentation has further details. In practice, this means that you will write a plugin class that implements the provided interfaces, and assign an instance of that class to a variable in your plugin module:

# omnipresence/plugins/example.py
from twisted.plugin import IPlugin
from omnipresence.iomnipresence import ICommand


class ExampleCommand(object):
    implements(IPlugin, ICommand)
    name = 'example'

    def execute(self, bot, prefix, reply_target, channel, args):
        # ... command performs its work ...
        bot.reply(reply_target, channel, text)


# Don't forget to do this at the end of your module file, or Omnipresence
# will not load your command plugin!
example = ExampleCommand()

Handler plugins

Handler plugins are expected to implement both twisted.plugin.IPlugin and IHandler.

interface omnipresence.iomnipresence.IHandler[source]

A handler that responds to IRC events passed to it by the bot. There are no required methods for this interface, since handlers may implement only a subset of available events. Callbacks are generally the same as those defined in omnipresence.IRCClient, except that an instance of the bot protocol class is provided as the second argument (after self).

registered()

An optional callback, fired when the plugin is initialized. At this point, an omnipresence.IRCClientFactory object has been assigned to the self.factory object attribute, which can be used to read configuration data (through config).

name

The name used to refer to this handler in the configuration file, among other places.

Command plugins

Handler plugins are expected to implement both twisted.plugin.IPlugin and ICommand.

interface omnipresence.iomnipresence.ICommand[source]

A command that is invoked in response to specially-formatted IRC messages.

The docstring is used to provide documentation for the help command plugin, with %s standing in for the keyword assigned by the bot’s configuration. Generally, command docstrings take the form of a brief usage note, with the following formatting:

  • Text to be typed literally by the user, including the command keyword, is presented in boldface, through wrapping with the IRC format code \x02.
  • Variable names are presented with an underline, through wrapping with the IRC format code \x1F.
  • Optional arguments are surrounded by unformatted square brackets.
  • Choices among mutually-exclusive arguments are separated with vertical pipes.

For example:

class SampleCommand(object):
    '''
    \x02%s\x02
    \x1Fa\x1F|\x1Fb\x1F|\x1Fc\x1F
    [\x1Foptional_argument\x1F] -
    Provides an example within documentation.
    '''

This would be presented to a typical IRC client as follows, assuming that the command keyword sample has been assigned:

sample a | b | c [optional_argument] - Provides an example within documentation.
registered()

See IHandler.registered().

execute(self, bot, prefix, reply_target, channel, args)

Invoked when a command message is seen.

Parameters:
  • bot (omnipresence.IRCClient) – The current bot protocol instance.
  • prefix (str) – The nick@user!host prefix of the user that invoked this command.
  • reply_target (str) – The target of command output redirection suggested by the invoking user with > target, or prefix if no such redirection is specified. This is not necessarily a valid prefix or nickname, as it is given by the user!
  • channel (str) – The channel on which the command was invoked. For private messages, this is generally the bot’s own nickname.
  • args (str) – The arguments passed with the command, including the keyword used to invoke the command ("keyword arg1 arg2").

Generally, a command’s execute() method should either call the bot’s reply() method and (implicitly) return None; or create a Twisted Deferred object, add a callback that calls reply(), and return that Deferred (see Using Deferreds). An error handler will be automatically added that replies with the associated value of any exceptions that are not handled by the command itself.

Most command plugins shipped with Omnipresence send error or “no-result” replies to prefix, giving the invoking user a chance to correct any potential mistakes, while successful replies are sent to reply_target:

def execute(self, bot, prefix, reply_target, channel, args):
    results = do_something(args)

    if not results:
        bot.reply(prefix, channel, 'No results found.')
        return

    bot.reply(reply_target, channel, results[0])
name

The name used to refer to this command in the configuration file, among other places.

Web-based commands

Omnipresence provides a convenience class for commands that rely on making an HTTP request and parsing the response, WebCommand. See the class documentation for more details.

Using Deferreds

Command and handler plugins that need to perform actions that would otherwise block the main thread should use Twisted’s deferred execution mechanism to make the blocking call asynchronously. Omnipresence automatically adds an errback to any Deferred objects returned by a command plugin’s execute() method, so that any unhandled errors encountered during the command’s execution can be reported to the user.